Răsfoiți Sursa

Added tinystl.

bkaradzic 12 ani în urmă
părinte
comite
2be64b6874
100 a modificat fișierele cu 9495 adăugiri și 0 ștergeri
  1. 20 0
      3rdparty/UnitTest++/COPYING
  2. 96 0
      3rdparty/UnitTest++/Makefile
  3. 68 0
      3rdparty/UnitTest++/README
  4. 174 0
      3rdparty/UnitTest++/TestUnitTest++.vsnet2003.vcproj
  5. 256 0
      3rdparty/UnitTest++/TestUnitTest++.vsnet2005.vcproj
  6. 169 0
      3rdparty/UnitTest++/TestUnitTestPP_vs6.dsp
  7. 30 0
      3rdparty/UnitTest++/UnitTest++.vsnet2003.sln
  8. 226 0
      3rdparty/UnitTest++/UnitTest++.vsnet2003.vcproj
  9. 29 0
      3rdparty/UnitTest++/UnitTest++.vsnet2005.sln
  10. 318 0
      3rdparty/UnitTest++/UnitTest++.vsnet2005.vcproj
  11. 260 0
      3rdparty/UnitTest++/UnitTestPP_vs6.dsp
  12. 44 0
      3rdparty/UnitTest++/UnitTestPP_vs6.dsw
  13. 260 0
      3rdparty/UnitTest++/docs/UnitTest++.html
  14. 34 0
      3rdparty/UnitTest++/src/AssertException.cpp
  15. 28 0
      3rdparty/UnitTest++/src/AssertException.h
  16. 122 0
      3rdparty/UnitTest++/src/CheckMacros.h
  17. 50 0
      3rdparty/UnitTest++/src/Checks.cpp
  18. 158 0
      3rdparty/UnitTest++/src/Checks.h
  19. 31 0
      3rdparty/UnitTest++/src/Config.h
  20. 18 0
      3rdparty/UnitTest++/src/CurrentTest.cpp
  21. 17 0
      3rdparty/UnitTest++/src/CurrentTest.h
  22. 28 0
      3rdparty/UnitTest++/src/DeferredTestReporter.cpp
  23. 29 0
      3rdparty/UnitTest++/src/DeferredTestReporter.h
  24. 29 0
      3rdparty/UnitTest++/src/DeferredTestResult.cpp
  25. 32 0
      3rdparty/UnitTest++/src/DeferredTestResult.h
  26. 46 0
      3rdparty/UnitTest++/src/ExecuteTest.h
  27. 149 0
      3rdparty/UnitTest++/src/MemoryOutStream.cpp
  28. 68 0
      3rdparty/UnitTest++/src/MemoryOutStream.h
  29. 46 0
      3rdparty/UnitTest++/src/Posix/SignalTranslator.cpp
  30. 42 0
      3rdparty/UnitTest++/src/Posix/SignalTranslator.h
  31. 33 0
      3rdparty/UnitTest++/src/Posix/TimeHelpers.cpp
  32. 28 0
      3rdparty/UnitTest++/src/Posix/TimeHelpers.h
  33. 11 0
      3rdparty/UnitTest++/src/ReportAssert.cpp
  34. 10 0
      3rdparty/UnitTest++/src/ReportAssert.h
  35. 41 0
      3rdparty/UnitTest++/src/Test.cpp
  36. 34 0
      3rdparty/UnitTest++/src/Test.h
  37. 22 0
      3rdparty/UnitTest++/src/TestDetails.cpp
  38. 24 0
      3rdparty/UnitTest++/src/TestDetails.h
  39. 39 0
      3rdparty/UnitTest++/src/TestList.cpp
  40. 32 0
      3rdparty/UnitTest++/src/TestList.h
  41. 113 0
      3rdparty/UnitTest++/src/TestMacros.h
  42. 10 0
      3rdparty/UnitTest++/src/TestReporter.cpp
  43. 20 0
      3rdparty/UnitTest++/src/TestReporter.h
  44. 46 0
      3rdparty/UnitTest++/src/TestReporterStdout.cpp
  45. 19 0
      3rdparty/UnitTest++/src/TestReporterStdout.h
  46. 60 0
      3rdparty/UnitTest++/src/TestResults.cpp
  47. 36 0
      3rdparty/UnitTest++/src/TestResults.h
  48. 76 0
      3rdparty/UnitTest++/src/TestRunner.cpp
  49. 59 0
      3rdparty/UnitTest++/src/TestRunner.h
  50. 12 0
      3rdparty/UnitTest++/src/TestSuite.h
  51. 29 0
      3rdparty/UnitTest++/src/TimeConstraint.cpp
  52. 33 0
      3rdparty/UnitTest++/src/TimeConstraint.h
  53. 7 0
      3rdparty/UnitTest++/src/TimeHelpers.h
  54. 18 0
      3rdparty/UnitTest++/src/UnitTest++.h
  55. 47 0
      3rdparty/UnitTest++/src/Win32/TimeHelpers.cpp
  56. 48 0
      3rdparty/UnitTest++/src/Win32/TimeHelpers.h
  57. 127 0
      3rdparty/UnitTest++/src/XmlTestReporter.cpp
  58. 34 0
      3rdparty/UnitTest++/src/XmlTestReporter.h
  59. 8 0
      3rdparty/UnitTest++/src/tests/Main.cpp
  60. 98 0
      3rdparty/UnitTest++/src/tests/RecordingReporter.h
  61. 37 0
      3rdparty/UnitTest++/src/tests/ScopedCurrentTest.h
  62. 44 0
      3rdparty/UnitTest++/src/tests/TestAssertHandler.cpp
  63. 801 0
      3rdparty/UnitTest++/src/tests/TestCheckMacros.cpp
  64. 293 0
      3rdparty/UnitTest++/src/tests/TestChecks.cpp
  65. 38 0
      3rdparty/UnitTest++/src/tests/TestCurrentTest.cpp
  66. 117 0
      3rdparty/UnitTest++/src/tests/TestDeferredTestReporter.cpp
  67. 151 0
      3rdparty/UnitTest++/src/tests/TestMemoryOutStream.cpp
  68. 129 0
      3rdparty/UnitTest++/src/tests/TestTest.cpp
  69. 50 0
      3rdparty/UnitTest++/src/tests/TestTestList.cpp
  70. 212 0
      3rdparty/UnitTest++/src/tests/TestTestMacros.cpp
  71. 111 0
      3rdparty/UnitTest++/src/tests/TestTestResults.cpp
  72. 307 0
      3rdparty/UnitTest++/src/tests/TestTestRunner.cpp
  73. 12 0
      3rdparty/UnitTest++/src/tests/TestTestSuite.cpp
  74. 69 0
      3rdparty/UnitTest++/src/tests/TestTimeConstraint.cpp
  75. 65 0
      3rdparty/UnitTest++/src/tests/TestTimeConstraintMacro.cpp
  76. 156 0
      3rdparty/UnitTest++/src/tests/TestUnitTest++.cpp
  77. 183 0
      3rdparty/UnitTest++/src/tests/TestXmlTestReporter.cpp
  78. 2 0
      LICENSE
  79. 23 0
      include/tinystl/LICENSE
  80. 49 0
      include/tinystl/allocator.h
  81. 212 0
      include/tinystl/buffer.h
  82. 53 0
      include/tinystl/hash.h
  83. 225 0
      include/tinystl/hash_base.h
  84. 43 0
      include/tinystl/new.h
  85. 40 0
      include/tinystl/stddef.h
  86. 212 0
      include/tinystl/string.h
  87. 85 0
      include/tinystl/traits.h
  88. 241 0
      include/tinystl/unordered_map.h
  89. 216 0
      include/tinystl/unordered_set.h
  90. 268 0
      include/tinystl/vector.h
  91. 57 0
      makefile
  92. 5 0
      premake/bx.lua
  93. 54 0
      premake/premake4.lua
  94. 45 0
      premake/unittest++.lua
  95. 31 0
      test/main.cpp
  96. 16 0
      test/test.h
  97. 263 0
      test/vector_complex.cpp
  98. 28 0
      test/vector_header.cpp
  99. 259 0
      test/vector_nodefault.cpp
  100. 242 0
      test/vector_primitive.cpp

+ 20 - 0
3rdparty/UnitTest++/COPYING

@@ -0,0 +1,20 @@
+Copyright (c) 2006 Noel Llopis and Charles Nicholson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 96 - 0
3rdparty/UnitTest++/Makefile

@@ -0,0 +1,96 @@
+CXX = g++
+CXXFLAGS ?= -g -Wall -W -Winline -ansi 
+LDFLAGS ?= 
+SED = sed
+MV = mv
+RM = rm
+
+.SUFFIXES: .o .cpp
+
+lib = libUnitTest++.a
+test = TestUnitTest++
+
+src = src/AssertException.cpp \
+	src/Test.cpp \
+	src/Checks.cpp \
+	src/TestRunner.cpp \
+	src/TestResults.cpp \
+	src/TestReporter.cpp \
+	src/TestReporterStdout.cpp \
+	src/ReportAssert.cpp \
+	src/TestList.cpp \
+	src/TimeConstraint.cpp \
+	src/TestDetails.cpp \
+	src/MemoryOutStream.cpp \
+	src/DeferredTestReporter.cpp \
+	src/DeferredTestResult.cpp \
+	src/XmlTestReporter.cpp \
+	src/CurrentTest.cpp
+	
+ifeq ($(MSYSTEM), MINGW32)
+  src += src/Win32/TimeHelpers.cpp
+else
+  src += src/Posix/SignalTranslator.cpp \
+	src/Posix/TimeHelpers.cpp
+endif
+
+test_src = src/tests/Main.cpp \
+	src/tests/TestAssertHandler.cpp \
+	src/tests/TestChecks.cpp \
+	src/tests/TestUnitTest++.cpp \
+	src/tests/TestTest.cpp \
+	src/tests/TestTestResults.cpp \
+	src/tests/TestTestRunner.cpp \
+	src/tests/TestCheckMacros.cpp \
+	src/tests/TestTestList.cpp \
+	src/tests/TestTestMacros.cpp \
+	src/tests/TestTimeConstraint.cpp \
+	src/tests/TestTimeConstraintMacro.cpp \
+	src/tests/TestMemoryOutStream.cpp \
+	src/tests/TestDeferredTestReporter.cpp \
+	src/tests/TestXmlTestReporter.cpp \
+	src/tests/TestCurrentTest.cpp
+
+objects = $(patsubst %.cpp, %.o, $(src))
+test_objects = $(patsubst %.cpp, %.o, $(test_src))
+dependencies = $(subst .o,.d,$(objects))
+test_dependencies = $(subst .o,.d,$(test_objects))
+
+define make-depend
+  $(CXX) $(CXXFLAGS) -M $1 | \
+  $(SED) -e 's,\($(notdir $2)\) *:,$(dir $2)\1: ,' > $3.tmp
+  $(SED) -e 's/#.*//' \
+      -e 's/^[^:]*: *//' \
+      -e 's/ *\\$$//' \
+      -e '/^$$/ d' \
+      -e 's/$$/ :/' $3.tmp >> $3.tmp
+  $(MV) $3.tmp $3
+endef
+
+
+all: $(test)
+
+
+$(lib): $(objects) 
+	@echo Creating $(lib) library...
+	@ar cr $(lib) $(objects)
+    
+$(test): $(lib) $(test_objects)
+	@echo Linking $(test)...
+	@$(CXX) $(LDFLAGS) -o $(test) $(test_objects) $(lib)
+	@echo Running unit tests...
+	@./$(test)
+
+clean:
+	-@$(RM) $(objects) $(test_objects) $(dependencies) $(test_dependencies) $(test) $(lib) 2> /dev/null
+
+%.o : %.cpp
+	@echo $<
+	@$(call make-depend,$<,$@,$(subst .o,.d,$@))
+	@$(CXX) $(CXXFLAGS) -c $< -o $(patsubst %.cpp, %.o, $<)
+
+
+ifneq "$(MAKECMDGOALS)" "clean"
+-include $(dependencies)
+-include $(test_dependencies)
+endif

+ 68 - 0
3rdparty/UnitTest++/README

@@ -0,0 +1,68 @@
+UnitTest++ README
+Version: v1.4
+Last update: 2008-10-30
+
+UnitTest++ is free software. You may copy, distribute, and modify it under
+the terms of the License contained in the file COPYING distributed
+with this package. This license is the same as the MIT/X Consortium
+license.
+
+See src/tests/TestUnitTest++.cpp for usage.
+
+Authors:
+Noel Llopis ([email protected]) 
+Charles Nicholson ([email protected])
+
+Contributors:
+Jim Tilander
+Kim Grasman
+Jonathan Jansson
+Dirck Blaskey
+Rory Driscoll
+Dan Lind
+Matt Kimmel -- Submitted with permission from Blue Fang Games
+Anthony Moralez
+Jeff Dixon
+Randy Coulman
+Lieven van der Heide
+
+Release notes:
+--------------
+Version 1.4 (2008-10-30)
+- CHECK macros work at arbitrary stack depth from inside TESTs.
+- Remove obsolete TEST_UTILITY macros
+- Predicated test execution (via TestRunner::RunTestsIf)
+- Better exception handling for fixture ctors/dtors.
+- VC6/7/8/9 support
+
+Version 1.3 (2007-4-22)
+- Removed dynamic memory allocations (other than streams)
+- MinGW support
+- Consistent (native) line endings
+- Minor bug fixing
+
+Version 1.2 (2006-10-29)
+- First pass at documentation.
+- More detailed error crash catching in fixtures.
+- Standard streams used for printing objects under check. This should allow the
+  use of standard class types such as std::string or other custom classes with
+  stream operators to ostream.
+- Standard streams can be optionally compiled off by defining UNITTEST_USE_CUSTOM_STREAMS
+  in Config.h
+- Added named test suites
+- Added CHECK_ARRAY2D_CLOSE 
+- Posix library name is libUnitTest++.a now
+- Floating point numbers are postfixed with f in the failure reports
+
+Version 1.1 (2006-04-18)
+- CHECK macros do not have side effects even if one of the parameters changes state
+- Removed CHECK_ARRAY_EQUAL (too similar to CHECK_ARRAY_CLOSE)
+- Added local and global time constraints
+- Removed dependencies on strstream
+- Improved Posix signal to exception translator
+- Failing tests are added to Visual Studio's error list
+- Fixed Visual Studio projects to work with spaces in directories
+
+Version 1.0 (2006-03-15)
+- Initial release
+

+ 174 - 0
3rdparty/UnitTest++/TestUnitTest++.vsnet2003.vcproj

@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="TestUnitTest++.vsnet2003"
+	ProjectGUID="{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/TestUnitTest++.vsnet2003.exe"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/TestUnitTest++.vsnet2003.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="&quot;$(TargetPath)&quot;"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="4"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/TestUnitTest++.vsnet2003.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="&quot;$(TargetPath)&quot;"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\src\tests\Main.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\RecordingReporter.h">
+		</File>
+        <File
+            RelativePath=".\src\tests\ScopedCurrentTest.h">
+        </File>
+        <File
+			RelativePath=".\src\tests\TestAssertHandler.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestCheckMacros.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestChecks.cpp">
+		</File>
+        <File
+            RelativePath=".\src\tests\TestCurrentTest.cpp">
+        </File>
+        <File
+            RelativePath=".\src\tests\TestDeferredTestReporter.cpp">
+        </File>
+		<File
+			RelativePath=".\src\tests\TestMemoryOutStream.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTest.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestList.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestMacros.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestResults.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestRunner.cpp">
+		</File>
+        <File
+            RelativePath=".\src\tests\TestTestSuite.cpp">
+        </File>
+		<File
+			RelativePath=".\src\tests\TestTimeConstraint.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTimeConstraintMacro.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestUnitTest++.cpp">
+		</File>
+		<File
+			RelativePath=".\src\tests\TestXmlTestReporter.cpp">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 256 - 0
3rdparty/UnitTest++/TestUnitTest++.vsnet2005.vcproj

@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="TestUnitTest++.vsnet2005"
+	ProjectGUID="{9CCC3439-309E-4E85-B3B8-CE704D385D48}"
+	RootNamespace="TestUnitTestvsnet2005"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="&quot;$(TargetPath)&quot;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+				ExceptionHandling="2"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="&quot;$(TargetPath)&quot;"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\src\tests\Main.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\RecordingReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\ScopedCurrentTest.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestAssertHandler.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestCheckMacros.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestChecks.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestCurrentTest.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestDeferredTestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestMemoryOutStream.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTest.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestList.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestMacros.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestResults.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestRunner.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTestSuite.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTimeConstraint.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestTimeConstraintMacro.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestUnitTest++.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\tests\TestXmlTestReporter.cpp"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 169 - 0
3rdparty/UnitTest++/TestUnitTestPP_vs6.dsp

@@ -0,0 +1,169 @@
+# Microsoft Developer Studio Project File - Name="TestUnitTestPP_vs6" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** 編集しないでください **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=TestUnitTestPP_vs6 - Win32 Debug
+!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。
+!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください
+!MESSAGE 
+!MESSAGE NMAKE /f "TestUnitTestPP_vs6.mak".
+!MESSAGE 
+!MESSAGE NMAKE の実行時に構成を指定できます
+!MESSAGE コマンド ライン上でマクロの設定を定義します。例:
+!MESSAGE 
+!MESSAGE NMAKE /f "TestUnitTestPP_vs6.mak" CFG="TestUnitTestPP_vs6 - Win32 Debug"
+!MESSAGE 
+!MESSAGE 選択可能なビルド モード:
+!MESSAGE 
+!MESSAGE "TestUnitTestPP_vs6 - Win32 Release" ("Win32 (x86) Console Application" 用)
+!MESSAGE "TestUnitTestPP_vs6 - Win32 Debug" ("Win32 (x86) Console Application" 用)
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "TestUnitTestPP_vs6 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "TestUnitTestPP_vs6 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "TestUnitTestPP_vs6 - Win32 Release"
+# Name "TestUnitTestPP_vs6 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\tests\Main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestAssertHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestCheckMacros.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestChecks.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestCurrentTest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestDeferredTestReporter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestMemoryOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTestList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTestMacros.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTestResults.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTestRunner.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTestSuite.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTimeConstraint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestTimeConstraintMacro.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=".\src\tests\TestUnitTest++.cpp"
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\TestXmlTestReporter.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\src\tests\RecordingReporter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\tests\ScopedCurrentTest.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 30 - 0
3rdparty/UnitTest++/UnitTest++.vsnet2003.sln

@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest++.vsnet2003", "UnitTest++.vsnet2003.vcproj", "{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestUnitTest++.vsnet2003", "TestUnitTest++.vsnet2003.vcproj", "{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}"
+	ProjectSection(ProjectDependencies) = postProject
+		{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5} = {7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}.Debug.ActiveCfg = Debug|Win32
+		{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}.Debug.Build.0 = Debug|Win32
+		{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}.Release.ActiveCfg = Release|Win32
+		{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}.Release.Build.0 = Release|Win32
+		{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}.Debug.ActiveCfg = Debug|Win32
+		{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}.Debug.Build.0 = Debug|Win32
+		{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}.Release.ActiveCfg = Release|Win32
+		{ACDF9A6A-874F-49E5-AB7C-74F8150BB4C7}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal

+ 226 - 0
3rdparty/UnitTest++/UnitTest++.vsnet2003.vcproj

@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="UnitTest++.vsnet2003"
+	ProjectGUID="{7E5DD804-EC63-4FA5-BB6D-53DA86806EF5}"
+	RootNamespace="UnitTest++.vsnet2003"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/UnitTest++.vsnet2003.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+				RuntimeLibrary="4"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)/UnitTest++.vsnet2003.lib"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Win32">
+			<File
+				RelativePath=".\src\Win32\TimeHelpers.cpp">
+			</File>
+			<File
+				RelativePath=".\src\Win32\TimeHelpers.h">
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\src\AssertException.cpp">
+		</File>
+		<File
+			RelativePath=".\src\AssertException.h">
+		</File>
+		<File
+			RelativePath=".\src\CheckMacros.h">
+		</File>
+		<File
+			RelativePath=".\src\Checks.cpp">
+		</File>
+		<File
+			RelativePath=".\src\Checks.h">
+		</File>
+		<File
+			RelativePath=".\src\Config.h">
+		</File>
+		<File
+            RelativePath=".\src\CurrentTest.cpp">
+        </File>
+        <File
+            RelativePath=".\src\CurrentTest.h">
+        </File>
+        <File
+            RelativePath=".\src\DeferredTestReporter.cpp">
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestReporter.h">
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestResult.cpp">
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestResult.h">
+		</File>
+		<File
+			RelativePath=".\src\ExecuteTest.h">
+		</File>
+		<File
+			RelativePath=".\src\MemoryOutStream.cpp">
+		</File>
+		<File
+			RelativePath=".\src\MemoryOutStream.h">
+		</File>
+		<File
+			RelativePath=".\src\ReportAssert.cpp">
+		</File>
+		<File
+			RelativePath=".\src\ReportAssert.h">
+		</File>
+		<File
+			RelativePath=".\src\Test.cpp">
+		</File>
+		<File
+			RelativePath=".\src\Test.h">
+		</File>
+		<File
+			RelativePath=".\src\TestDetails.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestDetails.h">
+		</File>
+		<File
+			RelativePath=".\src\TestList.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestList.h">
+		</File>
+		<File
+			RelativePath=".\src\TestMacros.h">
+		</File>
+		<File
+			RelativePath=".\src\TestReporter.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestReporter.h">
+		</File>
+		<File
+			RelativePath=".\src\TestReporterStdout.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestReporterStdout.h">
+		</File>
+		<File
+			RelativePath=".\src\TestResults.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestResults.h">
+		</File>
+		<File
+			RelativePath=".\src\TestRunner.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TestRunner.h">
+		</File>
+		<File
+			RelativePath=".\src\TestSuite.h">
+		</File>
+		<File
+			RelativePath=".\src\TimeConstraint.cpp">
+		</File>
+		<File
+			RelativePath=".\src\TimeConstraint.h">
+		</File>
+		<File
+			RelativePath=".\src\TimeHelpers.h">
+		</File>
+		<File
+			RelativePath=".\src\UnitTest++.h">
+		</File>
+		<File
+			RelativePath=".\src\XmlTestReporter.cpp">
+		</File>
+		<File
+			RelativePath=".\src\XmlTestReporter.h">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 29 - 0
3rdparty/UnitTest++/UnitTest++.vsnet2005.sln

@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest++.vsnet2005", "UnitTest++.vsnet2005.vcproj", "{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestUnitTest++.vsnet2005", "TestUnitTest++.vsnet2005.vcproj", "{9CCC3439-309E-4E85-B3B8-CE704D385D48}"
+	ProjectSection(ProjectDependencies) = postProject
+		{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6} = {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.ActiveCfg = Debug|Win32
+		{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.Build.0 = Debug|Win32
+		{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.ActiveCfg = Release|Win32
+		{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.Build.0 = Release|Win32
+		{9CCC3439-309E-4E85-B3B8-CE704D385D48}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9CCC3439-309E-4E85-B3B8-CE704D385D48}.Debug|Win32.Build.0 = Debug|Win32
+		{9CCC3439-309E-4E85-B3B8-CE704D385D48}.Release|Win32.ActiveCfg = Release|Win32
+		{9CCC3439-309E-4E85-B3B8-CE704D385D48}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 318 - 0
3rdparty/UnitTest++/UnitTest++.vsnet2005.vcproj

@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="UnitTest++.vsnet2005"
+	ProjectGUID="{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}"
+	RootNamespace="UnitTestvsnet2005"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="1"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="1"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+				ExceptionHandling="2"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Win32"
+			>
+			<File
+				RelativePath=".\src\Win32\TimeHelpers.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\Win32\TimeHelpers.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\src\AssertException.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\AssertException.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\CheckMacros.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\Checks.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\Checks.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\Config.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\CurrentTest.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\CurrentTest.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestResult.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\DeferredTestResult.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\ExecuteTest.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\MemoryOutStream.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\MemoryOutStream.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\ReportAssert.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\ReportAssert.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\Test.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\Test.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestDetails.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestDetails.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestList.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestList.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestMacros.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestReporter.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestReporterStdout.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestReporterStdout.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestResults.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestResults.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestRunner.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestRunner.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TestSuite.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TimeConstraint.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TimeConstraint.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\TimeHelpers.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\UnitTest++.h"
+			>
+		</File>
+		<File
+			RelativePath=".\src\XmlTestReporter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\src\XmlTestReporter.h"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 260 - 0
3rdparty/UnitTest++/UnitTestPP_vs6.dsp

@@ -0,0 +1,260 @@
+# Microsoft Developer Studio Project File - Name="UnitTestPP_vs6" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** 編集しないでください **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=UnitTestPP_vs6 - Win32 Debug
+!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。
+!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください
+!MESSAGE 
+!MESSAGE NMAKE /f "UnitTestPP_vs6.mak".
+!MESSAGE 
+!MESSAGE NMAKE の実行時に構成を指定できます
+!MESSAGE コマンド ライン上でマクロの設定を定義します。例:
+!MESSAGE 
+!MESSAGE NMAKE /f "UnitTestPP_vs6.mak" CFG="UnitTestPP_vs6 - Win32 Debug"
+!MESSAGE 
+!MESSAGE 選択可能なビルド モード:
+!MESSAGE 
+!MESSAGE "UnitTestPP_vs6 - Win32 Release" ("Win32 (x86) Static Library" 用)
+!MESSAGE "UnitTestPP_vs6 - Win32 Debug" ("Win32 (x86) Static Library" 用)
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "UnitTestPP_vs6 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x411 /d "NDEBUG"
+# ADD RSC /l 0x411 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "UnitTestPP_vs6 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x411 /d "_DEBUG"
+# ADD RSC /l 0x411 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "UnitTestPP_vs6 - Win32 Release"
+# Name "UnitTestPP_vs6 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\src\AssertException.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Checks.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\CurrentTest.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\DeferredTestReporter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\DeferredTestResult.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\MemoryOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ReportAssert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Test.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestDetails.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestList.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestReporter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestReporterStdout.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestResults.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestRunner.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TimeConstraint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\XmlTestReporter.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\src\AssertException.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\CheckMacros.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Checks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\CurrentTest.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\DeferredTestReporter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\DeferredTestResult.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ExecuteTest.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\MemoryOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\ReportAssert.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Test.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestDetails.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestList.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestMacros.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestReporter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestReporterStdout.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestResults.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestRunner.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TestSuite.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TimeConstraint.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\TimeHelpers.h
+# End Source File
+# Begin Source File
+
+SOURCE=".\src\UnitTest++.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\XmlTestReporter.h
+# End Source File
+# End Group
+# Begin Group "Win32"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\src\Win32\TimeHelpers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\src\Win32\TimeHelpers.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 44 - 0
3rdparty/UnitTest++/UnitTestPP_vs6.dsw

@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# 警告: このワークスペース ファイル を編集または削除しないでください!
+
+###############################################################################
+
+Project: "TestUnitTestPP_vs6"=".\TestUnitTestPP_vs6.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name UnitTestPP_vs6
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "UnitTestPP_vs6"=".\UnitTestPP_vs6.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 260 - 0
3rdparty/UnitTest++/docs/UnitTest++.html

@@ -0,0 +1,260 @@
+<html>
+<head>
+	<title>UnitTest++ in brief</title>
+</head>
+<body>
+<h1>UnitTest++ in brief</h1>
+<h2>Introduction</h2>
+<p>This little document serves as bare-bones documentation for UnitTest++.</p>
+
+<p>For background, goals and license details, see:</p>
+
+<ul>
+  <li><a href="http://unittest-cpp.sourceforge.net/">The UnitTest++ home page</a></li>
+  <li><a href="http://gamesfromwithin.com/?p=51">Release announcement</a></li>
+</ul>
+
+<p>The documentation, while sparse, aims to be practical, so it should give you enough info to get started using UnitTest++ as fast as possible.</p>
+
+<h2>Building UnitTest++</h2>
+<p>Building UnitTest++ will be specific to each platform and build environment, but it should be straightforward.</p>
+
+<h3>Building with Visual Studio</h3>
+<p>If you are using Visual Studio, go for either of the provided .sln files, depending on version. There are no prefabricated solutions for versions earlier than VS.NET 2003, but we have had reports of people building UnitTest++ with at least VS.NET 2002.</p>
+
+<h3>Building with Make</h3>
+<p>The bundled makefile is written to build with g++. It also needs <code>sed</code> installed in the path, and to be able to use the <code>mv</code> and <code>rm</code> shell commands. The makefile should be usable on most Posix-like platforms.</p>
+
+<p>Do "make all" to generate a library and test executable. A final build step runs all unit tests to make sure that the result works as expected.</p>
+
+<h3>Packaging</h3>
+<p>You'll probably want to keep the generated library in a shared space in source control, so you can reuse it for multiple test projects. A redistributable package of UnitTest++ would consist of the generated library file, and all of the header files in <code>UnitTest++/src/</code> and its per-platform subfolders. The <code>tests</code> directory only contains the unit tests for the library, and need not be included.</p>
+
+<h2>Using UnitTest++</h2>
+<p>The source code for UnitTest++ comes with a full test suite written <em>using</em> UnitTest++. This is a great place to learn techniques for testing. There is one sample .cpp file: <code>UnitTest++/src/tests/TestUnitTest++.cpp</code>. It covers most of UnitTest++'s features in an easy-to-grasp context, so start there if you want a quick overview of typical usage.</p>
+
+<h3>Getting started</h3>
+<p>Listed below is a minimal C++ program to run a failing test through UnitTest++.</p>
+
+<pre>
+  // test.cpp
+  #include &lt;UnitTest++.h&gt;
+
+  TEST(FailSpectacularly)
+  {
+    CHECK(false);
+  }
+
+  int main()
+  {
+    return UnitTest::RunAllTests();
+  }
+</pre>
+
+<p><code>UnitTest++.h</code> is a facade header for UnitTest++, so including that should get you all features of the library. All classes and free functions are placed in namespace <code>UnitTest</code>, so you need to either qualify their full names (as with <code>RunAllTests()</code> in the example) or add a <code>using namespace UnitTest;</code> statement in your .cpp files. Note that any mention of UnitTest++ functions and classes in this document assume that the <code>UnitTest</code> namespace has been opened.</p>
+
+<p>Compiling and linking this program with UnitTest++'s static library into an executable, and running it, will produce the following output (details may vary):</p>
+
+<pre>
+  .\test.cpp(5): error: Failure in FailSpectacularly: false
+  FAILED: 1 out of 1 tests failed (1 failures).
+  Test time: 0.00 seconds.
+</pre>
+
+<p>UnitTest++ attempts to report every failure in an IDE-friendly format, depending on platform (e.g. you can double-click it in Visual Studio's error list.) The exit code will be the number of failed tests, so that a failed test run always returns a non-zero exit code.</p>
+
+<h3>Test macros</h3>
+<p>To add a test, simply put the following code in a .cpp file of your choice:</p>
+
+<pre>
+  TEST(YourTestName)
+  {
+  }
+</pre>
+
+<p>The <code>TEST</code> macro contains enough machinery to turn this slightly odd-looking syntax into legal C++, and automatically register the test in a global list. This test list forms the basis of what is executed by <code>RunAllTests()</code>.</p>
+
+<p>If you want to re-use a set of test data for more than one test, or provide setup/teardown for tests, you can use the <code>TEST_FIXTURE</code> macro instead. The macro requires that you pass it a class name that it will instantiate, so any setup and teardown code should be in its constructor and destructor.</p>
+
+<pre>
+  struct SomeFixture
+  {
+    SomeFixture() { /* some setup */ }
+    ~SomeFixture() { /* some teardown */ }
+
+    int testData;
+  };
+ 
+  TEST_FIXTURE(SomeFixture, YourTestName)
+  {
+    int temp = testData;
+  }
+</pre>
+
+<p>Note how members of the fixture are used as if they are a part of the test, since the macro-generated test class derives from the provided fixture class.</p>
+
+<h3>Suite macros</h3>
+<p>Tests can be grouped into suites, using the <code>SUITE</code> macro. A suite serves as a namespace for test names, so that the same test name can be used in two difference contexts.</p>
+
+<pre>
+  SUITE(YourSuiteName)
+  {
+    TEST(YourTestName)
+    {
+    }
+
+    TEST(YourOtherTestName)
+    {
+    }
+  }
+</pre>
+
+<p>This will place the tests into a C++ namespace called <code>YourSuiteName</code>, and make the suite name available to UnitTest++. <code>RunAllTests()</code> can be called for a specific suite name, so you can use this to build named groups of tests to be run together.</p>
+
+<h3>Simple check macros</h3>
+<p>In test cases, we want to check the results of our system under test. UnitTest++ provides a number of check macros that handle comparison and proper failure reporting.</p>
+
+<p>The most basic variety is the boolean <code>CHECK</code> macro:</p>
+
+<pre>
+  CHECK(false); // fails
+</pre>
+
+<p>It will fail if the boolean expression evaluates to false.</p>
+
+<p>For equality checks, it's generally better to use <code>CHECK_EQUAL</code>:</p>
+
+<pre>
+  CHECK_EQUAL(10, 20); // fails
+  CHECK_EQUAL("foo", "bar"); // fails
+</pre>
+
+<p>Note how <code>CHECK_EQUAL</code> is overloaded for C strings, so you don't have to resort to <code>strcmp</code> or similar. There is no facility for case-insensitive comparison or string searches, so you may have to drop down to a plain boolean <code>CHECK</code> with help from the CRT:</p>
+
+<pre>
+  CHECK(std::strstr("zaza", "az") != 0); // succeeds
+</pre>
+
+<p>For floating-point comparison, equality <a href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm">isn't necessarily well-defined</a>, so you should prefer the <code>CHECK_CLOSE</code> macro:</p>
+
+<pre>
+  CHECK_CLOSE(3.14, 3.1415, 0.01); // succeeds
+</pre>
+
+<p>All of the macros are tailored to avoid unintended side-effects, for example:</p>
+
+<pre>
+  TEST(CheckMacrosHaveNoSideEffects)
+  {
+    int i = 4;
+    CHECK_EQUAL(5, ++i); // succeeds
+    CHECK_EQUAL(5, i); // succeeds
+  }
+</pre>
+
+<p>The check macros guarantee that the <code>++i</code> expression isn't repeated internally, as demonstrated above.</p>
+
+<h3>Array check macros</h3>
+<p>There is a set of check macros for array comparison as well:</p>
+
+<pre>
+  const float oned[2] = { 10, 20 };
+  CHECK_ARRAY_EQUAL(oned, oned, 2); // succeeds
+  CHECK_ARRAY_CLOSE(oned, oned, 2, 0.00); // succeeds
+
+  const float twod[2][3] = { {0, 1, 2}, {2, 3, 4} };
+  CHECK_ARRAY2D_CLOSE(twod, twod, 2, 3, 0.00); // succeeds
+</pre>
+
+<p>The array equal macro compares elements using <code>operator==</code>, so <code>CHECK_ARRAY_EQUAL</code> won't work for an array of C strings, for example.</p>
+
+<p>The array close macros are similar to the regular CHECK_CLOSE macro, and are really only useful for scalar types, that can be compared in terms of a difference between two array elements.</p>
+
+<p>Note that the one-dimensional array macros work for <code>std::vector</code> as well, as it can be indexed just as a C array.</p>
+
+<h3>Exception check macros</h3>
+<p>Finally, there's a <code>CHECK_THROW</code> macro, which asserts that its enclosed expression throws the specified type:</p>
+
+<pre>
+  struct TestException {};
+  CHECK_THROW(throw TestException(), TestException); // succeeds
+</pre>
+
+<p>UnitTest++ natively catches exceptions if your test code doesn't. So if your code under test throws any exception UnitTest++ will fail the test and report either using the <code>what()</code> method for <code>std::exception</code> derivatives or just a plain message for unknown exception types.</p>
+
+<p>Should your test or code raise an irrecoverable error (an Access Violation on Win32, for example, or a signal on Linux), UnitTest++ will attempt to map them to an exception and fail the test, just as for other unhandled exceptions.</p>
+
+<h3>Time constraints</h3>
+<p>UnitTest++ can fail a test if it takes too long to complete, using so-called time constraints.</p>
+
+<p>They come in two flavors; <em>local</em> and <em>global</em> time constraints.</p>
+
+<p>Local time constraints are limited to the current scope, like so:</p>
+
+<pre>
+  TEST(YourTimedTest)
+  {
+     // Lengthy setup...
+
+     {
+        UNITTEST_TIME_CONSTRAINT(50);
+
+        // Do time-critical stuff
+     }
+
+     // Lengthy teardown...
+  }
+</pre>
+
+<p>The test will fail if the "Do time-critical stuff" block takes longer than 50 ms to complete. The time-consuming setup and teardown are not measured, since the time constraint is scope-bound. It's perfectly valid to have multiple local time constraints in the same test, as long as there is only one per block.</p>
+
+<p>A global time constraint, on the other hand, requires that all of the tests in a test run are faster than a specified amount of time. This allows you, when you run a suite of tests, to ask UnitTest++ to fail it entirely if any test exceeds the global constraint. The max time is passed as a parameter to an overload of <code>RunAllTests()</code>.</p>
+
+<p>If you want to use a global time constraint, but have one test that is notoriously slow, you can exempt it from inspection by using the <code>UNITTEST_TIME_CONSTRAINT_EXEMPT</code> macro anywhere inside the test body.</p>
+
+<pre>
+  TEST(NotoriouslySlowTest)
+  {
+     UNITTEST_TIME_CONSTRAINT_EXEMPT();
+
+     // Oh boy, this is going to take a while
+     ...
+  }
+</pre>
+
+<h3>Test runners</h3>
+<p>The <code>RunAllTests()</code> function has an overload that lets you customize the behavior of the runner, such as global time constraints, custom reporters, which suite to run, etc.</p>
+
+<pre>
+  int RunAllTests(TestReporter& reporter, TestList const& list, char const* suiteName, int const maxTestTimeInMs);
+</pre>
+
+<p>If you attempt to pass custom parameters to <code>RunAllTests()</code>, note that the <code>list</code> parameter should have the value <code>Test::GetTestList()</code>.</p>
+
+<p>The parameterless <code>RunAllTests()</code> is a simple wrapper for this one, with sensible defaults.</p>
+
+<h3>Example setup</h3>
+<p>How to create a new test project varies depending on your environment, but here are some directions on common file structure and usage.</p>
+
+<p>The general idea is that you keep one <code>Main.cpp</code> file with the entry-point which calls <code>RunAllTests()</code>.</p>
+
+<p>Then you can simply compile and link new .cpp files at will, typically one per test suite.</p>
+
+<pre>
+   + ShaverTests/
+   |
+   +- Main.cpp
+   |
+   +- TestBrush.cpp   
+   +- TestEngine.cpp
+   +- TestRazor.cpp   
+</pre>
+
+<p>Each of the <code>Test*.cpp</code> files will contain one or more <code>TEST</code> macro incantations with the associated test code. There are no source-level dependencies between <code>Main.cpp</code> and <code>Test*.cpp</code>, as the <code>TEST</code> macro handles the registration and setup necessary for <code>RunAllTests()</code> to find all tests compiled into the same final executable.</p>
+
+<p>UnitTest++ does not require this structure, even if this is how the library itself does it. As long as your test project contains one or more <code>TESTs</code> and calls <code>RunAllTests()</code> at one point or another, it will be handled by UnitTest++.</p>
+
+<p>It's common to make the generated executable start as a post-build step, so that merely building your test project will run the tests as well. Since the exit code is the count of failures, a failed test will generally break the build, as most build engines will fail a build if any step returns a non-zero exit code.</p>
+
+</body>
+</html>

+ 34 - 0
3rdparty/UnitTest++/src/AssertException.cpp

@@ -0,0 +1,34 @@
+#include "AssertException.h"
+#include <cstring>
+
+namespace UnitTest {
+
+AssertException::AssertException(char const* description, char const* filename, int lineNumber)
+    : m_lineNumber(lineNumber)
+{
+	using namespace std;
+
+    strcpy(m_description, description);
+    strcpy(m_filename, filename);
+}
+
+AssertException::~AssertException() throw()
+{
+}
+
+char const* AssertException::what() const throw()
+{
+    return m_description;
+}
+
+char const* AssertException::Filename() const
+{
+    return m_filename;
+}
+
+int AssertException::LineNumber() const
+{
+    return m_lineNumber;
+}
+
+}

+ 28 - 0
3rdparty/UnitTest++/src/AssertException.h

@@ -0,0 +1,28 @@
+#ifndef UNITTEST_ASSERTEXCEPTION_H
+#define UNITTEST_ASSERTEXCEPTION_H
+
+#include <exception>
+
+
+namespace UnitTest {
+
+class AssertException : public std::exception
+{
+public:
+    AssertException(char const* description, char const* filename, int lineNumber);
+    virtual ~AssertException() throw();
+
+    virtual char const* what() const throw();
+
+    char const* Filename() const;
+    int LineNumber() const;
+
+private:
+    char m_description[512];
+    char m_filename[256];
+    int m_lineNumber;
+};
+
+}
+
+#endif

+ 122 - 0
3rdparty/UnitTest++/src/CheckMacros.h

@@ -0,0 +1,122 @@
+#ifndef UNITTEST_CHECKMACROS_H 
+#define UNITTEST_CHECKMACROS_H
+
+#include "Checks.h"
+#include "AssertException.h"
+#include "MemoryOutStream.h"
+#include "TestDetails.h"
+#include "CurrentTest.h"
+
+#ifdef CHECK
+    #error UnitTest++ redefines CHECK
+#endif
+
+#ifdef CHECK_EQUAL
+	#error UnitTest++ redefines CHECK_EQUAL
+#endif
+
+#ifdef CHECK_CLOSE
+	#error UnitTest++ redefines CHECK_CLOSE
+#endif
+
+#ifdef CHECK_ARRAY_EQUAL
+	#error UnitTest++ redefines CHECK_ARRAY_EQUAL
+#endif
+
+#ifdef CHECK_ARRAY_CLOSE
+	#error UnitTest++ redefines CHECK_ARRAY_CLOSE
+#endif
+
+#ifdef CHECK_ARRAY2D_CLOSE
+	#error UnitTest++ redefines CHECK_ARRAY2D_CLOSE
+#endif
+
+#define CHECK(value) \
+    do \
+    { \
+        try { \
+            if (!UnitTest::Check(value)) \
+                UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK(" #value ")"); \
+        } \
+    } while (0)
+
+#define CHECK_EQUAL(expected, actual) \
+    do \
+    { \
+        try { \
+            UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK_EQUAL(" #expected ", " #actual ")"); \
+        } \
+    } while (0)
+
+#define CHECK_CLOSE(expected, actual, tolerance) \
+    do \
+    { \
+        try { \
+            UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \
+        } \
+    } while (0)
+
+#define CHECK_ARRAY_EQUAL(expected, actual, count) \
+    do \
+    { \
+        try { \
+            UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"); \
+        } \
+    } while (0)
+
+#define CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \
+    do \
+    { \
+        try { \
+            UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \
+        } \
+    } while (0)
+
+#define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \
+    do \
+    { \
+        try { \
+            UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \
+        } \
+        catch (...) { \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \
+                    "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \
+        } \
+    } while (0)
+
+
+#define CHECK_THROW(expression, ExpectedExceptionType) \
+    do \
+    { \
+        bool caught_ = false; \
+        try { expression; } \
+        catch (ExpectedExceptionType const&) { caught_ = true; } \
+        catch (...) {} \
+        if (!caught_) \
+            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "Expected exception: \"" #ExpectedExceptionType "\" not thrown"); \
+    } while(0)
+
+#define CHECK_ASSERT(expression) \
+    CHECK_THROW(expression, UnitTest::AssertException);
+
+#endif

+ 50 - 0
3rdparty/UnitTest++/src/Checks.cpp

@@ -0,0 +1,50 @@
+#include "Checks.h"
+#include <cstring>
+
+namespace UnitTest {
+
+namespace {
+
+void CheckStringsEqual(TestResults& results, char const* expected, char const* actual, 
+                       TestDetails const& details)
+{
+	using namespace std;
+
+    if (strcmp(expected, actual))
+    {
+        UnitTest::MemoryOutStream stream;
+        stream << "Expected " << expected << " but was " << actual;
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+}
+
+
+void CheckEqual(TestResults& results, char const* expected, char const* actual,
+                TestDetails const& details)
+{
+    CheckStringsEqual(results, expected, actual, details);
+}
+
+void CheckEqual(TestResults& results, char* expected, char* actual,
+                TestDetails const& details)
+{
+    CheckStringsEqual(results, expected, actual, details);
+}
+
+void CheckEqual(TestResults& results, char* expected, char const* actual,
+                TestDetails const& details)
+{
+    CheckStringsEqual(results, expected, actual, details);
+}
+
+void CheckEqual(TestResults& results, char const* expected, char* actual,
+                TestDetails const& details)
+{
+    CheckStringsEqual(results, expected, actual, details);
+}
+
+
+}

+ 158 - 0
3rdparty/UnitTest++/src/Checks.h

@@ -0,0 +1,158 @@
+#ifndef UNITTEST_CHECKS_H
+#define UNITTEST_CHECKS_H
+
+#include "Config.h"
+#include "TestResults.h"
+#include "MemoryOutStream.h"
+
+namespace UnitTest {
+
+
+template< typename Value >
+bool Check(Value const value)
+{
+    return !!value; // doing double negative to avoid silly VS warnings
+}
+
+
+template< typename Expected, typename Actual >
+void CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details)
+{
+    if (!(expected == actual))
+    {
+        UnitTest::MemoryOutStream stream;
+        stream << "Expected " << expected << " but was " << actual;
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details);
+
+void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details);
+
+void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details);
+
+void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details);
+
+template< typename Expected, typename Actual, typename Tolerance >
+bool AreClose(Expected const& expected, Actual const& actual, Tolerance const& tolerance)
+{
+    return (actual >= (expected - tolerance)) && (actual <= (expected + tolerance));
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
+void CheckClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance,
+                TestDetails const& details)
+{
+    if (!AreClose(expected, actual, tolerance))
+    { 
+        UnitTest::MemoryOutStream stream;
+        stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual;
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+
+template< typename Expected, typename Actual >
+void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual,
+                int const count, TestDetails const& details)
+{
+    bool equal = true;
+    for (int i = 0; i < count; ++i)
+        equal &= (expected[i] == actual[i]);
+
+    if (!equal)
+    {
+        UnitTest::MemoryOutStream stream;
+
+		stream << "Expected [ ";
+
+		for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex)
+            stream << expected[expectedIndex] << " ";
+
+		stream << "] but was [ ";
+
+		for (int actualIndex = 0; actualIndex < count; ++actualIndex)
+            stream << actual[actualIndex] << " ";
+
+		stream << "]";
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
+bool ArrayAreClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance)
+{
+    bool equal = true;
+    for (int i = 0; i < count; ++i)
+        equal &= AreClose(expected[i], actual[i], tolerance);
+    return equal;
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
+void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual,
+                   int const count, Tolerance const& tolerance, TestDetails const& details)
+{
+    bool equal = ArrayAreClose(expected, actual, count, tolerance);
+
+    if (!equal)
+    {
+        UnitTest::MemoryOutStream stream;
+
+        stream << "Expected [ ";
+        for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex)
+            stream << expected[expectedIndex] << " ";
+        stream << "] +/- " << tolerance << " but was [ ";
+
+		for (int actualIndex = 0; actualIndex < count; ++actualIndex)
+            stream << actual[actualIndex] << " ";
+        stream << "]";
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+template< typename Expected, typename Actual, typename Tolerance >
+void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual,
+                   int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details)
+{
+    bool equal = true;
+    for (int i = 0; i < rows; ++i)
+        equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance);
+
+    if (!equal)
+    {
+        UnitTest::MemoryOutStream stream;
+
+        stream << "Expected [ ";    
+
+		for (int expectedRow = 0; expectedRow < rows; ++expectedRow)
+        {
+            stream << "[ ";
+            for (int expectedColumn = 0; expectedColumn < columns; ++expectedColumn)
+                stream << expected[expectedRow][expectedColumn] << " ";
+            stream << "] ";
+        }
+
+		stream << "] +/- " << tolerance << " but was [ ";
+
+		for (int actualRow = 0; actualRow < rows; ++actualRow)
+        {
+            stream << "[ ";
+            for (int actualColumn = 0; actualColumn < columns; ++actualColumn)
+                stream << actual[actualRow][actualColumn] << " ";
+            stream << "] ";
+        }
+
+		stream << "]";
+
+        results.OnTestFailure(details, stream.GetText());
+    }
+}
+
+}
+
+#endif

+ 31 - 0
3rdparty/UnitTest++/src/Config.h

@@ -0,0 +1,31 @@
+#ifndef UNITTEST_CONFIG_H
+#define UNITTEST_CONFIG_H
+
+// Standard defines documented here: http://predef.sourceforge.net
+
+#if defined(_MSC_VER)
+    #pragma warning(disable:4127) // conditional expression is constant
+	#pragma warning(disable:4702) // unreachable code
+	#pragma warning(disable:4722) // destructor never returns, potential memory leak
+
+	#if (_MSC_VER == 1200)  // VC6
+		#pragma warning(disable:4786)
+		#pragma warning(disable:4290)
+	#endif
+#endif
+
+#if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \
+    defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)        
+    #define UNITTEST_POSIX
+#endif
+
+#if defined(__MINGW32__)
+    #define UNITTEST_MINGW
+#endif
+
+// by default, MemoryOutStream is implemented in terms of std::ostringstream, which can be expensive.
+// uncomment this line to use the custom MemoryOutStream (no deps on std::ostringstream).
+
+//#define UNITTEST_USE_CUSTOM_STREAMS
+
+#endif

+ 18 - 0
3rdparty/UnitTest++/src/CurrentTest.cpp

@@ -0,0 +1,18 @@
+#include "CurrentTest.h"
+#include <cstddef>
+
+namespace UnitTest {
+
+TestResults*& CurrentTest::Results()
+{
+	static TestResults* testResults = NULL;
+	return testResults;
+}
+
+const TestDetails*& CurrentTest::Details()
+{
+	static const TestDetails* testDetails = NULL;
+	return testDetails;
+}
+
+}

+ 17 - 0
3rdparty/UnitTest++/src/CurrentTest.h

@@ -0,0 +1,17 @@
+#ifndef UNITTEST_CURRENTTESTRESULTS_H
+#define UNITTEST_CURRENTTESTRESULTS_H
+
+namespace UnitTest {
+
+class TestResults;
+class TestDetails;
+
+namespace CurrentTest
+{
+	TestResults*& Results();
+	const TestDetails*& Details();
+}
+
+}
+
+#endif

+ 28 - 0
3rdparty/UnitTest++/src/DeferredTestReporter.cpp

@@ -0,0 +1,28 @@
+#include "DeferredTestReporter.h"
+#include "TestDetails.h"
+
+using namespace UnitTest;
+
+void DeferredTestReporter::ReportTestStart(TestDetails const& details)
+{
+    m_results.push_back(DeferredTestResult(details.suiteName, details.testName));
+}
+
+void DeferredTestReporter::ReportFailure(TestDetails const& details, char const* failure)
+{
+    DeferredTestResult& r = m_results.back();
+    r.failed = true;
+    r.failures.push_back(DeferredTestResult::Failure(details.lineNumber, failure));
+    r.failureFile = details.filename;
+}
+
+void DeferredTestReporter::ReportTestFinish(TestDetails const&, float secondsElapsed)
+{
+    DeferredTestResult& r = m_results.back();
+    r.timeElapsed = secondsElapsed;
+}
+
+DeferredTestReporter::DeferredTestResultList& DeferredTestReporter::GetResults()
+{
+    return m_results;
+}

+ 29 - 0
3rdparty/UnitTest++/src/DeferredTestReporter.h

@@ -0,0 +1,29 @@
+#ifndef UNITTEST_DEFERREDTESTREPORTER_H
+#define UNITTEST_DEFERREDTESTREPORTER_H
+
+#include "TestReporter.h"
+#include "DeferredTestResult.h"
+#include "Config.h"
+
+#include <vector>
+
+namespace UnitTest
+{
+
+class DeferredTestReporter : public TestReporter
+{
+public:
+    virtual void ReportTestStart(TestDetails const& details);
+    virtual void ReportFailure(TestDetails const& details, char const* failure);
+    virtual void ReportTestFinish(TestDetails const& details, float secondsElapsed);
+
+    typedef std::vector< DeferredTestResult > DeferredTestResultList;
+    DeferredTestResultList& GetResults();
+
+private:
+    DeferredTestResultList m_results;
+};
+
+}
+
+#endif

+ 29 - 0
3rdparty/UnitTest++/src/DeferredTestResult.cpp

@@ -0,0 +1,29 @@
+#include "DeferredTestResult.h"
+#include "Config.h"
+
+namespace UnitTest
+{
+
+DeferredTestResult::DeferredTestResult()
+	: suiteName("")
+	, testName("")
+	, failureFile("")
+	, timeElapsed(0.0f)
+	, failed(false)
+{
+}
+
+DeferredTestResult::DeferredTestResult(char const* suite, char const* test)
+	: suiteName(suite)
+	, testName(test)
+	, failureFile("")
+	, timeElapsed(0.0f)
+	, failed(false)
+{
+}
+
+DeferredTestResult::~DeferredTestResult()
+{
+}
+
+}

+ 32 - 0
3rdparty/UnitTest++/src/DeferredTestResult.h

@@ -0,0 +1,32 @@
+#ifndef UNITTEST_DEFERREDTESTRESULT_H
+#define UNITTEST_DEFERREDTESTRESULT_H
+
+#include "Config.h"
+
+#include <string>
+#include <vector>
+
+namespace UnitTest
+{
+
+struct DeferredTestResult
+{
+	DeferredTestResult();
+    DeferredTestResult(char const* suite, char const* test);
+    ~DeferredTestResult();
+    
+    std::string suiteName;
+    std::string testName;
+    std::string failureFile;
+    
+    typedef std::pair< int, std::string > Failure;
+    typedef std::vector< Failure > FailureVec;
+    FailureVec failures;
+    
+    float timeElapsed;
+	bool failed;
+};
+
+}
+
+#endif //UNITTEST_DEFERREDTESTRESULT_H

+ 46 - 0
3rdparty/UnitTest++/src/ExecuteTest.h

@@ -0,0 +1,46 @@
+#ifndef UNITTEST_EXECUTE_TEST_H
+#define UNITTEST_EXECUTE_TEST_H
+
+#include "TestDetails.h"
+#include "MemoryOutStream.h"
+#include "AssertException.h"
+#include "CurrentTest.h"
+
+#ifdef UNITTEST_POSIX
+	#include "Posix/SignalTranslator.h"
+#endif
+
+namespace UnitTest {
+
+template< typename T >
+void ExecuteTest(T& testObject, TestDetails const& details)
+{
+	CurrentTest::Details() = &details;
+
+	try
+	{
+#ifdef UNITTEST_POSIX
+		UNITTEST_THROW_SIGNALS
+#endif
+		testObject.RunImpl();
+	}
+	catch (AssertException const& e)
+	{
+		CurrentTest::Results()->OnTestFailure(
+			TestDetails(details.testName, details.suiteName, e.Filename(), e.LineNumber()), e.what());
+	}
+	catch (std::exception const& e)
+	{
+		MemoryOutStream stream;
+		stream << "Unhandled exception: " << e.what();
+		CurrentTest::Results()->OnTestFailure(details, stream.GetText());
+	}
+	catch (...)
+	{
+		CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: Crash!");
+	}
+}
+
+}
+
+#endif

+ 149 - 0
3rdparty/UnitTest++/src/MemoryOutStream.cpp

@@ -0,0 +1,149 @@
+#include "MemoryOutStream.h"
+
+#ifndef UNITTEST_USE_CUSTOM_STREAMS
+
+
+namespace UnitTest {
+
+char const* MemoryOutStream::GetText() const
+{
+    m_text = this->str();
+    return m_text.c_str();
+}
+
+
+}
+
+
+#else
+
+
+#include <cstring>
+#include <cstdio>
+
+namespace UnitTest {
+
+namespace {
+
+template<typename ValueType>
+void FormatToStream(MemoryOutStream& stream, char const* format, ValueType const& value)
+{
+	using namespace std;
+
+    char txt[32];
+    sprintf(txt, format, value);
+    stream << txt;
+}
+
+int RoundUpToMultipleOfPow2Number (int n, int pow2Number)
+{
+    return (n + (pow2Number - 1)) & ~(pow2Number - 1);
+}
+
+}
+
+
+MemoryOutStream::MemoryOutStream(int const size)
+    : m_capacity (0)
+    , m_buffer (0)
+
+{
+    GrowBuffer(size);
+}
+
+MemoryOutStream::~MemoryOutStream()
+{
+    delete [] m_buffer;
+}
+
+char const* MemoryOutStream::GetText() const
+{
+    return m_buffer;
+}
+
+MemoryOutStream& MemoryOutStream::operator << (char const* txt)
+{
+	using namespace std;
+
+    int const bytesLeft = m_capacity - (int)strlen(m_buffer);
+    int const bytesRequired = (int)strlen(txt) + 1;
+
+    if (bytesRequired > bytesLeft)
+    {
+        int const requiredCapacity = bytesRequired + m_capacity - bytesLeft;
+        GrowBuffer(requiredCapacity);
+    }
+
+    strcat(m_buffer, txt);
+    return *this;
+}
+
+MemoryOutStream& MemoryOutStream::operator << (int const n)
+{
+    FormatToStream(*this, "%i", n);
+    return *this;
+}
+
+MemoryOutStream& MemoryOutStream::operator << (long const n)
+{
+    FormatToStream(*this, "%li", n);
+    return *this;
+}
+
+MemoryOutStream& MemoryOutStream::operator << (unsigned long const n)
+{
+    FormatToStream(*this, "%lu", n);
+    return *this;
+}
+
+MemoryOutStream& MemoryOutStream::operator << (float const f)
+{
+    FormatToStream(*this, "%ff", f);
+    return *this;    
+}
+
+MemoryOutStream& MemoryOutStream::operator << (void const* p)
+{
+    FormatToStream(*this, "%p", p);
+    return *this;    
+}
+
+MemoryOutStream& MemoryOutStream::operator << (unsigned int const s)
+{
+    FormatToStream(*this, "%u", s);
+    return *this;    
+}
+
+MemoryOutStream& MemoryOutStream::operator <<(double const d)
+{
+	FormatToStream(*this, "%f", d);
+	return *this;
+}
+
+int MemoryOutStream::GetCapacity() const
+{
+    return m_capacity;
+}
+
+
+void MemoryOutStream::GrowBuffer(int const desiredCapacity)
+{
+    int const newCapacity = RoundUpToMultipleOfPow2Number(desiredCapacity, GROW_CHUNK_SIZE);
+
+	using namespace std;
+
+    char* buffer = new char[newCapacity];
+    if (m_buffer)
+        strcpy(buffer, m_buffer);
+    else
+        strcpy(buffer, "");
+
+    delete [] m_buffer;
+    m_buffer = buffer;
+    m_capacity = newCapacity;
+}
+
+}
+
+
+#endif

+ 68 - 0
3rdparty/UnitTest++/src/MemoryOutStream.h

@@ -0,0 +1,68 @@
+#ifndef UNITTEST_MEMORYOUTSTREAM_H
+#define UNITTEST_MEMORYOUTSTREAM_H
+
+#include "Config.h"
+
+#ifndef UNITTEST_USE_CUSTOM_STREAMS
+
+#include <sstream>
+
+namespace UnitTest
+{
+
+class MemoryOutStream : public std::ostringstream
+{
+public:
+    MemoryOutStream() {}
+    ~MemoryOutStream() {}
+    char const* GetText() const;
+
+private:
+    MemoryOutStream(MemoryOutStream const&);
+    void operator =(MemoryOutStream const&);
+
+    mutable std::string m_text;
+};
+
+}
+
+#else
+
+#include <cstddef>
+
+namespace UnitTest
+{
+
+class MemoryOutStream
+{
+public:
+    explicit MemoryOutStream(int const size = 256);
+    ~MemoryOutStream();
+
+    char const* GetText() const;
+
+    MemoryOutStream& operator << (char const* txt);
+    MemoryOutStream& operator << (int n);
+    MemoryOutStream& operator << (long n);
+    MemoryOutStream& operator << (unsigned long n);
+    MemoryOutStream& operator << (float f);
+    MemoryOutStream& operator << (double d);
+    MemoryOutStream& operator << (void const* p);
+    MemoryOutStream& operator << (unsigned int s);
+
+    enum { GROW_CHUNK_SIZE = 32 };
+    int GetCapacity() const;
+
+private:
+    void operator= (MemoryOutStream const&);
+    void GrowBuffer(int capacity);
+
+    int m_capacity;
+    char* m_buffer;
+};
+
+}
+
+#endif
+
+#endif

+ 46 - 0
3rdparty/UnitTest++/src/Posix/SignalTranslator.cpp

@@ -0,0 +1,46 @@
+#include "SignalTranslator.h"
+
+namespace UnitTest {
+
+sigjmp_buf* SignalTranslator::s_jumpTarget = 0;
+
+namespace {
+
+void SignalHandler(int sig)
+{
+    siglongjmp(*SignalTranslator::s_jumpTarget, sig );
+}
+
+}
+
+
+SignalTranslator::SignalTranslator()
+{
+    m_oldJumpTarget = s_jumpTarget;
+    s_jumpTarget = &m_currentJumpTarget;
+
+    struct sigaction action;
+    action.sa_flags = 0;
+    action.sa_handler = SignalHandler;
+    sigemptyset( &action.sa_mask );
+
+    sigaction( SIGSEGV, &action, &m_old_SIGSEGV_action );
+    sigaction( SIGFPE , &action, &m_old_SIGFPE_action  );
+    sigaction( SIGTRAP, &action, &m_old_SIGTRAP_action );
+    sigaction( SIGBUS , &action, &m_old_SIGBUS_action  );
+    sigaction( SIGILL , &action, &m_old_SIGBUS_action  );
+}
+
+SignalTranslator::~SignalTranslator()
+{
+    sigaction( SIGILL , &m_old_SIGBUS_action , 0 );
+    sigaction( SIGBUS , &m_old_SIGBUS_action , 0 );
+    sigaction( SIGTRAP, &m_old_SIGTRAP_action, 0 );
+    sigaction( SIGFPE , &m_old_SIGFPE_action , 0 );
+    sigaction( SIGSEGV, &m_old_SIGSEGV_action, 0 );
+
+    s_jumpTarget = m_oldJumpTarget;
+}
+
+
+}

+ 42 - 0
3rdparty/UnitTest++/src/Posix/SignalTranslator.h

@@ -0,0 +1,42 @@
+#ifndef UNITTEST_SIGNALTRANSLATOR_H
+#define UNITTEST_SIGNALTRANSLATOR_H
+
+#include <setjmp.h>
+#include <signal.h>
+
+namespace UnitTest {
+
+class SignalTranslator
+{
+public:
+    SignalTranslator();
+    ~SignalTranslator();
+
+    static sigjmp_buf* s_jumpTarget;
+
+private:
+    sigjmp_buf m_currentJumpTarget;
+    sigjmp_buf* m_oldJumpTarget;
+
+    struct sigaction m_old_SIGFPE_action;
+    struct sigaction m_old_SIGTRAP_action;
+    struct sigaction m_old_SIGSEGV_action;
+    struct sigaction m_old_SIGBUS_action;
+    struct sigaction m_old_SIGABRT_action;
+    struct sigaction m_old_SIGALRM_action;
+};
+
+#if !defined (__GNUC__)
+    #define UNITTEST_EXTENSION
+#else
+    #define UNITTEST_EXTENSION __extension__
+#endif
+
+#define UNITTEST_THROW_SIGNALS \
+	UnitTest::SignalTranslator sig; \
+	if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \
+        throw ("Unhandled system exception"); 
+
+}
+
+#endif

+ 33 - 0
3rdparty/UnitTest++/src/Posix/TimeHelpers.cpp

@@ -0,0 +1,33 @@
+#include "TimeHelpers.h"
+#include <unistd.h>
+
+namespace UnitTest {
+
+Timer::Timer()
+{
+    m_startTime.tv_sec = 0;
+    m_startTime.tv_usec = 0;
+}
+
+void Timer::Start()
+{
+    gettimeofday(&m_startTime, 0);
+}
+
+double Timer::GetTimeInMs() const
+{
+    struct timeval currentTime;
+    gettimeofday(&currentTime, 0);
+
+	double const dsecs = currentTime.tv_sec - m_startTime.tv_sec;
+    double const dus = currentTime.tv_usec - m_startTime.tv_usec;
+
+	return (dsecs * 1000.0) + (dus / 1000.0);
+}
+
+void TimeHelpers::SleepMs(int ms)
+{
+    usleep(ms * 1000);
+}
+
+}

+ 28 - 0
3rdparty/UnitTest++/src/Posix/TimeHelpers.h

@@ -0,0 +1,28 @@
+#ifndef UNITTEST_TIMEHELPERS_H
+#define UNITTEST_TIMEHELPERS_H
+
+#include <sys/time.h>
+
+namespace UnitTest {
+
+class Timer
+{
+public:
+    Timer();
+    void Start();
+    double GetTimeInMs() const;    
+
+private:
+    struct timeval m_startTime;    
+};
+
+
+namespace TimeHelpers
+{
+void SleepMs (int ms);
+}
+
+
+}
+
+#endif

+ 11 - 0
3rdparty/UnitTest++/src/ReportAssert.cpp

@@ -0,0 +1,11 @@
+#include "ReportAssert.h"
+#include "AssertException.h"
+
+namespace UnitTest {
+
+void ReportAssert(char const* description, char const* filename, int lineNumber)
+{
+    throw AssertException(description, filename, lineNumber);
+}
+
+}

+ 10 - 0
3rdparty/UnitTest++/src/ReportAssert.h

@@ -0,0 +1,10 @@
+#ifndef UNITTEST_ASSERT_H
+#define UNITTEST_ASSERT_H
+
+namespace UnitTest {
+
+void ReportAssert(char const* description, char const* filename, int lineNumber);
+    
+}
+
+#endif

+ 41 - 0
3rdparty/UnitTest++/src/Test.cpp

@@ -0,0 +1,41 @@
+#include "Config.h"
+#include "Test.h"
+#include "TestList.h"
+#include "TestResults.h"
+#include "AssertException.h"
+#include "MemoryOutStream.h"
+#include "ExecuteTest.h"
+
+#ifdef UNITTEST_POSIX
+    #include "Posix/SignalTranslator.h"
+#endif
+
+namespace UnitTest {
+
+TestList& Test::GetTestList()
+{
+    static TestList s_list;
+    return s_list;
+}
+
+Test::Test(char const* testName, char const* suiteName, char const* filename, int lineNumber)
+    : m_details(testName, suiteName, filename, lineNumber)
+    , next(0)
+    , m_timeConstraintExempt(false)
+{
+}
+
+Test::~Test()
+{
+}
+
+void Test::Run()
+{
+	ExecuteTest(*this, m_details);
+}
+
+void Test::RunImpl() const
+{
+}
+
+}

+ 34 - 0
3rdparty/UnitTest++/src/Test.h

@@ -0,0 +1,34 @@
+#ifndef UNITTEST_TEST_H
+#define UNITTEST_TEST_H
+
+#include "TestDetails.h"
+
+namespace UnitTest {
+
+class TestResults;
+class TestList;
+
+class Test
+{
+public:
+    explicit Test(char const* testName, char const* suiteName = "DefaultSuite", char const* filename = "", int lineNumber = 0);
+    virtual ~Test();
+    void Run();
+
+    TestDetails const m_details;
+    Test* next;
+    mutable bool m_timeConstraintExempt;
+
+    static TestList& GetTestList();
+
+    virtual void RunImpl() const;
+
+private:
+	Test(Test const&);
+    Test& operator =(Test const&);
+};
+
+
+}
+
+#endif

+ 22 - 0
3rdparty/UnitTest++/src/TestDetails.cpp

@@ -0,0 +1,22 @@
+#include "TestDetails.h"
+
+namespace UnitTest {
+
+TestDetails::TestDetails(char const* testName_, char const* suiteName_, char const* filename_, int lineNumber_)
+    : suiteName(suiteName_)
+    , testName(testName_)
+    , filename(filename_)
+    , lineNumber(lineNumber_)
+{
+}
+
+TestDetails::TestDetails(const TestDetails& details, int lineNumber_)
+    : suiteName(details.suiteName)
+    , testName(details.testName)
+    , filename(details.filename)
+    , lineNumber(lineNumber_)
+{
+}
+
+
+}

+ 24 - 0
3rdparty/UnitTest++/src/TestDetails.h

@@ -0,0 +1,24 @@
+#ifndef UNITTEST_TESTDETAILS_H
+#define UNITTEST_TESTDETAILS_H
+
+namespace UnitTest {
+
+class TestDetails
+{
+public:
+    TestDetails(char const* testName, char const* suiteName, char const* filename, int lineNumber);
+    TestDetails(const TestDetails& details, int lineNumber);
+
+    char const* const suiteName;
+    char const* const testName;
+    char const* const filename;
+    int const lineNumber;
+
+    TestDetails(TestDetails const&); // Why is it public? --> http://gcc.gnu.org/bugs.html#cxx_rvalbind
+private:
+    TestDetails& operator=(TestDetails const&);
+};
+
+}
+
+#endif

+ 39 - 0
3rdparty/UnitTest++/src/TestList.cpp

@@ -0,0 +1,39 @@
+#include "TestList.h"
+#include "Test.h"
+
+#include <cassert>
+
+namespace UnitTest {
+
+TestList::TestList() 
+    : m_head(0)
+    , m_tail(0)
+{
+}
+
+void TestList::Add(Test* test)
+{
+    if (m_tail == 0)
+    {
+        assert(m_head == 0);
+        m_head = test;
+        m_tail = test;
+    }
+    else
+    {
+        m_tail->next = test;
+        m_tail = test;
+    }
+}
+
+Test* TestList::GetHead() const
+{
+    return m_head;
+}
+
+ListAdder::ListAdder(TestList& list, Test* test)
+{
+    list.Add(test);
+}
+
+}

+ 32 - 0
3rdparty/UnitTest++/src/TestList.h

@@ -0,0 +1,32 @@
+#ifndef UNITTEST_TESTLIST_H
+#define UNITTEST_TESTLIST_H
+
+
+namespace UnitTest {
+
+class Test;
+
+class TestList
+{
+public:
+    TestList();
+    void Add (Test* test);
+
+    Test* GetHead() const;
+
+private:
+    Test* m_head;
+    Test* m_tail;
+};
+
+
+class ListAdder
+{
+public:
+    ListAdder(TestList& list, Test* test);
+};
+
+}
+
+
+#endif

+ 113 - 0
3rdparty/UnitTest++/src/TestMacros.h

@@ -0,0 +1,113 @@
+#ifndef UNITTEST_TESTMACROS_H
+#define UNITTEST_TESTMACROS_H
+
+#include "Config.h"
+#include "ExecuteTest.h"
+#include "AssertException.h"
+#include "TestDetails.h"
+#include "MemoryOutStream.h"
+
+#ifndef UNITTEST_POSIX
+	#define UNITTEST_THROW_SIGNALS
+#else
+	#include "Posix/SignalTranslator.h"
+#endif
+
+#ifdef TEST
+    #error UnitTest++ redefines TEST
+#endif
+
+#ifdef TEST_EX
+	#error UnitTest++ redefines TEST_EX
+#endif
+
+#ifdef TEST_FIXTURE_EX
+	#error UnitTest++ redefines TEST_FIXTURE_EX
+#endif
+
+#define SUITE(Name)                                                         \
+	namespace Suite##Name {                                                        \
+        namespace UnitTestSuite {                                           \
+            inline char const* GetSuiteName () {                            \
+                return #Name ;                                              \
+            }                                                               \
+        }                                                                   \
+    }                                                                       \
+	namespace Suite##Name
+
+#define TEST_EX(Name, List)                                                \
+    class Test##Name : public UnitTest::Test                               \
+    {                                                                      \
+    public:                                                                \
+		Test##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {}  \
+    private:                                                               \
+        virtual void RunImpl() const;   \
+    } test##Name##Instance;                                                \
+																		   \
+    UnitTest::ListAdder adder##Name (List, &test##Name##Instance);         \
+																		   \
+    void Test##Name::RunImpl() const
+
+
+#define TEST(Name) TEST_EX(Name, UnitTest::Test::GetTestList())
+
+
+#define TEST_FIXTURE_EX(Fixture, Name, List)                                         \
+    class Fixture##Name##Helper : public Fixture									 \
+	{																				 \
+	public:																			 \
+        explicit Fixture##Name##Helper(UnitTest::TestDetails const& details) : m_details(details) {} \
+        void RunImpl();                           \
+        UnitTest::TestDetails const& m_details;                                      \
+    private:                                                                         \
+        Fixture##Name##Helper(Fixture##Name##Helper const&);                         \
+        Fixture##Name##Helper& operator =(Fixture##Name##Helper const&);             \
+    };                                                                               \
+																					 \
+    class Test##Fixture##Name : public UnitTest::Test                                \
+    {                                                                                \
+    public:                                                                          \
+	    Test##Fixture##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \
+    private:                                                                         \
+        virtual void RunImpl() const;             \
+    } test##Fixture##Name##Instance;                                                 \
+																					 \
+    UnitTest::ListAdder adder##Fixture##Name (List, &test##Fixture##Name##Instance); \
+																					 \
+    void Test##Fixture##Name::RunImpl() const	 \
+	{																				 \
+		bool ctorOk = false;														 \
+		try {																		 \
+			Fixture##Name##Helper fixtureHelper(m_details);							 \
+			ctorOk = true;															 \
+			UnitTest::ExecuteTest(fixtureHelper, m_details);					 \
+		}																			 \
+		catch (UnitTest::AssertException const& e)											 \
+		{																			 \
+			UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); \
+		}																			 \
+		catch (std::exception const& e)												 \
+		{																			 \
+			UnitTest::MemoryOutStream stream;													 \
+			stream << "Unhandled exception: " << e.what();							 \
+			UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText());				 \
+		}																			 \
+		catch (...) {																 \
+			if (ctorOk)																 \
+			{																		 \
+	            UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__),	 \
+					"Unhandled exception while destroying fixture " #Fixture);		 \
+			}																		 \
+			else																	 \
+			{																		 \
+				UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__),   \
+					"Unhandled exception while constructing fixture " #Fixture);         \
+			}																		 \
+		}																			 \
+    }                                                                                \
+    void Fixture##Name##Helper::RunImpl()
+
+#define TEST_FIXTURE(Fixture,Name) TEST_FIXTURE_EX(Fixture, Name, UnitTest::Test::GetTestList())
+
+
+#endif

+ 10 - 0
3rdparty/UnitTest++/src/TestReporter.cpp

@@ -0,0 +1,10 @@
+#include "TestReporter.h"
+
+namespace UnitTest {
+
+
+TestReporter::~TestReporter()
+{
+}
+
+}

+ 20 - 0
3rdparty/UnitTest++/src/TestReporter.h

@@ -0,0 +1,20 @@
+#ifndef UNITTEST_TESTREPORTER_H
+#define UNITTEST_TESTREPORTER_H
+
+namespace UnitTest {
+
+class TestDetails;
+
+class TestReporter
+{
+public:
+    virtual ~TestReporter();
+
+    virtual void ReportTestStart(TestDetails const& test) = 0;
+    virtual void ReportFailure(TestDetails const& test, char const* failure) = 0;
+    virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed) = 0;
+    virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) = 0;
+};
+
+}
+#endif

+ 46 - 0
3rdparty/UnitTest++/src/TestReporterStdout.cpp

@@ -0,0 +1,46 @@
+#include "TestReporterStdout.h"
+#include <cstdio>
+
+#include "TestDetails.h"
+
+// cstdio doesn't pull in namespace std on VC6, so we do it here.
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+	namespace std {}
+#endif
+
+namespace UnitTest {
+
+void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure)
+{
+#if defined(__APPLE__) || defined(__GNUG__)
+    char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n";
+#else
+    char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n";
+#endif
+
+	using namespace std;
+    printf(errorFormat, details.filename, details.lineNumber, details.testName, failure);
+}
+
+void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/)
+{
+}
+
+void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float)
+{
+}
+
+void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount,
+                                       int const failureCount, float secondsElapsed)
+{
+	using namespace std;
+
+    if (failureCount > 0)
+        printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount);
+    else
+        printf("Success: %d tests passed.\n", totalTestCount);
+
+    printf("Test time: %.2f seconds.\n", secondsElapsed);
+}
+
+}

+ 19 - 0
3rdparty/UnitTest++/src/TestReporterStdout.h

@@ -0,0 +1,19 @@
+#ifndef UNITTEST_TESTREPORTERSTDOUT_H
+#define UNITTEST_TESTREPORTERSTDOUT_H
+
+#include "TestReporter.h"
+
+namespace UnitTest {
+
+class TestReporterStdout : public TestReporter
+{
+private:
+    virtual void ReportTestStart(TestDetails const& test);
+    virtual void ReportFailure(TestDetails const& test, char const* failure);
+    virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed);
+    virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed);
+};
+
+}
+
+#endif 

+ 60 - 0
3rdparty/UnitTest++/src/TestResults.cpp

@@ -0,0 +1,60 @@
+#include "TestResults.h"
+#include "TestReporter.h"
+
+#include "TestDetails.h"
+
+namespace UnitTest {
+
+TestResults::TestResults(TestReporter* testReporter)
+    : m_testReporter(testReporter)
+    , m_totalTestCount(0)
+    , m_failedTestCount(0)
+    , m_failureCount(0)
+    , m_currentTestFailed(false)
+{
+}
+
+void TestResults::OnTestStart(TestDetails const& test)
+{
+    ++m_totalTestCount;
+    m_currentTestFailed = false;
+    if (m_testReporter)
+        m_testReporter->ReportTestStart(test);
+}
+
+void TestResults::OnTestFailure(TestDetails const& test, char const* failure)
+{
+    ++m_failureCount;
+    if (!m_currentTestFailed)
+    {
+        ++m_failedTestCount;
+        m_currentTestFailed = true;
+    }
+
+    if (m_testReporter)
+        m_testReporter->ReportFailure(test, failure);
+}
+
+void TestResults::OnTestFinish(TestDetails const& test, float secondsElapsed)
+{
+    if (m_testReporter)
+        m_testReporter->ReportTestFinish(test, secondsElapsed);
+}
+
+int TestResults::GetTotalTestCount() const
+{
+    return m_totalTestCount;
+}
+
+int TestResults::GetFailedTestCount() const
+{
+    return m_failedTestCount;
+}
+
+int TestResults::GetFailureCount() const
+{
+    return m_failureCount;
+}
+
+
+}

+ 36 - 0
3rdparty/UnitTest++/src/TestResults.h

@@ -0,0 +1,36 @@
+#ifndef UNITTEST_TESTRESULTS_H
+#define UNITTEST_TESTRESULTS_H
+
+namespace UnitTest {
+
+class TestReporter;
+class TestDetails;
+
+class TestResults
+{
+public:
+    explicit TestResults(TestReporter* reporter = 0);
+
+    void OnTestStart(TestDetails const& test);
+    void OnTestFailure(TestDetails const& test, char const* failure);
+    void OnTestFinish(TestDetails const& test, float secondsElapsed);
+
+    int GetTotalTestCount() const;
+    int GetFailedTestCount() const;
+    int GetFailureCount() const;
+
+private:
+    TestReporter* m_testReporter;
+    int m_totalTestCount;
+    int m_failedTestCount;
+    int m_failureCount;
+
+    bool m_currentTestFailed;
+
+    TestResults(TestResults const&);
+    TestResults& operator =(TestResults const&);
+};
+
+}
+
+#endif

+ 76 - 0
3rdparty/UnitTest++/src/TestRunner.cpp

@@ -0,0 +1,76 @@
+#include "TestRunner.h"
+#include "TestResults.h"
+#include "TestReporter.h"
+#include "TestReporterStdout.h"
+#include "TimeHelpers.h"
+#include "MemoryOutStream.h"
+
+#include <cstring>
+
+
+namespace UnitTest {
+
+int RunAllTests()
+{
+	TestReporterStdout reporter;
+	TestRunner runner(reporter);
+	return runner.RunTestsIf(Test::GetTestList(), NULL, True(), 0);
+}
+
+
+TestRunner::TestRunner(TestReporter& reporter)
+	: m_reporter(&reporter)
+	, m_result(new TestResults(&reporter))
+	, m_timer(new Timer)
+{
+	m_timer->Start();
+}
+
+TestRunner::~TestRunner()
+{
+	delete m_result;
+	delete m_timer;
+}
+
+int TestRunner::Finish() const
+{
+    float const secondsElapsed = static_cast<float>(m_timer->GetTimeInMs() / 1000.0);
+    m_reporter->ReportSummary(m_result->GetTotalTestCount(), 
+							  m_result->GetFailedTestCount(), 
+							  m_result->GetFailureCount(), 
+							  secondsElapsed);
+    
+	return m_result->GetFailureCount();
+}
+
+bool TestRunner::IsTestInSuite(const Test* const curTest, char const* suiteName) const
+{
+	using namespace std;
+	return (suiteName == NULL) || !strcmp(curTest->m_details.suiteName, suiteName);
+}
+
+void TestRunner::RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const
+{
+	CurrentTest::Results() = result;
+
+	Timer testTimer;
+	testTimer.Start();
+
+	result->OnTestStart(curTest->m_details);
+
+	curTest->Run();
+
+	double const testTimeInMs = testTimer.GetTimeInMs();
+	if (maxTestTimeInMs > 0 && testTimeInMs > maxTestTimeInMs && !curTest->m_timeConstraintExempt)
+	{
+	    MemoryOutStream stream;
+	    stream << "Global time constraint failed. Expected under " << maxTestTimeInMs <<
+	            "ms but took " << testTimeInMs << "ms.";
+
+	    result->OnTestFailure(curTest->m_details, stream.GetText());
+	}
+
+	result->OnTestFinish(curTest->m_details, static_cast<float>(testTimeInMs/1000.0));
+}
+
+}

+ 59 - 0
3rdparty/UnitTest++/src/TestRunner.h

@@ -0,0 +1,59 @@
+#ifndef UNITTEST_TESTRUNNER_H
+#define UNITTEST_TESTRUNNER_H
+
+#include "Test.h"
+#include "TestList.h"
+#include "CurrentTest.h"
+
+namespace UnitTest {
+
+class TestReporter;
+class TestResults;
+class Timer;
+
+int RunAllTests();
+
+struct True
+{
+	bool operator()(const Test* const) const
+	{
+		return true;	
+	}
+};
+
+class TestRunner
+{
+public:
+	explicit TestRunner(TestReporter& reporter);
+	~TestRunner();
+
+	template <class Predicate>
+	int RunTestsIf(TestList const& list, char const* suiteName, 
+				   const Predicate& predicate, int maxTestTimeInMs) const
+	{
+	    Test* curTest = list.GetHead();
+
+	    while (curTest != 0)
+	    {
+		    if (IsTestInSuite(curTest, suiteName) && predicate(curTest))
+				RunTest(m_result, curTest, maxTestTimeInMs);
+
+			curTest = curTest->next;
+	    }
+
+	    return Finish();
+	}	
+
+private:
+	TestReporter* m_reporter;
+	TestResults* m_result;
+	Timer* m_timer;
+
+	int Finish() const;
+	bool IsTestInSuite(const Test* const curTest, char const* suiteName) const;
+	void RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const;
+};
+
+}
+
+#endif

+ 12 - 0
3rdparty/UnitTest++/src/TestSuite.h

@@ -0,0 +1,12 @@
+#ifndef UNITTEST_TESTSUITE_H
+#define UNITTEST_TESTSUITE_H
+
+namespace UnitTestSuite 
+{
+    inline char const* GetSuiteName ()
+    {
+        return "DefaultSuite";
+    }
+}
+
+#endif

+ 29 - 0
3rdparty/UnitTest++/src/TimeConstraint.cpp

@@ -0,0 +1,29 @@
+#include "TimeConstraint.h"
+#include "TestResults.h"
+#include "MemoryOutStream.h"
+#include "CurrentTest.h"
+
+namespace UnitTest {
+
+
+TimeConstraint::TimeConstraint(int ms, TestDetails const& details)
+	: m_details(details)
+    , m_maxMs(ms)
+{
+    m_timer.Start();
+}
+
+TimeConstraint::~TimeConstraint()
+{
+    double const totalTimeInMs = m_timer.GetTimeInMs();
+    if (totalTimeInMs > m_maxMs)
+    {
+        MemoryOutStream stream;
+        stream << "Time constraint failed. Expected to run test under " << m_maxMs <<
+                  "ms but took " << totalTimeInMs << "ms.";
+
+		UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText());
+    }
+}
+
+}

+ 33 - 0
3rdparty/UnitTest++/src/TimeConstraint.h

@@ -0,0 +1,33 @@
+#ifndef UNITTEST_TIMECONSTRAINT_H
+#define UNITTEST_TIMECONSTRAINT_H
+
+#include "TimeHelpers.h"
+
+namespace UnitTest {
+
+class TestResults;
+class TestDetails;
+
+class TimeConstraint
+{
+public:
+    TimeConstraint(int ms, TestDetails const& details);
+    ~TimeConstraint();
+
+private:
+    void operator=(TimeConstraint const&); 
+	TimeConstraint(TimeConstraint const&);
+
+	Timer m_timer;
+    TestDetails const& m_details;
+	int const m_maxMs;
+};
+
+#define UNITTEST_TIME_CONSTRAINT(ms) \
+	UnitTest::TimeConstraint unitTest__timeConstraint__(ms, UnitTest::TestDetails(m_details, __LINE__))
+
+#define UNITTEST_TIME_CONSTRAINT_EXEMPT() do { m_timeConstraintExempt = true; } while (0)
+
+}
+
+#endif

+ 7 - 0
3rdparty/UnitTest++/src/TimeHelpers.h

@@ -0,0 +1,7 @@
+#include "Config.h"
+
+#if defined UNITTEST_POSIX
+    #include "Posix/TimeHelpers.h"
+#else
+    #include "Win32/TimeHelpers.h"
+#endif

+ 18 - 0
3rdparty/UnitTest++/src/UnitTest++.h

@@ -0,0 +1,18 @@
+#ifndef UNITTESTCPP_H
+#define UNITTESTCPP_H
+
+//lint -esym(1509,*Fixture)
+
+#include "Config.h"
+#include "Test.h"
+#include "TestList.h"
+#include "TestSuite.h"
+#include "TestResults.h"
+
+#include "TestMacros.h"
+
+#include "CheckMacros.h"
+#include "TestRunner.h"
+#include "TimeConstraint.h"
+
+#endif

+ 47 - 0
3rdparty/UnitTest++/src/Win32/TimeHelpers.cpp

@@ -0,0 +1,47 @@
+#include "TimeHelpers.h"
+#include <windows.h>
+
+namespace UnitTest {
+
+Timer::Timer()
+	: m_threadHandle(::GetCurrentThread())
+	, m_startTime(0)
+{
+#if defined(_MSC_VER) && (_MSC_VER == 1200) // VC6 doesn't have DWORD_PTR?
+	typedef unsigned long DWORD_PTR;
+#endif
+
+	DWORD_PTR systemMask;
+	::GetProcessAffinityMask(GetCurrentProcess(), &m_processAffinityMask, &systemMask);
+	::SetThreadAffinityMask(m_threadHandle, 1);
+	::QueryPerformanceFrequency(reinterpret_cast< LARGE_INTEGER* >(&m_frequency));
+	::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask);
+}
+
+void Timer::Start()
+{
+	m_startTime = GetTime();
+}
+
+double Timer::GetTimeInMs() const
+{
+	__int64 const elapsedTime = GetTime() - m_startTime;
+	double const seconds = double(elapsedTime) / double(m_frequency);
+	return seconds * 1000.0;
+}
+
+__int64 Timer::GetTime() const
+{
+	LARGE_INTEGER curTime;
+	::SetThreadAffinityMask(m_threadHandle, 1);
+	::QueryPerformanceCounter(&curTime);
+	::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask);
+	return curTime.QuadPart;
+}
+
+void TimeHelpers::SleepMs(int const ms)
+{
+	::Sleep(ms);
+}
+
+}

+ 48 - 0
3rdparty/UnitTest++/src/Win32/TimeHelpers.h

@@ -0,0 +1,48 @@
+#ifndef UNITTEST_TIMEHELPERS_H
+#define UNITTEST_TIMEHELPERS_H
+
+#include "../Config.h"
+
+
+#ifdef UNITTEST_MINGW
+    #ifndef __int64
+        #define __int64 long long
+    #endif
+#endif
+
+namespace UnitTest {
+
+class Timer
+{
+public:
+    Timer();
+	void Start();
+	double GetTimeInMs() const;    
+
+private:
+    __int64 GetTime() const;
+
+    void* m_threadHandle;
+
+#if defined(_WIN64)
+    unsigned __int64 m_processAffinityMask;
+#else
+    unsigned long m_processAffinityMask;
+#endif
+
+	__int64 m_startTime;
+	__int64 m_frequency;
+};
+
+
+namespace TimeHelpers
+{
+void SleepMs (int ms);
+}
+
+
+}
+
+
+
+#endif

+ 127 - 0
3rdparty/UnitTest++/src/XmlTestReporter.cpp

@@ -0,0 +1,127 @@
+#include "XmlTestReporter.h"
+#include "Config.h"
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+using std::string;
+using std::ostringstream;
+using std::ostream;
+
+namespace {
+
+void ReplaceChar(string& str, char c, string const& replacement)
+{
+    for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1))
+        str.replace(pos, 1, replacement);
+}
+
+string XmlEscape(string const& value)
+{
+    string escaped = value;
+
+    ReplaceChar(escaped, '&', "&amp;");
+    ReplaceChar(escaped, '<', "&lt;");
+    ReplaceChar(escaped, '>', "&gt;");
+    ReplaceChar(escaped, '\'', "&apos;");
+    ReplaceChar(escaped, '\"', "&quot;");
+ 
+    return escaped;
+}
+
+string BuildFailureMessage(string const& file, int line, string const& message)
+{
+    ostringstream failureMessage;
+    failureMessage << file << "(" << line << ") : " << message;
+    return failureMessage.str();
+}
+
+}
+
+namespace UnitTest {
+
+XmlTestReporter::XmlTestReporter(ostream& ostream)
+    : m_ostream(ostream)
+{
+}
+
+void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount,
+                                    int failureCount, float secondsElapsed)
+{
+    AddXmlElement(m_ostream, NULL);
+
+    BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed);
+
+    DeferredTestResultList const& results = GetResults();
+    for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i)
+    {
+        BeginTest(m_ostream, *i);
+
+        if (i->failed)
+            AddFailure(m_ostream, *i);
+
+        EndTest(m_ostream, *i);
+    }
+
+    EndResults(m_ostream);
+}
+
+void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding)
+{
+    os << "<?xml version=\"1.0\"";
+
+    if (encoding != NULL)
+        os << " encoding=\"" << encoding << "\"";
+
+    os << "?>";
+}
+
+void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, 
+                                   int failureCount, float secondsElapsed)
+{
+   os << "<unittest-results"
+       << " tests=\"" << totalTestCount << "\"" 
+       << " failedtests=\"" << failedTestCount << "\"" 
+       << " failures=\"" << failureCount << "\"" 
+       << " time=\"" << secondsElapsed << "\""
+       << ">";
+}
+
+void XmlTestReporter::EndResults(std::ostream& os)
+{
+    os << "</unittest-results>";
+}
+
+void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result)
+{
+    os << "<test"
+        << " suite=\"" << result.suiteName << "\"" 
+        << " name=\"" << result.testName << "\""
+        << " time=\"" << result.timeElapsed << "\"";
+}
+
+void XmlTestReporter::EndTest(std::ostream& os, DeferredTestResult const& result)
+{
+    if (result.failed)
+        os << "</test>";
+    else
+        os << "/>";
+}
+
+void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result)
+{
+    os << ">"; // close <test> element
+
+    for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin(); 
+         it != result.failures.end(); 
+         ++it)
+    {
+        string const escapedMessage = XmlEscape(it->second);
+        string const message = BuildFailureMessage(result.failureFile, it->first, escapedMessage);
+
+        os << "<failure" << " message=\"" << message << "\"" << "/>";
+    }
+}
+
+}

+ 34 - 0
3rdparty/UnitTest++/src/XmlTestReporter.h

@@ -0,0 +1,34 @@
+#ifndef UNITTEST_XMLTESTREPORTER_H
+#define UNITTEST_XMLTESTREPORTER_H
+
+#include "DeferredTestReporter.h"
+
+#include <iosfwd>
+
+namespace UnitTest
+{
+
+class XmlTestReporter : public DeferredTestReporter
+{
+public:
+    explicit XmlTestReporter(std::ostream& ostream);
+
+    virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed);
+
+private:
+    XmlTestReporter(XmlTestReporter const&);
+    XmlTestReporter& operator=(XmlTestReporter const&);
+
+    void AddXmlElement(std::ostream& os, char const* encoding);
+    void BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed);
+    void EndResults(std::ostream& os);
+    void BeginTest(std::ostream& os, DeferredTestResult const& result);
+    void AddFailure(std::ostream& os, DeferredTestResult const& result);
+    void EndTest(std::ostream& os, DeferredTestResult const& result);
+
+    std::ostream& m_ostream;
+};
+
+}
+
+#endif

+ 8 - 0
3rdparty/UnitTest++/src/tests/Main.cpp

@@ -0,0 +1,8 @@
+#include "../UnitTest++.h"
+#include "../TestReporterStdout.h"
+
+
+int main(int, char const *[])
+{
+    return UnitTest::RunAllTests();
+}

+ 98 - 0
3rdparty/UnitTest++/src/tests/RecordingReporter.h

@@ -0,0 +1,98 @@
+#ifndef UNITTEST_RECORDINGREPORTER_H
+#define UNITTEST_RECORDINGREPORTER_H
+
+#include "../TestReporter.h"
+#include <cstring>
+
+#include "../TestDetails.h"
+
+struct RecordingReporter : public UnitTest::TestReporter
+{
+private:
+    enum { kMaxStringLength = 256 };
+
+public:
+    RecordingReporter()
+        : testRunCount(0)
+        , testFailedCount(0)
+        , lastFailedLine(0)
+        , testFinishedCount(0)
+        , lastFinishedTestTime(0)
+        , summaryTotalTestCount(0)
+        , summaryFailedTestCount(0)
+        , summaryFailureCount(0)
+        , summarySecondsElapsed(0)
+    {
+        lastStartedSuite[0] = '\0';
+        lastStartedTest[0] = '\0';
+        lastFailedFile[0] = '\0';
+        lastFailedSuite[0] = '\0';
+        lastFailedTest[0] = '\0';
+        lastFailedMessage[0] = '\0';
+        lastFinishedSuite[0] = '\0';
+        lastFinishedTest[0] = '\0';
+    }
+
+    virtual void ReportTestStart(UnitTest::TestDetails const& test)
+    {
+		using namespace std;
+
+        ++testRunCount;
+        strcpy(lastStartedSuite, test.suiteName);
+        strcpy(lastStartedTest, test.testName);
+    }
+
+    virtual void ReportFailure(UnitTest::TestDetails const& test, char const* failure)
+    {
+		using namespace std;
+
+		++testFailedCount;
+        strcpy(lastFailedFile, test.filename);
+        lastFailedLine = test.lineNumber;
+        strcpy(lastFailedSuite, test.suiteName);
+        strcpy(lastFailedTest, test.testName);
+        strcpy(lastFailedMessage, failure);
+    }
+
+    virtual void ReportTestFinish(UnitTest::TestDetails const& test, float testDuration)
+    {
+		using namespace std;
+
+		++testFinishedCount;
+        strcpy(lastFinishedSuite, test.suiteName);
+        strcpy(lastFinishedTest, test.testName);
+        lastFinishedTestTime = testDuration;
+    }
+
+    virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) 
+    {
+        summaryTotalTestCount = totalTestCount;
+        summaryFailedTestCount = failedTestCount;
+        summaryFailureCount = failureCount;
+        summarySecondsElapsed = secondsElapsed;
+    }
+
+    int testRunCount;
+    char lastStartedSuite[kMaxStringLength];
+    char lastStartedTest[kMaxStringLength];
+
+    int testFailedCount;
+    char lastFailedFile[kMaxStringLength];
+    int lastFailedLine;
+    char lastFailedSuite[kMaxStringLength];
+    char lastFailedTest[kMaxStringLength];
+    char lastFailedMessage[kMaxStringLength];
+
+    int testFinishedCount;
+    char lastFinishedSuite[kMaxStringLength];
+    char lastFinishedTest[kMaxStringLength];
+    float lastFinishedTestTime;
+
+    int summaryTotalTestCount;
+    int summaryFailedTestCount;
+    int summaryFailureCount;
+    float summarySecondsElapsed;
+};
+
+
+#endif

+ 37 - 0
3rdparty/UnitTest++/src/tests/ScopedCurrentTest.h

@@ -0,0 +1,37 @@
+#ifndef UNITTEST_SCOPEDCURRENTTEST_H
+#define UNITTEST_SCOPEDCURRENTTEST_H
+
+#include "../CurrentTest.h"
+#include <cstddef>
+
+class ScopedCurrentTest
+{
+public:
+	ScopedCurrentTest()
+		: m_oldTestResults(UnitTest::CurrentTest::Results())
+		, m_oldTestDetails(UnitTest::CurrentTest::Details())
+	{
+	}
+
+	explicit ScopedCurrentTest(UnitTest::TestResults& newResults, const UnitTest::TestDetails* newDetails = NULL)
+		: m_oldTestResults(UnitTest::CurrentTest::Results())
+		, m_oldTestDetails(UnitTest::CurrentTest::Details())
+	{
+		UnitTest::CurrentTest::Results() = &newResults;
+
+		if (newDetails != NULL)
+			UnitTest::CurrentTest::Details() = newDetails;
+	}
+
+	~ScopedCurrentTest()
+	{
+		UnitTest::CurrentTest::Results() = m_oldTestResults;
+		UnitTest::CurrentTest::Details() = m_oldTestDetails;
+	}
+
+private:
+	UnitTest::TestResults* m_oldTestResults;
+	const UnitTest::TestDetails* m_oldTestDetails;
+};
+
+#endif

+ 44 - 0
3rdparty/UnitTest++/src/tests/TestAssertHandler.cpp

@@ -0,0 +1,44 @@
+#include "../UnitTest++.h"
+#include "../AssertException.h"
+#include "../ReportAssert.h"
+
+using namespace UnitTest;
+
+namespace {
+
+TEST(ReportAssertThrowsAssertException)
+{
+    bool caught = false;
+
+    try
+    {
+        ReportAssert("", "", 0);
+    }
+    catch(AssertException const&)
+    {
+        caught = true;
+    }
+
+    CHECK (true == caught);
+}
+
+TEST(ReportAssertSetsCorrectInfoInException)
+{
+    const int lineNumber = 12345;
+    const char* description = "description";
+    const char* filename = "filename";
+
+    try
+    {
+        ReportAssert(description, filename, lineNumber);
+    }
+    catch(AssertException const& e)
+    {
+        CHECK_EQUAL(description, e.what());
+        CHECK_EQUAL(filename, e.Filename());
+        CHECK_EQUAL(lineNumber, e.LineNumber());
+    }
+}
+
+
+}

+ 801 - 0
3rdparty/UnitTest++/src/tests/TestCheckMacros.cpp

@@ -0,0 +1,801 @@
+#include "../UnitTest++.h"
+#include "../CurrentTest.h"
+#include "RecordingReporter.h"
+#include "ScopedCurrentTest.h"
+
+using namespace std;
+
+namespace {
+
+TEST(CheckSucceedsOnTrue)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+
+		ScopedCurrentTest scopedResults(testResults);
+		CHECK(true);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckFailsOnFalse)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK(false);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(FailureReportsCorrectTestName)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK(false);
+    }
+
+    CHECK_EQUAL(m_details.testName, reporter.lastFailedTest);
+}
+
+TEST(CheckFailureIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        const bool yaddayadda = false;
+        CHECK(yaddayadda);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "yaddayadda"));
+}
+
+int ThrowingFunction()
+{
+    throw "Doh";
+}
+
+TEST(CheckFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK(ThrowingFunction() == 1);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckFailureBecauseOfExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK(ThrowingFunction() == 1);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "ThrowingFunction() == 1"));
+}
+
+TEST(CheckEqualSucceedsOnEqual)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(1, 1);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckEqualFailsOnNotEqual)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(1, 2);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckEqualFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(ThrowingFunction(), 1);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckEqualFailureContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails const testDetails("testName", "suiteName", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		CHECK_EQUAL(1, 123);    line = __LINE__;
+    }
+
+    CHECK_EQUAL("testName", reporter.lastFailedTest);
+    CHECK_EQUAL("suiteName", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckEqualFailureBecauseOfExceptionContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails const testDetails("testName", "suiteName", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		CHECK_EQUAL(ThrowingFunction(), 123);    line = __LINE__;
+    }
+
+    CHECK_EQUAL("testName", reporter.lastFailedTest);
+    CHECK_EQUAL("suiteName", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckEqualFailureBecauseOfExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(ThrowingFunction(), 123);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "ThrowingFunction()"));
+    CHECK(strstr(reporter.lastFailedMessage, "123"));
+}
+
+int g_sideEffect = 0;
+int FunctionWithSideEffects()
+{
+    ++g_sideEffect;
+    return 1;
+}
+
+TEST(CheckEqualDoesNotHaveSideEffectsWhenPassing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(1, FunctionWithSideEffects());
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckEqualDoesNotHaveSideEffectsWhenFailing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_EQUAL(2, FunctionWithSideEffects());
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+
+TEST(CheckCloseSucceedsOnEqual)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE (1.0f, 1.001f, 0.01f);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckCloseFailsOnNotEqual)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE (1.0f, 1.1f, 0.01f);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckCloseFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckCloseFailureContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("test", "suite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		CHECK_CLOSE (1.0f, 1.1f, 0.01f);    line = __LINE__;
+    }
+
+    CHECK_EQUAL("test", reporter.lastFailedTest);
+    CHECK_EQUAL("suite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("closeTest", "closeSuite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+        CHECK_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f);    line = __LINE__;
+    }
+
+    CHECK_EQUAL("closeTest", reporter.lastFailedTest);
+    CHECK_EQUAL("closeSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckCloseFailureBecauseOfExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE ((float)ThrowingFunction(), 1.0001f, 0.1f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "(float)ThrowingFunction()"));
+    CHECK(strstr(reporter.lastFailedMessage, "1.0001f"));
+}
+
+TEST(CheckCloseDoesNotHaveSideEffectsWhenPassing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE (1, FunctionWithSideEffects(), 0.1f);
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckCloseDoesNotHaveSideEffectsWhenFailing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+        CHECK_CLOSE (2, FunctionWithSideEffects(), 0.1f);
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+
+class ThrowingObject
+{
+public:
+    float operator[](int) const
+    {
+        throw "Test throw";
+    }
+};
+
+
+TEST(CheckArrayCloseSucceedsOnEqual)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+        const float data[4] = { 0, 1, 2, 3 };
+        CHECK_ARRAY_CLOSE (data, data, 4, 0.01f);
+        failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckArrayCloseFailsOnNotEqual)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+		CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArrayCloseFailureIncludesCheckExpectedAndActual)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]"));
+    CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]"));
+}
+
+TEST(CheckArrayCloseFailureContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("arrayCloseTest", "arrayCloseSuite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f);     line = __LINE__;
+    }
+
+    CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArrayCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("arrayCloseTest", "arrayCloseSuite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		int const data[4] = { 0, 1, 2, 3 };
+        CHECK_ARRAY_CLOSE (data, ThrowingObject(), 4, 0.01f);     line = __LINE__;
+    }
+
+    CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArrayCloseFailureIncludesTolerance)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		float const data1[4] = { 0, 1, 2, 3 };
+        float const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_CLOSE (data1, data2, 4, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+
+TEST(CheckArrayCloseFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[4] = { 0, 1, 2, 3 };
+        ThrowingObject obj;
+        CHECK_ARRAY_CLOSE (data, obj, 3, 0.01f);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArrayCloseFailureOnExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[4] = { 0, 1, 2, 3 };
+        ThrowingObject obj;
+        CHECK_ARRAY_CLOSE (data, obj, 3, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "data"));
+    CHECK(strstr(reporter.lastFailedMessage, "obj"));
+}
+
+
+TEST(CheckArrayEqualSuceedsOnEqual)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[4] = { 0, 1, 2, 3 };
+        CHECK_ARRAY_EQUAL (data, data, 4);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckArrayEqualFailsOnNotEqual)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_EQUAL (data1, data2, 4);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArrayEqualFailureIncludesCheckExpectedAndActual)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_EQUAL (data1, data2, 4);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "xpected [ 0 1 2 3 ]"));
+    CHECK(strstr(reporter.lastFailedMessage, "was [ 0 1 3 3 ]"));
+}
+
+TEST(CheckArrayEqualFailureContainsCorrectInfo)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[4] = { 0, 1, 2, 3 };
+        int const data2[4] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_EQUAL (data1, data2, 4);     line = __LINE__;
+    }
+
+    CHECK_EQUAL("CheckArrayEqualFailureContainsCorrectInfo", reporter.lastFailedTest);
+    CHECK_EQUAL(__FILE__, reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArrayEqualFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[4] = { 0, 1, 2, 3 };
+        ThrowingObject obj;
+        CHECK_ARRAY_EQUAL (data, obj, 3);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArrayEqualFailureOnExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[4] = { 0, 1, 2, 3 };
+        ThrowingObject obj;
+        CHECK_ARRAY_EQUAL (data, obj, 3);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "data"));
+    CHECK(strstr(reporter.lastFailedMessage, "obj"));
+}
+
+float const* FunctionWithSideEffects2()
+{
+    ++g_sideEffect;
+    static float const data[] = {1,2,3,4};
+    return data;
+}
+
+TEST(CheckArrayCloseDoesNotHaveSideEffectsWhenPassing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[] = { 0, 1, 2, 3 };
+        CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f);
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckArrayCloseDoesNotHaveSideEffectsWhenFailing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[] = { 0, 1, 3, 3 };
+        CHECK_ARRAY_CLOSE (data, FunctionWithSideEffects2(), 4, 0.01f);
+    }
+
+	CHECK_EQUAL(1, g_sideEffect);
+}
+
+class ThrowingObject2D
+{
+public:
+    float* operator[](int) const
+    {
+        throw "Test throw";
+    }
+};
+
+
+TEST(CheckArray2DCloseSucceedsOnEqual)
+{
+    bool failure = true;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[2][2] = { {0, 1}, {2, 3} };
+        CHECK_ARRAY2D_CLOSE (data, data, 2, 2, 0.01f);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(!failure);
+}
+
+TEST(CheckArray2DCloseFailsOnNotEqual)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[2][2] = { {0, 1}, {2, 3} };
+        int const data2[2][2] = { {0, 1}, {3, 3} };
+        CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArray2DCloseFailureIncludesCheckExpectedAndActual)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		int const data1[2][2] = { {0, 1}, {2, 3} };
+        int const data2[2][2] = { {0, 1}, {3, 3} };
+
+		CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "xpected [ [ 0 1 ] [ 2 3 ] ]"));
+    CHECK(strstr(reporter.lastFailedMessage, "was [ [ 0 1 ] [ 3 3 ] ]"));
+}
+
+TEST(CheckArray2DCloseFailureContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("array2DCloseTest", "array2DCloseSuite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		int const data1[2][2] = { {0, 1}, {2, 3} };
+        int const data2[2][2] = { {0, 1}, {3, 3} };
+		CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f);     line = __LINE__;
+    }
+
+    CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArray2DCloseFailureBecauseOfExceptionContainsCorrectDetails)
+{
+    int line = 0;
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		UnitTest::TestDetails testDetails("array2DCloseTest", "array2DCloseSuite", "filename", -1);
+		ScopedCurrentTest scopedResults(testResults, &testDetails);
+
+		const float data[2][2] = { {0, 1}, {2, 3} };
+        CHECK_ARRAY2D_CLOSE (data, ThrowingObject2D(), 2, 2, 0.01f);   line = __LINE__;
+    }
+
+    CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("filename", reporter.lastFailedFile);
+    CHECK_EQUAL(line, reporter.lastFailedLine);
+}
+
+TEST(CheckArray2DCloseFailureIncludesTolerance)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		float const data1[2][2] = { {0, 1}, {2, 3} };
+        float const data2[2][2] = { {0, 1}, {3, 3} };
+        CHECK_ARRAY2D_CLOSE (data1, data2, 2, 2, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+TEST(CheckArray2DCloseFailsOnException)
+{
+    bool failure = false;
+    {
+        RecordingReporter reporter;
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[2][2] = { {0, 1}, {2, 3} };
+        ThrowingObject2D obj;
+        CHECK_ARRAY2D_CLOSE (data, obj, 2, 2, 0.01f);
+
+		failure = (testResults.GetFailureCount() > 0);
+    }
+
+    CHECK(failure);
+}
+
+TEST(CheckArray2DCloseFailureOnExceptionIncludesCheckContents)
+{
+    RecordingReporter reporter;
+    {
+        UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[2][2] = { {0, 1}, {2, 3} };
+        ThrowingObject2D obj;
+        CHECK_ARRAY2D_CLOSE (data, obj, 2, 2, 0.01f);
+    }
+
+    CHECK(strstr(reporter.lastFailedMessage, "data"));
+    CHECK(strstr(reporter.lastFailedMessage, "obj"));
+}
+
+float const* const* FunctionWithSideEffects3()
+{
+    ++g_sideEffect;
+    static float const data1[] = {0,1};
+    static float const data2[] = {2,3};
+    static const float* const data[] = {data1, data2};
+    return data;
+}
+
+TEST(CheckArray2DCloseDoesNotHaveSideEffectsWhenPassing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[2][2] = { {0, 1}, {2, 3} };
+        CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f);
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+TEST(CheckArray2DCloseDoesNotHaveSideEffectsWhenFailing)
+{
+    g_sideEffect = 0;
+    {
+        UnitTest::TestResults testResults;
+		ScopedCurrentTest scopedResults(testResults);
+
+		const float data[2][2] = { {0, 1}, {3, 3} };
+        CHECK_ARRAY2D_CLOSE (data, FunctionWithSideEffects3(), 2, 2, 0.01f);
+    }
+    CHECK_EQUAL(1, g_sideEffect);
+}
+
+}

+ 293 - 0
3rdparty/UnitTest++/src/tests/TestChecks.cpp

@@ -0,0 +1,293 @@
+#include "../UnitTest++.h"
+#include "RecordingReporter.h"
+
+using namespace UnitTest;
+
+
+namespace {
+
+
+TEST(CheckEqualWithUnsignedLong)
+{
+    TestResults results;
+    unsigned long something = 2;
+    CHECK_EQUAL(something, something);
+}
+
+TEST(CheckEqualsWithStringsFailsOnDifferentStrings)
+{
+    char txt1[] = "Hello";
+    char txt2[] = "Hallo";
+    TestResults results;
+    CheckEqual(results, txt1, txt2, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+char txt1[] = "Hello"; // non-const on purpose so no folding of duplicate data
+char txt2[] = "Hello";
+
+TEST(CheckEqualsWithStringsWorksOnContentsNonConstNonConst)
+{
+    char const* const p1 = txt1;
+    char const* const p2 = txt2;
+    TestResults results;
+    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckEqualsWithStringsWorksOnContentsConstConst)
+{
+    char* const p1 = txt1;
+    char* const p2 = txt2;
+    TestResults results;
+    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckEqualsWithStringsWorksOnContentsNonConstConst)
+{
+    char* const p1 = txt1;
+    char const* const p2 = txt2;
+    TestResults results;
+    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckEqualsWithStringsWorksOnContentsConstNonConst)
+{
+    char const* const p1 = txt1;
+    char* const p2 = txt2;
+    TestResults results;
+    CheckEqual(results, p1, p2, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckEqualsWithStringsWorksOnContentsWithALiteral)
+{
+    char const* const p1 = txt1;
+    TestResults results;
+    CheckEqual(results, "Hello", p1, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckEqualFailureIncludesCheckExpectedAndActual)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    const int something = 2;
+    CheckEqual(results, 1, something, TestDetails("", "", "", 0));
+
+	using namespace std;
+    CHECK(strstr(reporter.lastFailedMessage, "xpected 1"));
+    CHECK(strstr(reporter.lastFailedMessage, "was 2"));
+}
+
+TEST(CheckEqualFailureIncludesDetails)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    TestDetails const details("mytest", "mysuite", "file.h", 101);
+
+    CheckEqual(results, 1, 2, details);
+
+    CHECK_EQUAL("mytest", reporter.lastFailedTest);
+    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("file.h", reporter.lastFailedFile);
+    CHECK_EQUAL(101, reporter.lastFailedLine);
+}
+
+TEST(CheckCloseTrue)
+{
+    TestResults results;
+    CheckClose(results, 3.001f, 3.0f, 0.1f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckCloseFalse)
+{
+    TestResults results;
+    CheckClose(results, 3.12f, 3.0f, 0.1f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckCloseWithZeroEpsilonWorksForSameNumber)
+{
+    TestResults results;
+    CheckClose(results, 0.1f, 0.1f, 0, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckCloseWithNaNFails)
+{
+    union
+    {
+        unsigned int bitpattern;
+        float nan;
+    };
+    bitpattern = 0xFFFFFFFF;
+    TestResults results;
+    CheckClose(results, 3.0f, nan, 0.1f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckCloseWithNaNAgainstItselfFails)
+{
+    union
+    {
+        unsigned int bitpattern;
+        float nan;
+    };
+    bitpattern = 0xFFFFFFFF;
+    TestResults results;
+    CheckClose(results, nan, nan, 0.1f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckCloseFailureIncludesCheckExpectedAndActual)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    const float expected = 0.9f;
+    const float actual = 1.1f;
+    CheckClose(results, expected, actual, 0.01f, TestDetails("", "", "", 0));
+
+	using namespace std;
+    CHECK(strstr(reporter.lastFailedMessage, "xpected 0.9"));
+    CHECK(strstr(reporter.lastFailedMessage, "was 1.1"));
+}
+
+TEST(CheckCloseFailureIncludesTolerance)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    CheckClose(results, 2, 3, 0.01f, TestDetails("", "", "", 0));
+
+	using namespace std;
+    CHECK(strstr(reporter.lastFailedMessage, "0.01"));
+}
+
+TEST(CheckCloseFailureIncludesDetails)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    TestDetails const details("mytest", "mysuite", "header.h", 10);
+
+    CheckClose(results, 2, 3, 0.01f, details);
+
+    CHECK_EQUAL("mytest", reporter.lastFailedTest);
+    CHECK_EQUAL("mysuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("header.h", reporter.lastFailedFile);
+    CHECK_EQUAL(10, reporter.lastFailedLine);
+}
+
+
+TEST(CheckArrayEqualTrue)
+{
+    TestResults results;
+
+    int const array[3] = { 1, 2, 3 };
+    CheckArrayEqual(results, array, array, 3, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckArrayEqualFalse)
+{
+    TestResults results;
+
+    int const array1[3] = { 1, 2, 3 };
+    int const array2[3] = { 1, 2, 2 };
+    CheckArrayEqual(results, array1, array2, 3, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckArrayCloseTrue)
+{
+    TestResults results;
+
+    float const array1[3] = { 1.0f, 1.5f, 2.0f };
+    float const array2[3] = { 1.01f, 1.51f, 2.01f };
+    CheckArrayClose(results, array1, array2, 3, 0.02f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckArrayCloseFalse)
+{
+    TestResults results;
+
+    float const array1[3] = { 1.0f, 1.5f, 2.0f };
+    float const array2[3] = { 1.01f, 1.51f, 2.01f };
+    CheckArrayClose(results, array1, array2, 3, 0.001f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckArrayCloseFailureIncludesDetails)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    TestDetails const details("arrayCloseTest", "arrayCloseSuite", "file", 1337);
+
+    float const array1[3] = { 1.0f, 1.5f, 2.0f };
+    float const array2[3] = { 1.01f, 1.51f, 2.01f };
+    CheckArrayClose(results, array1, array2, 3, 0.001f, details);
+
+    CHECK_EQUAL("arrayCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("arrayCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("file", reporter.lastFailedFile);
+    CHECK_EQUAL(1337, reporter.lastFailedLine);
+}
+
+
+TEST(CheckArray2DCloseTrue)
+{
+    TestResults results;
+
+    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+                                 { 2.0f, 2.5f, 3.0f },
+                                 { 3.0f, 3.5f, 4.0f } };
+    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+                                 { 2.01f, 2.51f, 3.01f },
+                                 { 3.01f, 3.51f, 4.01f } };
+    CheckArray2DClose(results, array1, array2, 3, 3, 0.02f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+TEST(CheckArray2DCloseFalse)
+{
+    TestResults results;
+
+    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+                                 { 2.0f, 2.5f, 3.0f },
+                                 { 3.0f, 3.5f, 4.0f } };
+    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+                                 { 2.01f, 2.51f, 3.01f },
+                                 { 3.01f, 3.51f, 4.01f } };
+    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, TestDetails("", "", "", 0));
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckCloseWithDoublesSucceeds)
+{
+    CHECK_CLOSE(0.5, 0.5, 0.0001);
+}
+
+TEST(CheckArray2DCloseFailureIncludesDetails)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    TestDetails const details("array2DCloseTest", "array2DCloseSuite", "file", 1234);
+
+    float const array1[3][3] = { { 1.0f, 1.5f, 2.0f },
+                                 { 2.0f, 2.5f, 3.0f },
+                                 { 3.0f, 3.5f, 4.0f } };
+    float const array2[3][3] = { { 1.01f, 1.51f, 2.01f },
+                                 { 2.01f, 2.51f, 3.01f },
+                                 { 3.01f, 3.51f, 4.01f } };
+    CheckArray2DClose(results, array1, array2, 3, 3, 0.001f, details);
+
+    CHECK_EQUAL("array2DCloseTest", reporter.lastFailedTest);
+    CHECK_EQUAL("array2DCloseSuite", reporter.lastFailedSuite);
+    CHECK_EQUAL("file", reporter.lastFailedFile);
+    CHECK_EQUAL(1234, reporter.lastFailedLine);
+}
+
+}

+ 38 - 0
3rdparty/UnitTest++/src/tests/TestCurrentTest.cpp

@@ -0,0 +1,38 @@
+#include "../UnitTest++.h"
+#include "../CurrentTest.h"
+#include "ScopedCurrentTest.h"
+
+namespace 
+{
+
+TEST(CanSetandGetDetails)
+{
+	bool ok = false;
+	{
+		ScopedCurrentTest scopedTest;
+
+		const UnitTest::TestDetails* details = reinterpret_cast< const UnitTest::TestDetails* >(12345);
+		UnitTest::CurrentTest::Details() = details;
+
+		ok = (UnitTest::CurrentTest::Details() == details);
+	}
+
+	CHECK(ok);
+}
+
+TEST(CanSetAndGetResults)
+{
+	bool ok = false;
+	{
+		ScopedCurrentTest scopedTest;
+
+		UnitTest::TestResults results;
+		UnitTest::CurrentTest::Results() = &results;
+
+		ok = (UnitTest::CurrentTest::Results() == &results);
+	}
+
+	CHECK(ok);
+}
+
+}

+ 117 - 0
3rdparty/UnitTest++/src/tests/TestDeferredTestReporter.cpp

@@ -0,0 +1,117 @@
+#include "../UnitTest++.h"
+#include "../DeferredTestReporter.h"
+#include "../Config.h"
+#include <cstring>
+
+namespace UnitTest
+{
+
+namespace 
+{
+
+#ifdef UNITTEST_USE_CUSTOM_STREAMS
+	MemoryOutStream& operator <<(MemoryOutStream& lhs, const std::string& rhs)
+	{
+		lhs << rhs.c_str();
+		return lhs;
+	}
+#endif
+
+struct MockDeferredTestReporter : public DeferredTestReporter
+{
+    virtual void ReportSummary(int, int, int, float) 
+    {
+    }
+};
+
+struct DeferredTestReporterFixture
+{
+    DeferredTestReporterFixture()
+        : testName("UniqueTestName")
+        , testSuite("UniqueTestSuite")
+        , fileName("filename.h")
+        , lineNumber(12)
+        , details(testName.c_str(), testSuite.c_str(), fileName.c_str(), lineNumber)
+    {
+    }
+
+    MockDeferredTestReporter reporter;
+    std::string const testName;
+    std::string const testSuite;
+    std::string const fileName;
+    int const lineNumber;
+    TestDetails const details;
+};
+
+TEST_FIXTURE(DeferredTestReporterFixture, ReportTestStartCreatesANewDeferredTest)
+{
+    reporter.ReportTestStart(details);
+    CHECK_EQUAL(1, (int)reporter.GetResults().size());
+}
+
+TEST_FIXTURE(DeferredTestReporterFixture, ReportTestStartCapturesTestNameAndSuite)
+{
+    reporter.ReportTestStart(details);
+
+    DeferredTestResult const& result = reporter.GetResults().at(0);
+    CHECK_EQUAL(testName.c_str(), result.testName);
+    CHECK_EQUAL(testSuite.c_str(), result.suiteName);
+}
+
+TEST_FIXTURE(DeferredTestReporterFixture, ReportTestEndCapturesTestTime)
+{
+    float const elapsed = 123.45f;
+    reporter.ReportTestStart(details);
+    reporter.ReportTestFinish(details, elapsed);
+
+    DeferredTestResult const& result = reporter.GetResults().at(0);
+    CHECK_CLOSE(elapsed, result.timeElapsed, 0.0001f);
+}
+
+TEST_FIXTURE(DeferredTestReporterFixture, ReportFailureSavesFailureDetails)
+{
+    char const* failure = "failure";
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, failure);
+
+    DeferredTestResult const& result = reporter.GetResults().at(0);
+    CHECK(result.failed == true);
+    CHECK_EQUAL(fileName.c_str(), result.failureFile);
+}
+
+TEST_FIXTURE(DeferredTestReporterFixture, ReportFailureSavesFailureDetailsForMultipleFailures)
+{
+    char const* failure1 = "failure 1";
+    char const* failure2 = "failure 2";
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, failure1);
+    reporter.ReportFailure(details, failure2);
+
+    DeferredTestResult const& result = reporter.GetResults().at(0);
+    CHECK_EQUAL(2, (int)result.failures.size());
+    CHECK_EQUAL(failure1, result.failures[0].second);
+    CHECK_EQUAL(failure2, result.failures[1].second);
+}
+
+TEST_FIXTURE(DeferredTestReporterFixture, DeferredTestReporterTakesCopyOfFailureMessage)
+{
+    reporter.ReportTestStart(details);
+
+    char failureMessage[128];
+    char const* goodStr = "Real failure message";
+    char const* badStr = "Bogus failure message";
+    
+	using namespace std;
+
+    strcpy(failureMessage, goodStr);
+    reporter.ReportFailure(details, failureMessage);
+    strcpy(failureMessage, badStr);
+
+    DeferredTestResult const& result = reporter.GetResults().at(0);
+    DeferredTestResult::Failure const& failure = result.failures.at(0);
+    CHECK_EQUAL(goodStr, failure.second);
+}
+
+}}

+ 151 - 0
3rdparty/UnitTest++/src/tests/TestMemoryOutStream.cpp

@@ -0,0 +1,151 @@
+#include "../UnitTest++.h"
+
+#include "../MemoryOutStream.h"
+#include <cstring>
+
+using namespace UnitTest;
+using namespace std;
+
+namespace {
+
+TEST(DefaultIsEmptyString)
+{
+    MemoryOutStream const stream;
+    CHECK(stream.GetText() != 0);
+    CHECK_EQUAL("", stream.GetText());
+}
+
+TEST(StreamingTextCopiesCharacters)
+{
+    MemoryOutStream stream;
+    stream << "Lalala";
+    CHECK_EQUAL("Lalala", stream.GetText());
+}
+
+TEST(StreamingMultipleTimesConcatenatesResult)
+{
+    MemoryOutStream stream;
+    stream << "Bork" << "Foo" << "Bar";
+    CHECK_EQUAL("BorkFooBar", stream.GetText());
+}
+
+TEST(StreamingIntWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    stream << (int)123;
+    CHECK_EQUAL("123", stream.GetText());
+}
+
+TEST(StreamingUnsignedIntWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    stream << (unsigned int)123;
+    CHECK_EQUAL("123", stream.GetText());
+}
+
+TEST(StreamingLongWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    stream << (long)(-123);
+    CHECK_EQUAL("-123", stream.GetText());
+}
+
+TEST(StreamingUnsignedLongWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    stream << (unsigned long)123;
+    CHECK_EQUAL("123", stream.GetText());
+}
+
+TEST(StreamingFloatWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    stream << 3.1415f;
+	CHECK(strstr(stream.GetText(), "3.1415"));
+}
+
+TEST(StreamingDoubleWritesCorrectCharacters)
+{
+	MemoryOutStream stream;
+	stream << 3.1415;
+	CHECK(strstr(stream.GetText(), "3.1415"));
+}
+
+TEST(StreamingPointerWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    int* p = (int*)0x1234;
+    stream << p;
+    CHECK(strstr(stream.GetText(), "1234"));
+}
+
+TEST(StreamingSizeTWritesCorrectCharacters)
+{
+    MemoryOutStream stream;
+    size_t const s = 53124;
+    stream << s;
+    CHECK_EQUAL("53124", stream.GetText());
+}
+
+#ifdef UNITTEST_USE_CUSTOM_STREAMS
+
+TEST(StreamInitialCapacityIsCorrect)
+{
+    MemoryOutStream stream(MemoryOutStream::GROW_CHUNK_SIZE);
+    CHECK_EQUAL((int)MemoryOutStream::GROW_CHUNK_SIZE, stream.GetCapacity());
+}
+
+TEST(StreamInitialCapacityIsMultipleOfGrowChunkSize)
+{
+    MemoryOutStream stream(MemoryOutStream::GROW_CHUNK_SIZE + 1);
+    CHECK_EQUAL((int)MemoryOutStream::GROW_CHUNK_SIZE * 2, stream.GetCapacity());
+}
+
+
+TEST(ExceedingCapacityGrowsBuffer)
+{
+    MemoryOutStream stream(MemoryOutStream::GROW_CHUNK_SIZE);
+    stream << "012345678901234567890123456789";
+    char const* const oldBuffer = stream.GetText();
+    stream << "0123456789";
+    CHECK(oldBuffer != stream.GetText());
+}
+
+TEST(ExceedingCapacityGrowsBufferByGrowChunk)
+{
+    MemoryOutStream stream(MemoryOutStream::GROW_CHUNK_SIZE);
+    stream << "0123456789012345678901234567890123456789";
+    CHECK_EQUAL(MemoryOutStream::GROW_CHUNK_SIZE * 2, stream.GetCapacity());
+}
+
+TEST(WritingStringLongerThanCapacityFitsInNewBuffer)
+{
+    MemoryOutStream stream(8);
+    stream << "0123456789ABCDEF";
+    CHECK_EQUAL("0123456789ABCDEF", stream.GetText());
+}
+
+TEST(WritingIntLongerThanCapacityFitsInNewBuffer)
+{
+    MemoryOutStream stream(8);
+    stream << "aaaa" << 123456;;
+    CHECK_EQUAL("aaaa123456", stream.GetText());
+}
+
+TEST(WritingFloatLongerThanCapacityFitsInNewBuffer)
+{
+    MemoryOutStream stream(8);
+    stream << "aaaa" << 123456.0f;;
+    CHECK_EQUAL("aaaa123456.000000f", stream.GetText());
+}
+
+TEST(WritingSizeTLongerThanCapacityFitsInNewBuffer)
+{
+    MemoryOutStream stream(8);
+    stream << "aaaa" << size_t(32145);
+    CHECK_EQUAL("aaaa32145", stream.GetText());
+}
+
+#endif
+
+}

+ 129 - 0
3rdparty/UnitTest++/src/tests/TestTest.cpp

@@ -0,0 +1,129 @@
+#include "../UnitTest++.h"
+#include "../TestReporter.h"
+#include "../TimeHelpers.h"
+#include "ScopedCurrentTest.h"
+
+using namespace UnitTest;
+
+namespace {
+
+TEST(PassingTestHasNoFailures)
+{
+    class PassingTest : public Test
+    {
+    public:
+        PassingTest() : Test("passing") {}
+        virtual void RunImpl() const
+        {
+            CHECK(true);
+        }
+    };
+
+    TestResults results;
+	{
+		ScopedCurrentTest scopedResults(results);
+		PassingTest().Run();
+	}
+
+    CHECK_EQUAL(0, results.GetFailureCount());
+}
+
+
+TEST(FailingTestHasFailures)
+{
+    class FailingTest : public Test
+    {
+    public:
+        FailingTest() : Test("failing") {}
+        virtual void RunImpl() const
+        {
+            CHECK(false);
+        }
+    };
+
+    TestResults results;
+	{
+		ScopedCurrentTest scopedResults(results);
+		FailingTest().Run();
+	}
+
+    CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+
+TEST(ThrowingTestsAreReportedAsFailures)
+{
+    class CrashingTest : public Test
+    {
+    public:
+        CrashingTest() : Test("throwing") {}
+        virtual void RunImpl() const
+        {
+            throw "Blah";
+        }
+    };
+ 
+    TestResults results;
+	{
+		ScopedCurrentTest scopedResult(results);
+		CrashingTest().Run();
+	}
+
+	CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+
+#ifndef UNITTEST_MINGW
+TEST(CrashingTestsAreReportedAsFailures)
+{
+    class CrashingTest : public Test
+    {
+    public:
+        CrashingTest() : Test("crashing") {}
+        virtual void RunImpl() const
+        {
+            reinterpret_cast< void (*)() >(0)();
+        }
+    };
+
+    TestResults results;
+	{
+		ScopedCurrentTest scopedResult(results);
+		CrashingTest().Run();
+	}
+
+	CHECK_EQUAL(1, results.GetFailureCount());
+}
+#endif
+
+TEST(TestWithUnspecifiedSuiteGetsDefaultSuite)
+{
+    Test test("test");
+    CHECK(test.m_details.suiteName != NULL);
+    CHECK_EQUAL("DefaultSuite", test.m_details.suiteName);
+}
+
+TEST(TestReflectsSpecifiedSuiteName)
+{
+    Test test("test", "testSuite");
+    CHECK(test.m_details.suiteName != NULL);
+    CHECK_EQUAL("testSuite", test.m_details.suiteName);
+}
+
+void Fail()
+{
+	CHECK(false);
+}
+
+TEST(OutOfCoreCHECKMacrosCanFailTests)
+{
+	TestResults results;
+	{
+		ScopedCurrentTest scopedResult(results);
+		Fail();
+	}
+
+	CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+}

+ 50 - 0
3rdparty/UnitTest++/src/tests/TestTestList.cpp

@@ -0,0 +1,50 @@
+#include "../UnitTest++.h"
+#include "../TestList.h"
+
+using namespace UnitTest;
+
+namespace {
+
+
+TEST (TestListIsEmptyByDefault)
+{
+    TestList list;
+    CHECK (list.GetHead() == 0);
+}
+
+TEST (AddingTestSetsHeadToTest)
+{
+    Test test("test");
+    TestList list;
+    list.Add(&test);
+
+    CHECK (list.GetHead() == &test);
+    CHECK (test.next == 0);
+}
+
+TEST (AddingSecondTestAddsItToEndOfList)
+{
+    Test test1("test1");
+    Test test2("test2");
+
+    TestList list;
+    list.Add(&test1);
+    list.Add(&test2);
+
+    CHECK (list.GetHead() == &test1);
+    CHECK (test1.next == &test2);
+    CHECK (test2.next == 0);
+}
+
+TEST (ListAdderAddsTestToList)
+{
+    TestList list;
+
+    Test test("");    
+    ListAdder adder(list, &test);
+
+    CHECK (list.GetHead() == &test);
+    CHECK (test.next == 0);
+}
+
+}

+ 212 - 0
3rdparty/UnitTest++/src/tests/TestTestMacros.cpp

@@ -0,0 +1,212 @@
+#include "../UnitTest++.h"
+#include "../TestMacros.h"
+#include "../TestList.h"
+#include "../TestResults.h"
+#include "../TestReporter.h"
+#include "../ReportAssert.h"
+#include "RecordingReporter.h"
+#include "ScopedCurrentTest.h"
+
+using namespace UnitTest;
+
+namespace {
+
+TestList list1;
+TEST_EX(DummyTest, list1)
+{
+}
+
+TEST (TestsAreAddedToTheListThroughMacro)
+{
+    CHECK(list1.GetHead() != 0);
+    CHECK(list1.GetHead()->next == 0);
+}
+
+struct ThrowingThingie
+{
+    ThrowingThingie() : dummy(false)
+    {
+        if (!dummy)
+            throw "Oops";
+    }
+
+    bool dummy;
+};
+
+TestList list2;
+TEST_FIXTURE_EX(ThrowingThingie, DummyTestName, list2)
+{
+}
+
+TEST (ExceptionsInFixtureAreReportedAsHappeningInTheFixture)
+{
+    RecordingReporter reporter;
+    TestResults result(&reporter);
+	{
+		ScopedCurrentTest scopedResults(result);
+		list2.GetHead()->Run();
+	}
+
+    CHECK(strstr(reporter.lastFailedMessage, "xception"));
+    CHECK(strstr(reporter.lastFailedMessage, "fixture"));
+    CHECK(strstr(reporter.lastFailedMessage, "ThrowingThingie"));
+}
+
+struct DummyFixture
+{
+    int x;
+};
+
+// We're really testing the macros so we just want them to compile and link
+SUITE(TestSuite1)
+{
+	TEST(SimilarlyNamedTestsInDifferentSuitesWork)
+	{
+	}
+
+	TEST_FIXTURE(DummyFixture, SimilarlyNamedFixtureTestsInDifferentSuitesWork)
+	{
+	}
+}
+
+SUITE(TestSuite2)
+{
+	TEST(SimilarlyNamedTestsInDifferentSuitesWork)
+	{
+	}
+
+	TEST_FIXTURE(DummyFixture,SimilarlyNamedFixtureTestsInDifferentSuitesWork)
+	{
+	}
+}
+
+TestList macroTestList1;
+TEST_EX(MacroTestHelper1, macroTestList1)
+{
+}
+
+TEST(TestAddedWithTEST_EXMacroGetsDefaultSuite)
+{
+    CHECK(macroTestList1.GetHead() != NULL);
+    CHECK_EQUAL ("MacroTestHelper1", macroTestList1.GetHead()->m_details.testName);
+    CHECK_EQUAL ("DefaultSuite", macroTestList1.GetHead()->m_details.suiteName);
+}
+
+TestList macroTestList2;
+TEST_FIXTURE_EX(DummyFixture, MacroTestHelper2, macroTestList2)
+{
+}
+
+TEST(TestAddedWithTEST_FIXTURE_EXMacroGetsDefaultSuite)
+{
+    CHECK(macroTestList2.GetHead() != NULL);
+    CHECK_EQUAL ("MacroTestHelper2", macroTestList2.GetHead()->m_details.testName);
+    CHECK_EQUAL ("DefaultSuite", macroTestList2.GetHead()->m_details.suiteName);
+}
+
+struct FixtureCtorThrows
+{
+	FixtureCtorThrows()	{ throw "exception"; }
+};
+
+TestList throwingFixtureTestList1;
+TEST_FIXTURE_EX(FixtureCtorThrows, FixtureCtorThrowsTestName, throwingFixtureTestList1)
+{
+}
+
+TEST(FixturesWithThrowingCtorsAreFailures)
+{
+	CHECK(throwingFixtureTestList1.GetHead() != NULL);
+	RecordingReporter reporter;
+	TestResults result(&reporter);
+	{
+		ScopedCurrentTest scopedResult(result);
+		throwingFixtureTestList1.GetHead()->Run();
+	}
+
+	int const failureCount = result.GetFailedTestCount();
+	CHECK_EQUAL(1, failureCount);
+	CHECK(strstr(reporter.lastFailedMessage, "while constructing fixture"));
+}
+
+struct FixtureDtorThrows
+{
+	~FixtureDtorThrows() { throw "exception"; }
+};
+
+TestList throwingFixtureTestList2;
+TEST_FIXTURE_EX(FixtureDtorThrows, FixtureDtorThrowsTestName, throwingFixtureTestList2)
+{
+}
+
+TEST(FixturesWithThrowingDtorsAreFailures)
+{
+	CHECK(throwingFixtureTestList2.GetHead() != NULL);
+
+	RecordingReporter reporter;
+	TestResults result(&reporter);
+	{
+		ScopedCurrentTest scopedResult(result);
+		throwingFixtureTestList2.GetHead()->Run();
+	}
+
+	int const failureCount = result.GetFailedTestCount();
+	CHECK_EQUAL(1, failureCount);
+	CHECK(strstr(reporter.lastFailedMessage, "while destroying fixture"));
+}
+
+const int FailingLine = 123;
+
+struct FixtureCtorAsserts
+{
+	FixtureCtorAsserts()
+	{
+		UnitTest::ReportAssert("assert failure", "file", FailingLine);
+	}
+};
+
+TestList ctorAssertFixtureTestList;
+TEST_FIXTURE_EX(FixtureCtorAsserts, CorrectlyReportsAssertFailureInCtor, ctorAssertFixtureTestList)
+{
+}
+
+TEST(CorrectlyReportsFixturesWithCtorsThatAssert)
+{
+	RecordingReporter reporter;
+	TestResults result(&reporter);
+	{
+		ScopedCurrentTest scopedResults(result);
+		ctorAssertFixtureTestList.GetHead()->Run();
+	}
+
+	const int failureCount = result.GetFailedTestCount();
+	CHECK_EQUAL(1, failureCount);
+	CHECK_EQUAL(FailingLine, reporter.lastFailedLine);
+	CHECK(strstr(reporter.lastFailedMessage, "assert failure"));
+}
+
+}
+
+// We're really testing if it's possible to use the same suite in two files
+// to compile and link successfuly (TestTestSuite.cpp has suite with the same name)
+// Note: we are outside of the anonymous namespace
+SUITE(SameTestSuite)
+{
+	TEST(DummyTest1)
+	{
+	}
+}
+
+#define CUR_TEST_NAME CurrentTestDetailsContainCurrentTestInfo
+#define INNER_STRINGIFY(X) #X
+#define STRINGIFY(X) INNER_STRINGIFY(X)
+
+TEST(CUR_TEST_NAME)
+{
+	const UnitTest::TestDetails* details = CurrentTest::Details();
+	CHECK_EQUAL(STRINGIFY(CUR_TEST_NAME), details->testName);
+}
+
+#undef CUR_TEST_NAME
+#undef INNER_STRINGIFY
+#undef STRINGIFY

+ 111 - 0
3rdparty/UnitTest++/src/tests/TestTestResults.cpp

@@ -0,0 +1,111 @@
+#include "../UnitTest++.h"
+#include "../TestResults.h"
+#include "RecordingReporter.h"
+
+using namespace UnitTest;
+
+namespace {
+
+TestDetails const details("testname", "suitename", "filename", 123);
+
+
+TEST(StartsWithNoTestsRun)
+{
+    TestResults results;
+    CHECK_EQUAL (0, results.GetTotalTestCount());
+}
+
+TEST(RecordsNumbersOfTests)
+{
+    TestResults results;
+    results.OnTestStart(details);
+    results.OnTestStart(details);
+    results.OnTestStart(details);
+    CHECK_EQUAL(3, results.GetTotalTestCount());
+}
+
+TEST(StartsWithNoTestsFailing)
+{
+    TestResults results;
+    CHECK_EQUAL (0, results.GetFailureCount());
+}
+
+TEST(RecordsNumberOfFailures)
+{
+    TestResults results;
+    results.OnTestFailure(details, "");
+    results.OnTestFailure(details, "");
+    CHECK_EQUAL(2, results.GetFailureCount());
+}
+
+TEST(RecordsNumberOfFailedTests)
+{
+    TestResults results;
+
+    results.OnTestStart(details);
+    results.OnTestFailure(details, "");
+    results.OnTestFinish(details, 0);
+
+    results.OnTestStart(details);
+    results.OnTestFailure(details, "");
+    results.OnTestFailure(details, "");
+    results.OnTestFailure(details, "");
+    results.OnTestFinish(details, 0);
+
+    CHECK_EQUAL (2, results.GetFailedTestCount());
+}
+
+TEST(NotifiesReporterOfTestStartWithCorrectInfo)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+    results.OnTestStart(details);
+
+    CHECK_EQUAL (1, reporter.testRunCount);
+    CHECK_EQUAL ("suitename", reporter.lastStartedSuite);
+    CHECK_EQUAL ("testname", reporter.lastStartedTest);
+}
+
+TEST(NotifiesReporterOfTestFailureWithCorrectInfo)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+
+    results.OnTestFailure(details, "failurestring");
+    CHECK_EQUAL (1, reporter.testFailedCount);
+    CHECK_EQUAL ("filename", reporter.lastFailedFile);
+    CHECK_EQUAL (123, reporter.lastFailedLine);
+    CHECK_EQUAL ("suitename", reporter.lastFailedSuite);
+    CHECK_EQUAL ("testname", reporter.lastFailedTest);
+    CHECK_EQUAL ("failurestring", reporter.lastFailedMessage);
+}
+
+TEST(NotifiesReporterOfCheckFailureWithCorrectInfo)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+
+    results.OnTestFailure(details, "failurestring");
+    CHECK_EQUAL (1, reporter.testFailedCount);
+
+    CHECK_EQUAL ("filename", reporter.lastFailedFile);
+    CHECK_EQUAL (123, reporter.lastFailedLine);
+    CHECK_EQUAL ("testname", reporter.lastFailedTest);
+    CHECK_EQUAL ("suitename", reporter.lastFailedSuite);
+    CHECK_EQUAL ("failurestring", reporter.lastFailedMessage);
+}
+
+TEST(NotifiesReporterOfTestEnd)
+{
+    RecordingReporter reporter;
+    TestResults results(&reporter);
+
+    results.OnTestFinish(details, 0.1234f);
+    CHECK_EQUAL (1, reporter.testFinishedCount);
+    CHECK_EQUAL ("testname", reporter.lastFinishedTest);
+    CHECK_EQUAL ("suitename", reporter.lastFinishedSuite);
+    CHECK_CLOSE (0.1234f, reporter.lastFinishedTestTime, 0.0001f);
+}
+
+
+}

+ 307 - 0
3rdparty/UnitTest++/src/tests/TestTestRunner.cpp

@@ -0,0 +1,307 @@
+#include "../UnitTest++.h"
+#include "RecordingReporter.h"
+#include "../ReportAssert.h"
+#include "../TestList.h"
+#include "../TimeHelpers.h"
+#include "../TimeConstraint.h"
+
+using namespace UnitTest;
+
+namespace
+{
+
+struct MockTest : public Test
+{
+    MockTest(char const* testName, bool const success_, bool const assert_, int const count_ = 1)
+        : Test(testName)
+        , success(success_)
+        , asserted(assert_)
+        , count(count_)
+    {
+    }
+
+    virtual void RunImpl(TestResults& testResults_) const
+    {
+        for (int i=0; i < count; ++i)
+        {
+            if (asserted)
+                ReportAssert("desc", "file", 0);
+            else if (!success)
+                testResults_.OnTestFailure(m_details, "message");
+        }
+    }
+
+    bool const success;
+    bool const asserted;
+    int const count;
+};
+
+
+struct TestRunnerFixture
+{
+	TestRunnerFixture()
+		: runner(reporter)
+	{
+	}
+
+    RecordingReporter reporter;
+    TestList list;
+	TestRunner runner;
+};
+
+TEST_FIXTURE(TestRunnerFixture, TestStartIsReportedCorrectly)
+{
+    MockTest test("goodtest", true, false);
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(1, reporter.testRunCount);
+    CHECK_EQUAL("goodtest", reporter.lastStartedTest);
+}
+
+TEST_FIXTURE(TestRunnerFixture, TestFinishIsReportedCorrectly)
+{
+    MockTest test("goodtest", true, false);
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(1, reporter.testFinishedCount);
+    CHECK_EQUAL("goodtest", reporter.lastFinishedTest);
+}
+
+class SlowTest : public Test
+{
+public:
+    SlowTest() : Test("slow", "somesuite", "filename", 123) {}
+    virtual void RunImpl(TestResults&) const
+    {
+        TimeHelpers::SleepMs(20);
+    }
+};
+
+TEST_FIXTURE(TestRunnerFixture, TestFinishIsCalledWithCorrectTime)
+{
+    SlowTest test;
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK(reporter.lastFinishedTestTime >= 0.005f && reporter.lastFinishedTestTime <= 0.050f);
+}
+
+TEST_FIXTURE(TestRunnerFixture, FailureCountIsZeroWhenNoTestsAreRun)
+{
+	CHECK_EQUAL(0, runner.RunTestsIf(list, NULL, True(), 0));
+    CHECK_EQUAL(0, reporter.testRunCount);
+    CHECK_EQUAL(0, reporter.testFailedCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, CallsReportFailureOncePerFailingTest)
+{
+    MockTest test1("test", false, false);
+    list.Add(&test1);
+    MockTest test2("test", true, false);
+    list.Add(&test2);
+    MockTest test3("test", false, false);
+    list.Add(&test3);
+
+	CHECK_EQUAL(2, 	runner.RunTestsIf(list, NULL, True(), 0));
+    CHECK_EQUAL(2, reporter.testFailedCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, TestsThatAssertAreReportedAsFailing)
+{
+    MockTest test("test", true, true);
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(1, reporter.testFailedCount);
+}
+
+
+TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfTestCount)
+{
+    MockTest test1("test", true, false);
+    MockTest test2("test", true, false);
+    MockTest test3("test", true, false);
+    list.Add(&test1);
+    list.Add(&test2);
+    list.Add(&test3);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(3, reporter.summaryTotalTestCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailedTests)
+{
+    MockTest test1("test", false, false, 2);
+    MockTest test2("test", true, false);
+    MockTest test3("test", false, false, 3);
+    list.Add(&test1);
+    list.Add(&test2);
+    list.Add(&test3);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(2, reporter.summaryFailedTestCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, ReporterNotifiedOfFailures)
+{
+    MockTest test1("test", false, false, 2);
+    MockTest test2("test", true, false);
+    MockTest test3("test", false, false, 3);
+    list.Add(&test1);
+    list.Add(&test2);
+    list.Add(&test3);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+	CHECK_EQUAL(5, reporter.summaryFailureCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, SlowTestPassesForHighTimeThreshold)
+{
+    SlowTest test;
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(0, reporter.testFailedCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, SlowTestFailsForLowTimeThreshold)
+{
+    SlowTest test;
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 3);
+    CHECK_EQUAL(1, reporter.testFailedCount);
+}
+
+TEST_FIXTURE(TestRunnerFixture, SlowTestHasCorrectFailureInformation)
+{
+    SlowTest test;
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 3);
+
+	using namespace std;
+
+    CHECK_EQUAL(test.m_details.testName, reporter.lastFailedTest);
+    CHECK(strstr(test.m_details.filename, reporter.lastFailedFile));
+    CHECK_EQUAL(test.m_details.lineNumber, reporter.lastFailedLine);
+
+	CHECK(strstr(reporter.lastFailedMessage, "Global time constraint failed"));
+    CHECK(strstr(reporter.lastFailedMessage, "3ms"));
+}
+
+TEST_FIXTURE(TestRunnerFixture, SlowTestWithTimeExemptionPasses)
+{
+    class SlowExemptedTest : public Test
+    {
+    public:
+        SlowExemptedTest() : Test("slowexempted", "", 0) {}
+        virtual void RunImpl(TestResults&) const
+        {
+            UNITTEST_TIME_CONSTRAINT_EXEMPT();
+            TimeHelpers::SleepMs(20);
+        }
+    };
+
+    SlowExemptedTest test;
+    list.Add(&test);
+
+	runner.RunTestsIf(list, NULL, True(), 3);
+    CHECK_EQUAL(0, reporter.testFailedCount);
+}
+
+struct TestSuiteFixture
+{
+    TestSuiteFixture()
+        : test1("TestInDefaultSuite")
+        , test2("TestInOtherSuite", "OtherSuite")
+        , test3("SecondTestInDefaultSuite")
+		, runner(reporter)
+    {
+        list.Add(&test1);
+        list.Add(&test2);
+    }
+
+    Test test1;
+    Test test2;
+    Test test3;
+    RecordingReporter reporter;
+    TestList list;
+	TestRunner runner;
+};
+
+TEST_FIXTURE(TestSuiteFixture, TestRunnerRunsAllSuitesIfNullSuiteIsPassed)
+{
+	runner.RunTestsIf(list, NULL, True(), 0);
+    CHECK_EQUAL(2, reporter.summaryTotalTestCount);
+}
+
+TEST_FIXTURE(TestSuiteFixture,TestRunnerRunsOnlySpecifiedSuite)
+{
+	runner.RunTestsIf(list, "OtherSuite", True(), 0);
+    CHECK_EQUAL(1, reporter.summaryTotalTestCount);
+    CHECK_EQUAL("TestInOtherSuite", reporter.lastFinishedTest);
+}
+
+struct RunTestIfNameIs
+{
+	RunTestIfNameIs(char const* name_)
+	: name(name_)
+	{		
+	}
+	
+	bool operator()(const Test* const test) const
+	{
+		using namespace std;
+		return (0 == strcmp(test->m_details.testName, name));
+	}
+	
+	char const* name;
+};
+
+TEST(TestMockPredicateBehavesCorrectly)
+{
+	RunTestIfNameIs predicate("pass");
+	
+	Test pass("pass");
+	Test fail("fail");
+	
+	CHECK(predicate(&pass));
+	CHECK(!predicate(&fail));	
+}
+
+TEST_FIXTURE(TestRunnerFixture, TestRunnerRunsTestsThatPassPredicate)
+{
+    Test should_run("goodtest");
+    list.Add(&should_run);
+
+    Test should_not_run("badtest");
+	list.Add(&should_not_run);
+ 
+	runner.RunTestsIf(list, NULL, RunTestIfNameIs("goodtest"), 0);
+	CHECK_EQUAL(1, reporter.testRunCount);
+    CHECK_EQUAL("goodtest", reporter.lastStartedTest);
+}
+
+TEST_FIXTURE(TestRunnerFixture, TestRunnerOnlyRunsTestsInSpecifiedSuiteAndThatPassPredicate)
+{
+    Test runningTest1("goodtest", "suite");
+    Test skippedTest2("goodtest");
+    Test skippedTest3("badtest", "suite");
+    Test skippedTest4("badtest");
+    
+    list.Add(&runningTest1);
+    list.Add(&skippedTest2);
+    list.Add(&skippedTest3);
+    list.Add(&skippedTest4);   
+
+	runner.RunTestsIf(list, "suite", RunTestIfNameIs("goodtest"), 0);
+
+	CHECK_EQUAL(1, reporter.testRunCount);
+    CHECK_EQUAL("goodtest", reporter.lastStartedTest); 
+    CHECK_EQUAL("suite", reporter.lastStartedSuite);    
+}
+
+}

+ 12 - 0
3rdparty/UnitTest++/src/tests/TestTestSuite.cpp

@@ -0,0 +1,12 @@
+#include "../UnitTest++.h"
+
+// We're really testing if it's possible to use the same suite in two files
+// to compile and link successfuly (TestTestSuite.cpp has suite with the same name)
+// Note: we are outside of the anonymous namespace
+SUITE(SameTestSuite)
+{
+    TEST(DummyTest2)
+    {
+    }
+}
+

+ 69 - 0
3rdparty/UnitTest++/src/tests/TestTimeConstraint.cpp

@@ -0,0 +1,69 @@
+#include "../UnitTest++.h"
+#include "../TestResults.h"
+#include "../TimeHelpers.h"
+#include "RecordingReporter.h"
+#include "ScopedCurrentTest.h"
+
+using namespace UnitTest;
+
+namespace
+{
+
+TEST(TimeConstraintSucceedsWithFastTest)
+{
+    TestResults result;
+    {
+		ScopedCurrentTest scopedResult(result);
+        TimeConstraint t(200, TestDetails("", "", "", 0));
+        TimeHelpers::SleepMs(5);
+    }
+    CHECK_EQUAL(0, result.GetFailureCount());
+}
+
+TEST(TimeConstraintFailsWithSlowTest)
+{
+    TestResults result;
+    {
+		ScopedCurrentTest scopedResult(result);
+        TimeConstraint t(10, TestDetails("", "", "", 0));
+        TimeHelpers::SleepMs(20);
+    }
+    CHECK_EQUAL(1, result.GetFailureCount());
+}
+
+TEST(TimeConstraintFailureIncludesCorrectData)
+{
+    RecordingReporter reporter;
+    TestResults result(&reporter);
+    {
+		ScopedCurrentTest scopedResult(result);
+
+		TestDetails const details("testname", "suitename", "filename", 10);
+        TimeConstraint t(10, details);
+        TimeHelpers::SleepMs(20);
+    }
+
+	using namespace std;
+
+	CHECK(strstr(reporter.lastFailedFile, "filename"));
+    CHECK_EQUAL(10, reporter.lastFailedLine);
+    CHECK(strstr(reporter.lastFailedTest, "testname"));
+}
+
+TEST(TimeConstraintFailureIncludesTimeoutInformation)
+{
+    RecordingReporter reporter;
+    TestResults result(&reporter);
+    {
+		ScopedCurrentTest scopedResult(result);
+        TimeConstraint t(10, TestDetails("", "", "", 0));
+        TimeHelpers::SleepMs(20);
+    }
+
+	using namespace std;
+
+	CHECK(strstr(reporter.lastFailedMessage, "ime constraint"));
+    CHECK(strstr(reporter.lastFailedMessage, "under 10ms"));
+}
+
+}

+ 65 - 0
3rdparty/UnitTest++/src/tests/TestTimeConstraintMacro.cpp

@@ -0,0 +1,65 @@
+#include "../UnitTest++.h"
+#include "../TimeHelpers.h"
+
+#include "RecordingReporter.h"
+#include "ScopedCurrentTest.h"
+
+namespace {
+
+TEST(TimeConstraintMacroQualifiesNamespace)
+{
+    // If this compiles without a "using namespace UnitTest;", all is well.
+    UNITTEST_TIME_CONSTRAINT(1);
+}
+
+TEST(TimeConstraintMacroUsesCorrectInfo)
+{
+    int testLine = 0;
+    RecordingReporter reporter;
+
+    {
+      UnitTest::TestResults testResults(&reporter);
+      ScopedCurrentTest scopedResults(testResults);
+
+      UNITTEST_TIME_CONSTRAINT(10);  testLine = __LINE__;
+      UnitTest::TimeHelpers::SleepMs(20);
+    }
+
+    using namespace std;
+
+    CHECK_EQUAL(1, reporter.testFailedCount);
+    CHECK(strstr(reporter.lastFailedFile, __FILE__));
+    CHECK_EQUAL(testLine, reporter.lastFailedLine);
+    CHECK(strstr(reporter.lastFailedTest, "TimeConstraintMacroUsesCorrectInfo"));
+}
+
+TEST(TimeConstraintMacroComparesAgainstPreciseActual)
+{
+    int testLine = 0;
+    RecordingReporter reporter;
+
+	{
+		UnitTest::TestResults testResults(&reporter);
+		ScopedCurrentTest scopedResults(testResults);
+
+		UNITTEST_TIME_CONSTRAINT(1);  testLine = __LINE__;
+
+		// start a new timer and run until we're as little over the 1 msec
+		// threshold as we can achieve; this should guarantee that the "test"
+		// runs in some very small amount of time > 1 msec
+		UnitTest::Timer myTimer;
+		myTimer.Start();
+
+		while (myTimer.GetTimeInMs() < 1.001)
+			UnitTest::TimeHelpers::SleepMs(0);
+	}
+
+    using namespace std;
+
+    CHECK_EQUAL(1, reporter.testFailedCount);
+    CHECK(strstr(reporter.lastFailedFile, __FILE__));
+    CHECK_EQUAL(testLine, reporter.lastFailedLine);
+    CHECK(strstr(reporter.lastFailedTest, "TimeConstraintMacroComparesAgainstPreciseActual"));
+}
+
+}

+ 156 - 0
3rdparty/UnitTest++/src/tests/TestUnitTest++.cpp

@@ -0,0 +1,156 @@
+#include "../UnitTest++.h"
+#include "../ReportAssert.h"
+#include "ScopedCurrentTest.h"
+
+#include <vector>
+
+// These are sample tests that show the different features of the framework
+
+namespace {
+
+TEST(ValidCheckSucceeds)
+{
+    bool const b = true;
+    CHECK(b);
+}
+
+TEST(CheckWorksWithPointers)
+{
+    void* p = (void *)0x100;
+    CHECK(p);
+    CHECK(p != 0);
+}
+
+TEST(ValidCheckEqualSucceeds)
+{
+    int const x = 3;
+    int const y = 3;
+    CHECK_EQUAL(x, y);
+}
+
+TEST(CheckEqualWorksWithPointers)
+{
+    void* p = (void *)0;
+    CHECK_EQUAL((void*)0, p);
+}
+
+TEST(ValidCheckCloseSucceeds)
+{
+    CHECK_CLOSE(2.0f, 2.001f, 0.01f);
+    CHECK_CLOSE(2.001f, 2.0f, 0.01f);
+}
+
+TEST(ArrayCloseSucceeds)
+{
+    float const a1[] = {1, 2, 3};
+    float const a2[] = {1, 2.01f, 3};
+    CHECK_ARRAY_CLOSE(a1, a2, 3, 0.1f);
+}
+
+TEST (CheckArrayCloseWorksWithVectors)
+{
+    std::vector< float > a(4);
+    for (int i = 0; i < 4; ++i)
+        a[i] = (float)i;
+
+    CHECK_ARRAY_CLOSE(a, a, (int)a.size(), 0.0001f);
+}
+
+TEST(CheckThrowMacroSucceedsOnCorrectException)
+{
+    struct TestException {};
+    CHECK_THROW(throw TestException(), TestException);
+}
+
+TEST(CheckAssertSucceeds)
+{
+    CHECK_ASSERT(UnitTest::ReportAssert("desc", "file", 0));
+}
+
+TEST(CheckThrowMacroFailsOnMissingException)
+{
+    class NoThrowTest : public UnitTest::Test
+    {
+    public:
+        NoThrowTest() : Test("nothrow") {}
+        void DontThrow() const
+        {
+        }
+
+        virtual void RunImpl() const
+        {
+            CHECK_THROW(DontThrow(), int);
+        }
+    };
+
+    UnitTest::TestResults results;
+	{
+		ScopedCurrentTest scopedResults(results);
+
+		NoThrowTest test;
+		test.Run();
+	}
+
+	CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+TEST(CheckThrowMacroFailsOnWrongException)
+{
+    class WrongThrowTest : public UnitTest::Test
+    {
+    public:
+        WrongThrowTest() : Test("wrongthrow") {}
+        virtual void RunImpl() const
+        {
+            CHECK_THROW(throw "oops", int);
+        }
+    };
+
+    UnitTest::TestResults results;
+	{
+		ScopedCurrentTest scopedResults(results);
+
+		WrongThrowTest test;
+		test.Run();
+	}
+
+	CHECK_EQUAL(1, results.GetFailureCount());
+}
+
+struct SimpleFixture
+{
+    SimpleFixture()
+    {
+        ++instanceCount;
+    }
+    ~SimpleFixture()
+    {
+        --instanceCount;
+    }
+
+    static int instanceCount;
+};
+
+int SimpleFixture::instanceCount = 0;
+
+TEST_FIXTURE(SimpleFixture, DefaultFixtureCtorIsCalled)
+{
+    CHECK(SimpleFixture::instanceCount > 0);
+}
+
+TEST_FIXTURE(SimpleFixture, OnlyOneFixtureAliveAtATime)
+{
+    CHECK_EQUAL(1, SimpleFixture::instanceCount);
+}
+
+void CheckBool(const bool b)
+{
+	CHECK(b);
+}
+
+TEST(CanCallCHECKOutsideOfTestFunction)
+{
+	CheckBool(true);
+}
+
+}

+ 183 - 0
3rdparty/UnitTest++/src/tests/TestXmlTestReporter.cpp

@@ -0,0 +1,183 @@
+#include "../UnitTest++.h"
+#include "../XmlTestReporter.h"
+
+#include <sstream>
+
+using namespace UnitTest;
+using std::ostringstream;
+
+namespace
+{
+
+#ifdef UNITTEST_USE_CUSTOM_STREAMS
+
+// Overload to let MemoryOutStream accept std::string
+MemoryOutStream& operator<<(MemoryOutStream& s, const std::string& value)
+{
+    s << value.c_str();
+    return s;
+}
+
+#endif
+
+struct XmlTestReporterFixture
+{
+    XmlTestReporterFixture()
+        : reporter(output)
+    {
+    }
+
+    ostringstream output;
+    XmlTestReporter reporter;
+};
+
+TEST_FIXTURE(XmlTestReporterFixture, MultipleCharactersAreEscaped)
+{
+    TestDetails const details("TestName", "suite", "filename.h", 4321);
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, "\"\"\'\'&&<<>>");
+    reporter.ReportTestFinish(details, 0.1f);
+    reporter.ReportSummary(1, 2, 3, 0.1f);
+
+    char const* expected =
+        "<?xml version=\"1.0\"?>"
+        "<unittest-results tests=\"1\" failedtests=\"2\" failures=\"3\" time=\"0.1\">"
+        "<test suite=\"suite\" name=\"TestName\" time=\"0.1\">"
+        "<failure message=\"filename.h(4321) : "
+        "&quot;&quot;&apos;&apos;&amp;&amp;&lt;&lt;&gt;&gt;\"/>"
+        "</test>"
+        "</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, OutputIsCachedUntilReportSummaryIsCalled)
+{
+    TestDetails const details("", "", "", 0);
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, "message");
+    reporter.ReportTestFinish(details, 1.0F);
+    CHECK(output.str().empty());
+
+    reporter.ReportSummary(1, 1, 1, 1.0f);
+    CHECK(!output.str().empty());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, EmptyReportSummaryFormat)
+{
+    reporter.ReportSummary(0, 0, 0, 0.1f);
+
+    const char *expected =
+"<?xml version=\"1.0\"?>"
+"<unittest-results tests=\"0\" failedtests=\"0\" failures=\"0\" time=\"0.1\">"
+"</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, SingleSuccessfulTestReportSummaryFormat)
+{
+    TestDetails const details("TestName", "DefaultSuite", "", 0);
+
+    reporter.ReportTestStart(details);
+    reporter.ReportSummary(1, 0, 0, 0.1f);
+
+    const char *expected =
+"<?xml version=\"1.0\"?>"
+"<unittest-results tests=\"1\" failedtests=\"0\" failures=\"0\" time=\"0.1\">"
+"<test suite=\"DefaultSuite\" name=\"TestName\" time=\"0\"/>"
+"</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, SingleFailedTestReportSummaryFormat)
+{
+    TestDetails const details("A Test", "suite", "A File", 4321);
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, "A Failure");
+    reporter.ReportSummary(1, 1, 1, 0.1f);
+
+    const char *expected =
+        "<?xml version=\"1.0\"?>"
+        "<unittest-results tests=\"1\" failedtests=\"1\" failures=\"1\" time=\"0.1\">"
+        "<test suite=\"suite\" name=\"A Test\" time=\"0\">"
+        "<failure message=\"A File(4321) : A Failure\"/>"
+        "</test>"
+        "</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, FailureMessageIsXMLEscaped)
+{
+    TestDetails const details("TestName", "suite", "filename.h", 4321);
+
+    reporter.ReportTestStart(details);
+    reporter.ReportFailure(details, "\"\'&<>");
+    reporter.ReportTestFinish(details, 0.1f);
+    reporter.ReportSummary(1, 1, 1, 0.1f);
+
+    char const* expected =
+        "<?xml version=\"1.0\"?>"
+        "<unittest-results tests=\"1\" failedtests=\"1\" failures=\"1\" time=\"0.1\">"
+        "<test suite=\"suite\" name=\"TestName\" time=\"0.1\">"
+        "<failure message=\"filename.h(4321) : &quot;&apos;&amp;&lt;&gt;\"/>"
+        "</test>"
+        "</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, OneFailureAndOneSuccess)
+{
+    TestDetails const failedDetails("FailedTest", "suite", "fail.h", 1);
+    reporter.ReportTestStart(failedDetails);
+    reporter.ReportFailure(failedDetails, "expected 1 but was 2");
+    reporter.ReportTestFinish(failedDetails, 0.1f);
+
+    TestDetails const succeededDetails("SucceededTest", "suite", "", 0);
+    reporter.ReportTestStart(succeededDetails);
+    reporter.ReportTestFinish(succeededDetails, 1.0f);
+    reporter.ReportSummary(2, 1, 1, 1.1f);
+
+    char const* expected =
+        "<?xml version=\"1.0\"?>"
+        "<unittest-results tests=\"2\" failedtests=\"1\" failures=\"1\" time=\"1.1\">"
+        "<test suite=\"suite\" name=\"FailedTest\" time=\"0.1\">"
+        "<failure message=\"fail.h(1) : expected 1 but was 2\"/>"
+        "</test>"
+        "<test suite=\"suite\" name=\"SucceededTest\" time=\"1\"/>"
+        "</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+TEST_FIXTURE(XmlTestReporterFixture, MultipleFailures)
+{
+    TestDetails const failedDetails1("FailedTest", "suite", "fail.h", 1);
+    TestDetails const failedDetails2("FailedTest", "suite", "fail.h", 31);
+
+    reporter.ReportTestStart(failedDetails1);
+    reporter.ReportFailure(failedDetails1, "expected 1 but was 2");
+    reporter.ReportFailure(failedDetails2, "expected one but was two");
+    reporter.ReportTestFinish(failedDetails1, 0.1f);
+
+    reporter.ReportSummary(1, 1, 2, 1.1f);
+
+    char const* expected =
+        "<?xml version=\"1.0\"?>"
+        "<unittest-results tests=\"1\" failedtests=\"1\" failures=\"2\" time=\"1.1\">"
+        "<test suite=\"suite\" name=\"FailedTest\" time=\"0.1\">"
+        "<failure message=\"fail.h(1) : expected 1 but was 2\"/>"
+        "<failure message=\"fail.h(31) : expected one but was two\"/>"
+        "</test>"
+        "</unittest-results>";
+
+    CHECK_EQUAL(expected, output.str());
+}
+
+}

+ 2 - 0
LICENSE

@@ -20,3 +20,5 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.
+
+https://github.com/bkaradzic/bx

+ 23 - 0
include/tinystl/LICENSE

@@ -0,0 +1,23 @@
+ Copyright 2012 Matthew Endsley
+ All rights reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted providing that the following conditions 
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.

+ 49 - 0
include/tinystl/allocator.h

@@ -0,0 +1,49 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_ALLOCATOR_H
+#define TINYSTL_ALLOCATOR_H
+
+#include "stddef.h"
+
+namespace tinystl {
+
+	struct allocator {
+		static void* static_allocate(size_t bytes) {
+			return operator new(bytes);
+		}
+
+		static void static_deallocate(void* ptr, size_t /*bytes*/) {
+			operator delete(ptr);
+		}
+	};
+}
+
+#ifndef TINYSTL_ALLOCATOR
+#	define TINYSTL_ALLOCATOR ::tinystl::allocator
+#endif
+
+#endif

+ 212 - 0
include/tinystl/buffer.h

@@ -0,0 +1,212 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_BUFFER_H
+#define TINYSTL_BUFFER_H
+
+#include "allocator.h"
+#include "new.h"
+#include "traits.h"
+
+namespace tinystl {
+
+	template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
+	struct buffer {
+		T* first;
+		T* last;
+		T* capacity;
+	};
+
+	template<typename T>
+	static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits<T, false>) {
+		for (; first < last; ++first)
+			first->~T();
+	}
+
+	template<typename T>
+	static inline void buffer_destroy_range_traits(T*, T*, pod_traits<T, true>) {
+	}
+
+	template<typename T>
+	static inline void buffer_destroy_range(T* first, T* last) {
+		buffer_destroy_range_traits(first, last, pod_traits<T>());
+	}
+
+	template<typename T>
+	static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, false>) {
+		for (; first < last; ++first)
+			new(placeholder(), first) T(value);
+	}
+
+	template<typename T>
+	static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, true>) {
+		for (; first < last; ++first)
+			*first = value;
+	}
+
+	template<typename T>
+	static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
+		for (T* it = first; it != last; ++it, ++dest)
+			move_construct(dest, *it);
+		buffer_destroy_range(first, last);
+	}
+
+	template<typename T>
+	static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
+		for (; first != last; ++first, ++dest)
+			*dest = *first;
+	}
+
+	template<typename T>
+	static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
+		dest += (last - first);
+		for (T* it = last; it != first; --it, --dest) {
+			move_construct(dest - 1, *(it - 1));
+			buffer_destroy_range(it - 1, it);
+		}
+	}
+
+	template<typename T>
+	static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
+		dest += (last - first);
+		for (T* it = last; it != first; --it, --dest)
+			*(dest - 1) = *(it - 1);
+	}
+
+	template<typename T>
+	static inline void buffer_move_urange(T* dest, T* first, T* last) {
+		buffer_move_urange_traits(dest, first, last, pod_traits<T>());
+	}
+
+	template<typename T>
+	static inline void buffer_bmove_urange(T* dest, T* first, T* last) {
+		buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
+	}
+
+	template<typename T>
+	static inline void buffer_fill_urange(T* first, T* last, const T& value) {
+		buffer_fill_urange_traits(first, last, value, pod_traits<T>());
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_init(buffer<T, Alloc>* b) {
+		b->first = b->last = b->capacity = 0;
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_destroy(buffer<T, Alloc>* b) {
+		buffer_destroy_range(b->first, b->last);
+		Alloc::static_deallocate(b->first, (size_t)((char*)b->first - (char*)b->last));
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_reserve(buffer<T, Alloc>* b, size_t capacity) {
+		if (b->first + capacity <= b->capacity)
+			return;
+
+		typedef T* pointer;
+		const size_t size = (size_t)(b->last - b->first);
+		pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity);
+		buffer_move_urange(newfirst, b->first, b->last);
+		Alloc::static_deallocate(b->first, sizeof(T) * capacity);
+
+		b->first = newfirst;
+		b->last = newfirst + size;
+		b->capacity = newfirst + capacity;
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
+		buffer_reserve(b, size);
+
+		buffer_fill_urange(b->last, b->first + size, value);
+		buffer_destroy_range(b->first + size, b->last);
+		b->last = b->first + size;
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_clear(buffer<T, Alloc>* b) {
+		buffer_destroy_range(b->first, b->last);
+		b->last = b->first;
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const T* first, const T* last) {
+		const size_t offset = (size_t)(where - b->first);
+		const size_t newsize = (size_t)((b->last - b->first) + (last - first));
+		if (b->first + newsize > b->capacity)
+			buffer_reserve(b, (newsize * 3) / 2);
+
+		where = b->first + offset;
+		const size_t count = (size_t)(last - first);
+
+		if (where != b->last)
+			buffer_bmove_urange(where + count, where, b->last);
+
+		for (; first != last; ++first, ++where)
+			new(placeholder(), where) T(*first);
+
+		b->last = b->first + newsize;
+	}
+
+	template<typename T, typename Alloc>
+	static inline T* buffer_erase(buffer<T, Alloc>* b, T* first, T* last) {
+		typedef T* pointer;
+		const size_t range = (last - first);
+		for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest)
+			move(*dest, *it);
+
+		buffer_destroy_range(b->last - range, b->last);
+
+		b->last -= range;
+		return first;
+	}
+
+	template<typename T, typename Alloc>
+	static inline T* buffer_erase_unordered(buffer<T, Alloc>* b, T* first, T* last) {
+		typedef T* pointer;
+		const size_t range = (last - first);
+		const size_t tail = (b->last - last);
+		pointer it = b->last - ((range < tail) ? range : tail);
+		for (pointer end = b->last, dest = first; it != end; ++it, ++dest)
+			move(*dest, *it);
+
+		buffer_destroy_range(b->last - range, b->last);
+
+		b->last -= range;
+		return first;
+	}
+
+	template<typename T, typename Alloc>
+	static inline void buffer_swap(buffer<T, Alloc>* b, buffer<T, Alloc>* other) {
+		typedef T* pointer;
+		const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity;
+		b->first = other->first, b->last = other->last, b->capacity = other->capacity;
+		other->first = tfirst, other->last = tlast, other->capacity = tcapacity;
+	}
+}
+
+#endif

+ 53 - 0
include/tinystl/hash.h

@@ -0,0 +1,53 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_STRINGHASH_H
+#define TINYSTL_STRINGHASH_H
+
+#include "stddef.h"
+
+namespace tinystl {
+
+	static inline size_t hash_string(const char* str, size_t len) {
+		// Implementation of sdbm a public domain string hash from Ozan Yigit
+		// see: http://www.eecs.harvard.edu/margo/papers/usenix91/paper.ps
+
+		size_t hash = 0;
+		typedef const char* pointer;
+		for (pointer it = str, end = str + len; it != end; ++it)
+			hash = *it + (hash << 6) + (hash << 16) - hash;
+
+		return hash;
+	}
+
+	template<typename T>
+	inline size_t hash(const T& value) {
+		const size_t asint = (size_t)value;
+		return hash_string((const char*)&asint, sizeof(asint));
+	}
+}
+
+#endif

+ 225 - 0
include/tinystl/hash_base.h

@@ -0,0 +1,225 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_HASH_BASE_H
+#define TINYSTL_HASH_BASE_H
+
+#include "stddef.h"
+
+namespace tinystl {
+
+	template<typename Key, typename Value>
+	struct pair {
+		pair();
+		pair(const Key& key, const Value& value);
+
+		Key first;
+		Value second;
+	};
+
+	template<typename Key, typename Value>
+	pair<Key, Value>::pair() {
+	}
+
+	template<typename Key, typename Value>
+	pair<Key, Value>::pair(const Key& key, const Value& value)
+		: first(key)
+		, second(value)
+	{
+	}
+
+	template<typename Key, typename Value>
+	static inline pair<Key, Value> make_pair(const Key& key, const Value& value) {
+		return pair<Key, Value>(key, value);
+	}
+
+
+	template<typename Key, typename Value>
+	struct unordered_hash_node {
+		unordered_hash_node(const Key& key, const Value& value);
+
+		const Key first;
+		Value second;
+		unordered_hash_node* next;
+		unordered_hash_node* prev;
+	};
+
+	template<typename Key, typename Value>
+	unordered_hash_node<Key, Value>::unordered_hash_node(const Key& key, const Value& value)
+		: first(key)
+		, second(value)
+	{
+	}
+
+	template <typename Key>
+	struct unordered_hash_node<Key, void> {
+		unordered_hash_node(const Key& key);
+
+		const Key first;
+		unordered_hash_node* next;
+		unordered_hash_node* prev;
+	};
+
+	template<typename Key>
+	unordered_hash_node<Key, void>::unordered_hash_node(const Key& key)
+		: first(key)
+	{
+	}
+
+	template<typename Key, typename Value>
+	static void unordered_hash_node_insert(unordered_hash_node<Key, Value>* node, size_t hash, unordered_hash_node<Key, Value>** buckets, size_t nbuckets) {
+		size_t bucket = hash & (nbuckets - 1);
+
+		unordered_hash_node<Key, Value>* it = buckets[bucket + 1];
+		node->next = it;
+		if (it) {
+			node->prev = it->prev;
+			it->prev = node;
+			if (node->prev)
+				node->prev->next = node;
+		} else {
+			size_t newbucket = bucket;
+			while (newbucket && !buckets[newbucket])
+				--newbucket;
+
+			unordered_hash_node<Key, Value>* prev = buckets[newbucket];
+			while (prev && prev->next)
+				prev = prev->next;
+
+			node->prev = prev;
+			if (prev)
+				prev->next = node;
+		}
+
+		// propagate node through buckets
+		for (; it == buckets[bucket]; --bucket) {
+			buckets[bucket] = node;
+			if (!bucket)
+				break;
+		}
+	}
+
+	template<typename Key, typename Value>
+	static inline void unordered_hash_node_erase(const unordered_hash_node<Key, Value>* where, size_t hash, unordered_hash_node<Key, Value>** buckets, size_t nbuckets) {
+		size_t bucket = hash & (nbuckets - 1);
+
+		unordered_hash_node<Key, Value>* next = where->next;
+		for (; buckets[bucket] == where; --bucket) {
+			buckets[bucket] = next;
+			if (!bucket)
+				break;
+		}
+
+		if (where->prev)
+			where->prev->next = where->next;
+		if (next)
+			next->prev = where->prev;
+	}
+
+	template<typename Node>
+	struct unordered_hash_iterator {
+		Node* operator->() const;
+		Node& operator*() const;
+		Node* node;
+	};
+
+	template<typename Node>
+	struct unordered_hash_iterator<const Node> {
+
+		unordered_hash_iterator() {}
+		unordered_hash_iterator(unordered_hash_iterator<Node> other)
+			: node(other.node)
+		{
+		}
+
+		const Node* operator->() const;
+		const Node& operator*() const;
+		const Node* node;
+	};
+
+	template<typename Key>
+	struct unordered_hash_iterator<const unordered_hash_node<Key, void> > {
+		const Key* operator->() const;
+		const Key& operator*() const;
+		unordered_hash_node<Key, void>* node;
+	};
+
+	template<typename LNode, typename RNode>
+	static inline bool operator==(const unordered_hash_iterator<LNode>& lhs, const unordered_hash_iterator<RNode>& rhs) {
+		return lhs.node == rhs.node;
+	}
+
+	template<typename LNode, typename RNode>
+	static inline bool operator!=(const unordered_hash_iterator<LNode>& lhs, const unordered_hash_iterator<RNode>& rhs) {
+		return lhs.node != rhs.node;
+	}
+
+	template<typename Node>
+	static inline void operator++(unordered_hash_iterator<Node>& lhs) {
+		lhs.node = lhs.node->next;
+	}
+
+	template<typename Node>
+	inline Node* unordered_hash_iterator<Node>::operator->() const {
+		return node;
+	}
+
+	template<typename Node>
+	inline Node& unordered_hash_iterator<Node>::operator*() const {
+		return *node;
+	}
+
+	template<typename Node>
+	inline const Node* unordered_hash_iterator<const Node>::operator->() const {
+		return node;
+	}
+
+	template<typename Node>
+	inline const Node& unordered_hash_iterator<const Node>::operator*() const {
+		return *node;
+	}
+
+	template<typename Key>
+	inline const Key* unordered_hash_iterator<const unordered_hash_node<Key, void> >::operator->() const {
+		return &node->first;
+	}
+
+	template<typename Key>
+	inline const Key& unordered_hash_iterator<const unordered_hash_node<Key, void> >::operator*() const {
+		return node->first;
+	}
+
+	template<typename Node, typename Key>
+	static inline Node unordered_hash_find(const Key& key, Node* buckets, size_t nbuckets) {
+		const size_t bucket = hash(key) & (nbuckets - 2);
+		for (Node it = buckets[bucket], end = buckets[bucket+1]; it != end; it = it->next)
+			if (it->first == key)
+				return it;
+
+		return 0;
+	}
+}
+#endif

+ 43 - 0
include/tinystl/new.h

@@ -0,0 +1,43 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_NEW_H
+#define TINYSTL_NEW_H
+
+#include "stddef.h"
+
+namespace tinystl {
+
+	struct placeholder {};
+}
+
+inline void* operator new(size_t, tinystl::placeholder, void* ptr) {
+	return ptr;
+}
+
+inline void operator delete(void*, tinystl::placeholder, void*) throw() {}
+
+#endif

+ 40 - 0
include/tinystl/stddef.h

@@ -0,0 +1,40 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_STDDEF_H
+#define TINYSTL_STDDEF_H
+
+#if defined(_WIN64)
+	typedef long long unsigned int size_t;
+#elif defined(_WIN32)
+	typedef unsigned int size_t;
+#elif defined (__linux__) && defined(__SIZE_TYPE__)
+	typedef __SIZE_TYPE__ size_t;
+#else
+#	include <stddef.h>
+#endif
+
+#endif

+ 212 - 0
include/tinystl/string.h

@@ -0,0 +1,212 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_STRING_H
+#define TINYSTL_STRING_H
+
+#include "allocator.h"
+#include "stddef.h"
+#include "hash.h"
+
+namespace tinystl {
+
+	class string {
+	public:
+		string();
+		string(const string& other);
+		string(const char* sz);
+		string(const char* sz, size_t len);
+		~string();
+
+		string& operator=(const string& other);
+
+		const char* c_str() const;
+		size_t size() const;
+
+		void reserve(size_t size);
+		void resize(size_t size);
+
+		void append(const char* first, const char* last);
+
+		void swap(string& other);
+
+	private:
+		typedef char* pointer;
+		pointer m_first;
+		pointer m_last;
+		pointer m_capacity;
+
+		static const size_t c_nbuffer = 12;
+		char m_buffer[12];
+	};
+
+	inline string::string()
+		: m_first(m_buffer)
+		, m_last(m_buffer)
+		, m_capacity(m_buffer + c_nbuffer)
+	{
+		resize(0);
+	}
+
+	inline string::string(const string& other)
+		: m_first(m_buffer)
+		, m_last(m_buffer)
+		, m_capacity(m_buffer + c_nbuffer)
+	{
+		reserve(other.size());
+		append(other.m_first, other.m_last);
+	}
+
+	inline string::string(const char* sz)
+		: m_first(m_buffer)
+		, m_last(m_buffer)
+		, m_capacity(m_buffer + c_nbuffer)
+	{
+		size_t len = 0;
+		for (const char* it = sz; *it; ++it)
+			++len;
+
+		reserve(len);
+		append(sz, sz + len);
+	}
+
+	inline string::string(const char* sz, size_t len)
+		: m_first(m_buffer)
+		, m_last(m_buffer)
+		, m_capacity(m_buffer + c_nbuffer)
+	{
+		reserve(len);
+		append(sz, sz + len);
+	}
+
+	inline string::~string() {
+		if (m_first != m_buffer)
+			TINYSTL_ALLOCATOR::static_deallocate(m_first, m_capacity - m_first);
+	}
+
+	inline string& string::operator=(const string& other) {
+		string(other).swap(*this);
+		return *this;
+	}
+
+	inline const char* string::c_str() const {
+		return m_first;
+	}
+
+	inline size_t string::size() const
+	{
+		return (size_t)(m_last - m_first);
+	}
+
+	inline void string::reserve(size_t capacity) {
+		if (m_first + capacity + 1 <= m_capacity)
+			return;
+
+		const size_t size = (size_t)(m_last - m_first);
+
+		pointer newfirst = (pointer)TINYSTL_ALLOCATOR::static_allocate(capacity + 1);
+		for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit)
+			*newit = *it;
+		if (m_first != m_buffer)
+			TINYSTL_ALLOCATOR::static_deallocate(m_first, m_capacity - m_first);
+
+		m_first = newfirst;
+		m_last = newfirst + size;
+		m_capacity = m_first + capacity;
+	}
+
+	inline void string::resize(size_t size) {
+		reserve(size);
+		for (pointer it = m_last, end = m_first + size + 1; it < end; ++it)
+			*it = 0;
+
+		m_last += size;
+	}
+
+	inline void string::append(const char* first, const char* last) {
+		const size_t newsize = (size_t)((m_last - m_first) + (last - first) + 1);
+		if (m_first + newsize > m_capacity)
+			reserve((newsize * 3) / 2);
+
+		for (; first != last; ++m_last, ++first)
+			*m_last = *first;
+		*m_last = 0;
+	}
+
+	inline void string::swap(string& other) {
+		const pointer tfirst = m_first, tlast = m_last, tcapacity = m_capacity;
+		m_first = other.m_first, m_last = other.m_last, m_capacity = other.m_capacity;
+		other.m_first = tfirst, other.m_last = tlast, other.m_capacity = tcapacity;
+
+		char tbuffer[c_nbuffer];
+
+		if (m_first == other.m_buffer)
+			for  (pointer it = other.m_buffer, end = m_last, out = tbuffer; it != end; ++it, ++out)
+				*out = *it;
+
+		if (other.m_first == m_buffer) {
+			other.m_last = other.m_last - other.m_first + other.m_buffer;
+			other.m_first = other.m_buffer;
+			other.m_capacity = other.m_buffer + c_nbuffer;
+
+			for (pointer it = other.m_first, end = other.m_last, in = m_buffer; it != end; ++it, ++in)
+				*it = *in;
+			*other.m_last = 0;
+		}
+
+		if (m_first == other.m_buffer) {
+			m_last = m_last - m_first + m_buffer;
+			m_first = m_buffer;
+			m_capacity = m_buffer + c_nbuffer;
+
+			for (pointer it = m_first, end = m_last, in = tbuffer; it != end; ++it, ++in)
+				*it = *in;
+			*m_last = 0;
+		}
+	}
+
+	inline bool operator==(const string& lhs, const string& rhs) {
+		typedef const char* pointer;
+
+		const size_t lsize = lhs.size(), rsize = rhs.size();
+		if (lsize != rsize)
+			return false;
+
+		pointer lit = lhs.c_str(), rit = rhs.c_str();
+		pointer lend = lit + lsize;
+		while (lit != lend)
+			if (*lit++ != *rit++)
+				return false;
+
+		return true;
+	}
+
+	static inline size_t hash(const string& value) {
+		return hash_string(value.c_str(), value.size());
+	}
+}
+
+#endif

+ 85 - 0
include/tinystl/traits.h

@@ -0,0 +1,85 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_TRAITS_H
+#define TINYSTL_TRAITS_H
+
+#include "new.h"
+
+#if defined(__GNUC__)
+#	define TINYSTL_TRY_POD_OPTIMIZATION(t) __is_pod(t)
+#elif defined(_MSC_VER)
+#	define TINYSTL_TRY_POD_OPTIMIZATION(t) (!__is_class(t) || __is_pod(t))
+#else
+#	define TINYSTL_TRY_POD_OPTIMIZATION(t) false
+#endif
+
+namespace tinystl {
+	template<typename T, bool pod = TINYSTL_TRY_POD_OPTIMIZATION(T)> struct pod_traits {};
+
+	template<typename T, T t> struct swap_holder;
+
+	template<typename T>
+	static inline void move_impl(T& a, T& b, ...) {
+		a = b;
+	}
+
+	template<typename T>
+	static inline void move_impl(T& a, T& b, T*, swap_holder<void (T::*)(T&), &T::swap>* = 0) {
+		a.swap(b);
+	}
+
+	template<typename T>
+	static inline void move(T& a, T&b) {
+		move_impl(a, b, (T*)0);
+	}
+
+	template<typename T>
+	static inline void move_construct_impl(T* a, T& b, ...) {
+		new(placeholder(), a) T(b);
+	}
+
+	template<typename T>
+	static inline void move_construct_impl(T* a, T& b, void*, swap_holder<void (T::*)(T&), &T::swap>* = 0) {
+		// If your type T does not have a default constructor, simply insert:
+		// struct tinystl_nomove_construct;
+		// in the class definition
+		new(placeholder(), a) T;
+		a->swap(b);
+	}
+
+	template<typename T>
+	static inline void move_construct_impl(T* a, T& b, T*, typename T::tinystl_nomove_construct* = 0) {
+		new(placeholder(), a) T(b);
+	}
+
+	template<typename T>
+	static inline void move_construct(T* a, T& b) {
+		move_construct_impl(a, b, (T*)0);
+	}
+}
+
+#endif

+ 241 - 0
include/tinystl/unordered_map.h

@@ -0,0 +1,241 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_UNORDERED_MAP_H
+#define TINYSTL_UNORDERED_MAP_H
+
+#include "allocator.h"
+#include "buffer.h"
+#include "hash.h"
+#include "hash_base.h"
+
+namespace tinystl {
+
+	template<typename Key, typename Value, typename Alloc = TINYSTL_ALLOCATOR>
+	class unordered_map {
+	public:
+		unordered_map();
+		unordered_map(const unordered_map& other);
+		~unordered_map();
+
+		unordered_map& operator=(const unordered_map& other);
+
+
+		typedef pair<Key, Value> value_type;
+		
+		typedef unordered_hash_iterator<const unordered_hash_node<Key, Value> > const_iterator;
+		typedef unordered_hash_iterator<unordered_hash_node<Key, Value> > iterator;
+
+		iterator begin();
+		iterator end();
+
+		const_iterator begin() const;
+		const_iterator end() const;
+
+		void clear();
+		bool empty() const;
+		size_t size() const;
+
+		const_iterator find(const Key& key) const;
+		iterator find(const Key& key);
+		pair<iterator, bool> insert(const pair<Key, Value>& p);
+		void erase(const_iterator where);
+
+		Value& operator[](const Key& key);
+
+		void swap(unordered_map& other);
+
+	private:
+
+		typedef unordered_hash_node<Key, Value>* pointer;
+
+		size_t m_size;
+		tinystl::buffer<pointer, Alloc> m_buckets;
+	};
+
+	template<typename Key, typename Value, typename Alloc>
+	unordered_map<Key, Value, Alloc>::unordered_map()
+		: m_size(0)
+	{
+		buffer_init<pointer, Alloc>(&m_buckets);
+		buffer_resize<pointer, Alloc>(&m_buckets, 9, 0);
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	unordered_map<Key, Value, Alloc>::unordered_map(const unordered_map& other)
+		: m_size(other.m_size)
+	{
+		const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first);
+		buffer_init<pointer, Alloc>(&m_buckets);
+		buffer_resize<pointer, Alloc>(&m_buckets, nbuckets, 0);
+
+		for (pointer it = *other.m_buckets.first; it; it = it->next) {
+			unordered_hash_node<Key, Value>* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node<Key, Value>))) unordered_hash_node<Key, Value>(it->first, it->second);
+			newnode->next = newnode->prev = 0;
+
+			unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1);
+		}
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	unordered_map<Key, Value, Alloc>::~unordered_map() {
+		clear();
+		buffer_destroy<pointer, Alloc>(&m_buckets);
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	unordered_map<Key, Value, Alloc>& unordered_map<Key, Value, Alloc>::operator=(const unordered_map<Key, Value, Alloc>& other) {
+		unordered_map<Key, Value, Alloc>(other).swap(*this);
+		return *this;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::iterator unordered_map<Key, Value, Alloc>::begin() {
+		iterator it;
+		it.node = *m_buckets.first;
+		return it;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::iterator unordered_map<Key, Value, Alloc>::end() {
+		iterator it;
+		it.node = 0;
+		return it;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::const_iterator unordered_map<Key, Value, Alloc>::begin() const {
+		const_iterator cit;
+		cit.node = *m_buckets.first;
+		return cit;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::const_iterator unordered_map<Key, Value, Alloc>::end() const {
+		const_iterator cit;
+		cit.node = 0;
+		return cit;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline bool unordered_map<Key, Value, Alloc>::empty() const {
+		return m_size == 0;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline size_t unordered_map<Key, Value, Alloc>::size() const {
+		return m_size;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline void unordered_map<Key, Value, Alloc>::clear() {
+		pointer it = *m_buckets.first;
+		while (it) {
+			const pointer next = it->next;
+			it->~unordered_hash_node<Key, Value>();
+			Alloc::static_deallocate(it, sizeof(unordered_hash_node<Key, Value>));
+
+			it = next;
+		}
+
+		m_buckets.last = m_buckets.first;
+		buffer_resize<pointer, Alloc>(&m_buckets, 9, 0);
+		m_size = 0;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::iterator unordered_map<Key, Value, Alloc>::find(const Key& key) {
+		iterator result;
+		result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first));
+		return result;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline typename unordered_map<Key, Value, Alloc>::const_iterator unordered_map<Key, Value, Alloc>::find(const Key& key) const {
+		iterator result;
+		result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first));
+		return result;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	inline pair<typename unordered_map<Key, Value, Alloc>::iterator, bool> unordered_map<Key, Value, Alloc>::insert(const pair<Key, Value>& p) {
+		pair<iterator, bool> result;
+		result.second = false;
+
+		result.first = find(p.first);
+		if (result.first.node != 0)
+			return result;
+		
+		unordered_hash_node<Key, Value>* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node<Key, Value>))) unordered_hash_node<Key, Value>(p.first, p.second);
+		newnode->next = newnode->prev = 0;
+
+		const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first);
+		unordered_hash_node_insert(newnode, hash(p.first), m_buckets.first, nbuckets - 1);
+
+		++m_size;
+		if (m_size + 1 > 4 * nbuckets) {
+			pointer root = *m_buckets.first;
+			
+			const size_t newnbuckets = ((size_t)(m_buckets.last - m_buckets.first) - 1) * 8;
+			m_buckets.last = m_buckets.first;
+			buffer_resize<pointer, Alloc>(&m_buckets, newnbuckets + 1, 0);
+			unordered_hash_node<Key, Value>** buckets = m_buckets.first;
+
+			while (root) {
+				const pointer next = root->next;
+				root->next = root->prev = 0;
+				unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets);
+				root = next;
+			}
+		}
+
+		result.first.node = newnode;
+		result.second = true;
+		return result;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	void unordered_map<Key, Value, Alloc>::erase(const_iterator where) {
+		unordered_hash_node_erase(where.node, hash(where->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1);
+
+		where->~unordered_hash_node<Key, Value>();
+		Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node<Key, Value>));
+		--m_size;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	Value& unordered_map<Key, Value, Alloc>::operator[](const Key& key) {
+		return insert(pair<Key, Value>(key, Value())).first->second;
+	}
+
+	template<typename Key, typename Value, typename Alloc>
+	void unordered_map<Key, Value, Alloc>::swap(unordered_map& other) {
+		size_t tsize = other.m_size;
+		other.m_size = m_size, m_size = tsize;
+		buffer_swap(&m_buckets, &other.m_buckets);
+	}
+}
+#endif

+ 216 - 0
include/tinystl/unordered_set.h

@@ -0,0 +1,216 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_UNORDERED_SET_H
+#define TINYSTL_UNORDERED_SET_H
+
+#include "allocator.h"
+#include "buffer.h"
+#include "hash.h"
+#include "hash_base.h"
+
+namespace tinystl {
+
+	template<typename Key, typename Alloc = TINYSTL_ALLOCATOR>
+	class unordered_set {
+	public:
+		unordered_set();
+		unordered_set(const unordered_set& other);
+		~unordered_set();
+
+		unordered_set& operator=(const unordered_set& other);
+
+		typedef unordered_hash_iterator<const unordered_hash_node<Key, void> > const_iterator;
+		typedef const_iterator iterator;
+
+		iterator begin() const;
+		iterator end() const;
+
+		void clear();
+		bool empty() const;
+		size_t size() const;
+
+		iterator find(const Key& key) const;
+		pair<iterator, bool> insert(const Key& key);
+		void erase(iterator where);
+		size_t erase(const Key& key);
+
+		void swap(unordered_set& other);
+
+	private:
+
+		typedef unordered_hash_node<Key, void>* pointer;
+
+		size_t m_size;
+		tinystl::buffer<pointer, Alloc> m_buckets;
+	};
+
+	template<typename Key, typename Alloc>
+	unordered_set<Key, Alloc>::unordered_set()
+		: m_size(0)
+	{
+		buffer_init<pointer, Alloc>(&m_buckets);
+		buffer_resize<pointer, Alloc>(&m_buckets, 9, 0);
+	}
+
+	template<typename Key, typename Alloc>
+	unordered_set<Key, Alloc>::unordered_set(const unordered_set& other)
+		: m_size(other.m_size)
+	{
+		const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first);
+		buffer_init<pointer, Alloc>(&m_buckets);
+		buffer_resize<pointer, Alloc>(&m_buckets, 9, 0);
+
+		for (pointer* it = *other.m_buckets.first; it; it = it->next) {
+			unordered_hash_node<Key, void>* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node<Key, void>))) unordered_hash_node<Key, void>(*it);
+			newnode->next = newnode->prev = 0;
+			unordered_hash_node_insert(newnode, hash(*it), m_buckets.first, nbuckets - 1);
+		}
+	}
+
+	template<typename Key, typename Alloc>
+	unordered_set<Key, Alloc>::~unordered_set() {
+		clear();
+		buffer_destroy<pointer, Alloc>(&m_buckets);
+	}
+
+	template<typename Key, typename Alloc>
+	unordered_set<Key, Alloc>& unordered_set<Key, Alloc>::operator=(const unordered_set<Key, Alloc>& other) {
+		unordered_set<Key, Alloc>(other).swap(*this);
+		return *this;
+	}
+
+	template<typename Key, typename Alloc>
+	inline typename unordered_set<Key, Alloc>::iterator unordered_set<Key, Alloc>::begin() const {
+		iterator cit;
+		cit.node = *m_buckets.first;
+		return cit;
+	}
+
+	template<typename Key, typename Alloc>
+	inline typename unordered_set<Key, Alloc>::iterator unordered_set<Key, Alloc>::end() const {
+		iterator cit;
+		cit.node = 0;
+		return cit;
+	}
+
+	template<typename Key, typename Alloc>
+	inline bool unordered_set<Key, Alloc>::empty() const {
+		return m_size == 0;
+	}
+
+	template<typename Key, typename Alloc>
+	inline size_t unordered_set<Key, Alloc>::size() const {
+		return m_size;
+	}
+
+	template<typename Key, typename Alloc>
+	inline void unordered_set<Key, Alloc>::clear() {
+		pointer it = *m_buckets.first;
+		while (it) {
+			const pointer next = it->next;
+			it->~unordered_hash_node<Key, void>();
+			Alloc::static_deallocate(it, sizeof(unordered_hash_node<Key, void>));
+
+			it = next;
+		}
+
+		m_buckets.last = m_buckets.first;
+		buffer_resize<pointer, Alloc>(&m_buckets, 9, 0);
+		m_size = 0;
+	}
+
+	template<typename Key, typename Alloc>
+	inline typename unordered_set<Key, Alloc>::iterator unordered_set<Key, Alloc>::find(const Key& key) const {
+		iterator result;
+		result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first));
+		return result;
+	}
+
+	template<typename Key, typename Alloc>
+	inline pair<typename unordered_set<Key, Alloc>::iterator, bool> unordered_set<Key, Alloc>::insert(const Key& key) {
+		pair<iterator, bool> result;
+		result.second = false;
+
+		result.first = find(key);
+		if (result.first.node != 0)
+			return result;
+
+		unordered_hash_node<Key, void>* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node<Key, void>))) unordered_hash_node<Key, void>(key);
+		newnode->next = newnode->prev = 0;
+
+		const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first);
+		unordered_hash_node_insert(newnode, hash(key), m_buckets.first, nbuckets - 1);
+
+		++m_size;
+		if (m_size + 1 > 4 * nbuckets) {
+			pointer root = *m_buckets.first;
+
+			const size_t newnbuckets = ((size_t)(m_buckets.last - m_buckets.first) - 1) * 8;
+			m_buckets.last = m_buckets.first;
+			buffer_resize<pointer, Alloc>(&m_buckets, newnbuckets + 1, 0);
+			unordered_hash_node<Key, void>** buckets = m_buckets.first;
+
+			while (root) {
+				const pointer next = root->next;
+				root->next = root->prev = 0;
+				unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets);
+				root = next;
+			}
+		}
+
+		result.first.node = newnode;
+		result.second = true;
+		return result;
+	}
+
+	template<typename Key, typename Alloc>
+	inline void unordered_set<Key, Alloc>::erase(iterator where) {
+		unordered_hash_node_erase(where.node, hash(where.node->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1);
+
+		where.node->~unordered_hash_node<Key, void>();
+		Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node<Key, void>));
+		--m_size;
+	}
+
+	template<typename Key, typename Alloc>
+	inline size_t unordered_set<Key, Alloc>::erase(const Key& key) {
+		const iterator it = find(key);
+		if (it.node == 0)
+			return 0;
+
+		erase(it);
+		return 1;
+	}
+
+	template <typename Key, typename Alloc>
+	void unordered_set<Key, Alloc>::swap(unordered_set& other) {
+		size_t tsize = other.m_size;
+		other.m_size = m_size, m_size = tsize;
+		buffer_swap(&m_buckets, &other.m_buckets);
+	}
+}
+#endif

+ 268 - 0
include/tinystl/vector.h

@@ -0,0 +1,268 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TINYSTL_VECTOR_H
+#define TINYSTL_VECTOR_H
+
+#include "allocator.h"
+#include "buffer.h"
+#include "new.h"
+#include "stddef.h"
+
+namespace tinystl {
+
+	template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
+	class vector {
+	public:
+		vector();
+		vector(const vector& other);
+		vector(size_t size);
+		vector(size_t size, const T& value);
+		vector(const T* first, const T* last);
+		~vector();
+
+		vector& operator=(const vector& other);
+
+		void assign(const T* first, const T* last);
+
+		const T* data() const;
+		T* data();
+		size_t size() const;
+		bool empty() const;
+
+		T& operator[](size_t idx);
+		const T& operator[](size_t idx) const;
+
+		const T& back() const;
+		T& back();
+
+		void resize(size_t size);
+		void resize(size_t size, const T& value);
+		void clear();
+		void reserve(size_t capacity);
+
+		void push_back(const T& t);
+		void pop_back();
+
+		void swap(vector& other);
+
+		typedef T value_type;
+
+		typedef T* iterator;
+		iterator begin();
+		iterator end();
+
+		typedef const T* const_iterator;
+		const_iterator begin() const;
+		const_iterator end() const;
+
+		void insert(iterator where, const T& value);
+		void insert(iterator where, const T* first, const T* last);
+
+		iterator erase(iterator where);
+		iterator erase(iterator first, iterator last);
+
+		iterator erase_unordered(iterator where);
+		iterator erase_unordered(iterator first, iterator last);
+
+	private:
+		buffer<T, Alloc> m_buffer;
+	};
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::vector() {
+		buffer_init(&m_buffer);
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::vector(const vector& other) {
+		buffer_init(&m_buffer);
+		buffer_reserve(&m_buffer, other.size());
+		buffer_insert(&m_buffer, m_buffer.last, other.m_buffer.first, other.m_buffer.last);
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::vector(size_t size) {
+		buffer_init(&m_buffer);
+		buffer_resize(&m_buffer, size, T());
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::vector(size_t size, const T& value) {
+		buffer_init(&m_buffer);
+		buffer_resize(&m_buffer, size, value);
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::vector(const T* first, const T* last) {
+		buffer_init(&m_buffer);
+		buffer_insert(&m_buffer, m_buffer.last, first, last);
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>::~vector() {
+		buffer_destroy(&m_buffer);
+	}
+
+	template<typename T, typename Alloc>
+	inline vector<T, Alloc>& vector<T, Alloc>::operator=(const vector& other) {
+		vector(other).swap(*this);
+		return *this;
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::assign(const T* first, const T* last) {
+		buffer_clear(&m_buffer);
+		buffer_insert(&m_buffer, m_buffer.last, first, last);
+	}
+
+	template<typename T, typename Alloc>
+	inline const T* vector<T, Alloc>::data() const {
+		return m_buffer.first;
+	}
+
+	template<typename T, typename Alloc>
+	inline T* vector<T, Alloc>::data() {
+		return m_buffer.first;
+	}
+
+	template<typename T, typename Alloc>
+	inline size_t vector<T, Alloc>::size() const {
+		return (size_t)(m_buffer.last - m_buffer.first);
+	}
+
+	template<typename T, typename Alloc>
+	inline bool vector<T, Alloc>::empty() const {
+		return m_buffer.last == m_buffer.first;
+	}
+
+	template<typename T, typename Alloc>
+	inline T& vector<T, Alloc>::operator[](size_t idx) {
+		return m_buffer.first[idx];
+	}
+
+	template<typename T, typename Alloc>
+	inline const T& vector<T, Alloc>::operator[](size_t idx) const {
+		return m_buffer.first[idx];
+	}
+
+	template<typename T, typename Alloc>
+	inline const T& vector<T, Alloc>::back() const {
+		return m_buffer.last[-1];
+	}
+
+	template<typename T, typename Alloc>
+	inline T& vector<T, Alloc>::back() {
+		return m_buffer.last[-1];
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::resize(size_t size) {
+		buffer_resize(&m_buffer, size, T());
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::resize(size_t size, const T& value) {
+		buffer_resize(&m_buffer, size, value);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::clear() {
+		buffer_clear(&m_buffer);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::reserve(size_t capacity) {
+		buffer_reserve(&m_buffer, capacity);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::push_back(const T& t) {
+		buffer_insert(&m_buffer, m_buffer.last, &t, &t + 1);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::pop_back() {
+		buffer_erase(&m_buffer, m_buffer.last - 1, m_buffer.last);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::swap(vector& other) {
+		buffer_swap(&m_buffer, &other.m_buffer);
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T,Alloc>::begin() {
+		return m_buffer.first;
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T,Alloc>::end() {
+		return m_buffer.last;
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::const_iterator vector<T,Alloc>::begin() const {
+		return m_buffer.first;
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::const_iterator vector<T,Alloc>::end() const {
+		return m_buffer.last;
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::insert(iterator where, const T& value) {
+		buffer_insert(&m_buffer, where, &value, &value + 1);
+	}
+
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::insert(iterator where, const T* first, const T* last) {
+		buffer_insert(&m_buffer, where, first, last);
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T, Alloc>::erase(iterator where) {
+		return buffer_erase(&m_buffer, where, where + 1);
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T, Alloc>::erase(iterator first, iterator last) {
+		return buffer_erase(&m_buffer, first, last);
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T, Alloc>::erase_unordered(iterator where) {
+		return buffer_erase_unordered(&m_buffer, where, where + 1);
+	}
+
+	template<typename T, typename Alloc>
+	inline typename vector<T, Alloc>::iterator vector<T, Alloc>::erase_unordered(iterator first, iterator last) {
+		return buffer_erase_unordered(&m_buffer, first, last);
+	}
+}
+
+#endif 

+ 57 - 0
makefile

@@ -0,0 +1,57 @@
+#
+# Copyright 2011-2013 Branimir Karadzic. All rights reserved.
+# License: http://www.opensource.org/licenses/BSD-2-Clause
+#
+
+all:
+	premake4 --file=premake/premake4.lua vs2008
+	premake4 --file=premake/premake4.lua vs2010
+	premake4 --file=premake/premake4.lua --gcc=mingw gmake
+	premake4 --file=premake/premake4.lua --gcc=linux gmake
+	premake4 --file=premake/premake4.lua --gcc=osx gmake
+	premake4 --file=premake/premake4.lua xcode4
+
+linux-debug32:
+	make -R -C .build/projects/gmake-linux config=debug32
+linux-release32:
+	make -R -C .build/projects/gmake-linux config=release32
+linux-debug64:
+	make -R -C .build/projects/gmake-linux config=debug64
+linux-release64:
+	make -R -C .build/projects/gmake-linux config=release64
+linux: linux-debug32 linux-release32 linux-debug64 linux-release64
+
+mingw-debug32:
+	make -R -C .build/projects/gmake-mingw config=debug32
+mingw-release32:
+	make -R -C .build/projects/gmake-mingw config=release32
+mingw-debug64:
+	make -R -C .build/projects/gmake-mingw config=debug64
+mingw-release64:
+	make -R -C .build/projects/gmake-mingw config=release64
+mingw: mingw-debug32 mingw-release32 mingw-debug64 mingw-release64
+
+vs2008-debug32:
+	devenv .build/projects/vs2008/bgfx.sln /Build "Debug|Win32"
+vs2008-release32:
+	devenv .build/projects/vs2008/bgfx.sln /Build "Release|Win32"
+vs2008-debug64:
+	devenv .build/projects/vs2008/bgfx.sln /Build "Debug|x64"
+vs2008-release64:
+	devenv .build/projects/vs2008/bgfx.sln /Build "Release|x64"
+vs2008: vs2008-debug32 vs2008-release32 vs2008-debug64 vs2008-release64
+
+osx-debug32:
+	make -C .build/projects/gmake-osx config=debug32
+osx-release32:
+	make -C .build/projects/gmake-osx config=release32
+osx-debug64:
+	make -C .build/projects/gmake-osx config=debug64
+osx-release64:
+	make -C .build/projects/gmake-osx config=release64
+osx: osx-debug32 osx-release32 osx-debug64 osx-release64
+
+clean:
+	@echo Cleaning...
+	-rm -r .build
+	-rm -r .debug

+ 5 - 0
premake/bx.lua

@@ -1,3 +1,8 @@
+--
+-- Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+-- License: http://www.opensource.org/licenses/BSD-2-Clause
+--
+ 
 project "bx"
 	uuid "4db0b09e-d6df-11e1-a0ec-65ccdd6a022f"
 	kind "StaticLib"

+ 54 - 0
premake/premake4.lua

@@ -0,0 +1,54 @@
+--
+-- Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+-- License: http://www.opensource.org/licenses/BSD-2-Clause
+--
+
+solution "bx"
+	configurations {
+		"Debug",
+		"Release",
+	}
+
+	platforms {
+		"x32",
+		"x64",
+	}
+
+	language "C++"
+
+BX_DIR = (path.getabsolute("..") .. "/")
+local BX_BUILD_DIR = (BX_DIR .. ".build/")
+local BX_THIRD_PARTY_DIR = (BX_DIR .. "3rdparty/")
+
+defines {
+	"BX_CONFIG_ENABLE_MSVC_LEVEL4_WARNINGS=1"
+}
+
+dofile (BX_DIR .. "premake/toolchain.lua")
+toolchain(BX_BUILD_DIR, BX_THIRD_PARTY_DIR)
+
+function copyLib()
+end
+
+dofile "bx.lua"
+dofile "unittest++.lua"
+
+project "bx.test"
+	uuid "8a653da8-23d6-11e3-acb4-887628d43830"
+	kind "ConsoleApp"
+
+	debugdir (BX_DIR .."tests")
+
+	includedirs {
+		BX_DIR .. "include",
+		BX_THIRD_PARTY_DIR .. "UnitTest++/src/",
+	}
+
+	links {
+		"UnitTest++",
+	}
+
+	files {
+		BX_DIR .. "test/**.cpp",
+		BX_DIR .. "test/**.H",
+	}

+ 45 - 0
premake/unittest++.lua

@@ -0,0 +1,45 @@
+--
+-- Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+-- License: http://www.opensource.org/licenses/BSD-2-Clause
+--
+
+function flagsremove(name)
+	-- bx's toolchain.lua disables exceptions everywhere
+	-- this function can remove some of those flags when
+	-- needed.
+	local container, err = premake.getobject("solution")
+	for _, block in pairs(container["blocks"]) do
+		local tbl = block["flags"]
+		for index, value in pairs(tbl) do
+			if value == name then
+				table.remove(tbl, index)
+				print(index, value, type(value))
+			end
+		end
+	end
+end
+
+project "UnitTest++"
+	uuid "ab932f5c-2409-11e3-b000-887628d43830"
+	kind "StaticLib"
+
+	flagsremove("NoExceptions")
+
+	files {
+		"../3rdparty/UnitTest++/src/*.cpp",
+		"../3rdparty/UnitTest++/src/*.h",
+	}
+
+	configuration { "linux or osx" }
+		files {
+			"../3rdparty/UnitTest++/src/Posix/**.cpp",
+			"../3rdparty/UnitTest++/src/Posix/**.h",
+		}
+
+	configuration { "windows" }
+		files {
+			"../3rdparty/UnitTest++/src/Win32/**.cpp",
+			"../3rdparty/UnitTest++/src/Win32/**.h",
+		}
+
+	configuration {}

+ 31 - 0
test/main.cpp

@@ -0,0 +1,31 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+
+int main() {
+	return UnitTest::RunAllTests();
+}

+ 16 - 0
test/test.h

@@ -0,0 +1,16 @@
+/*
+ * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#ifndef __TEST_H__
+#define __TEST_H__
+
+#include <bx/bx.h>
+#include <UnitTest++.h>
+
+#if !BX_COMPILER_MSVC
+#	define _strdup strdup
+#endif // !BX_COMPILER_MSVC
+
+#endif // __TEST_H__

+ 263 - 0
test/vector_complex.cpp

@@ -0,0 +1,263 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+#include <tinystl/vector.h>
+#include <algorithm>
+#include <string.h>
+#include <stdlib.h>
+
+struct complex {
+	complex() {data = 0;}
+	complex(const char* s) { data = _strdup(s); }
+	~complex() { free(data); }
+	complex(const complex& other) { data = 0; if (other.data) data = _strdup(other.data); }
+	complex& operator=(const complex& other) { complex(other).swap(*this); return *this; }
+	void swap(complex& other) { std::swap(data, other.data); }
+
+	char* data;
+};
+
+static inline bool operator==(const complex& lhs, const complex& rhs) {
+	if (lhs.data == 0 && rhs.data == 0)
+		return true;
+	if (lhs.data != 0 && rhs.data != 0)
+		return 0 == strcmp(lhs.data, rhs.data);
+	return false;
+}
+
+TEST(vector_complex_constructor) {
+	typedef tinystl::vector<complex> vector;
+
+	{
+		vector v;
+		CHECK( v.empty() );
+		CHECK( v.size() == 0 );
+	}
+	{
+		const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector v(array, array + 10);
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+	}
+	{
+		const complex value = "127";
+		const size_t count = 24;
+		vector v(count, value);
+
+		CHECK( v.size() == count );
+
+		vector::iterator it = v.begin(), end = v.end();
+		for (; it != end; ++it)
+			CHECK(*it == value);
+	}
+	{
+		const size_t count = 24;
+		vector v(count);
+
+		CHECK(v.size() == count);
+		vector::iterator it = v.begin(), end = v.end();
+		for (; it != end; ++it)
+			CHECK(*it == complex());
+	}
+	{
+		const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector other(array, array + 10);
+		vector v = other;
+
+		CHECK( v.size() == other.size() );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_complex_assignment) {
+	typedef tinystl::vector<complex> vector;
+
+	{
+		const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector other(array, array + 10);
+
+		vector v;
+		v = other;
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+		CHECK( other.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_complex_pushback) {
+	tinystl::vector<complex> v;
+	v.push_back("42");
+
+	CHECK(v.size() == 1);
+	CHECK(v[0] == "42");
+}
+
+TEST(vector_complex_vector) {
+	tinystl::vector< tinystl::vector<complex> > v(10, tinystl::vector<complex>());
+
+	tinystl::vector< tinystl::vector<complex> >::iterator it = v.begin(), end = v.end();
+	for (; it != end; ++it) {
+		CHECK( (*it).empty() );
+		CHECK( (*it).size() == 0 );
+		CHECK( (*it).begin() == (*it).end() );
+	}
+}
+
+TEST(vector_complex_swap) {
+	tinystl::vector<complex> v1;
+	v1.push_back("12");
+	v1.push_back("20");
+
+	tinystl::vector<complex> v2;
+	v2.push_back("54");
+
+	v1.swap(v2);
+
+	CHECK(v1.size() == 1);
+	CHECK(v2.size() == 2);
+	CHECK(v1[0] == "54");
+	CHECK(v2[0] == "12");
+	CHECK(v2[1] == "20");
+}
+
+TEST(vector_complex_popback) {
+	tinystl::vector<complex> v;
+	v.push_back("12");
+	v.push_back("24");
+
+	CHECK(v.back() == "24");
+	
+	v.pop_back();
+
+	CHECK(v.back() == "12");
+	CHECK(v.size() == 1);
+}
+
+TEST(vector_complex_assign) {
+	tinystl::vector<complex> v;
+
+	CHECK(v.size() == 0);
+
+	const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	v.assign(array, array + 10);
+	CHECK(v.size() == 10);
+	CHECK( std::equal(v.begin(), v.end(), array) );
+}
+
+TEST(vector_complex_erase) {
+	const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	tinystl::vector<complex> v(array, array + 10);
+
+	tinystl::vector<complex>::iterator it = v.erase(v.begin());
+	CHECK(*it == "2");
+	CHECK(v.size() == 9);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	it = v.erase(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	v.erase(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK(v[0] == "2");
+	CHECK(v[1] == "9");
+}
+
+TEST(vector_complex_erase_unordered) {
+	const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	typedef tinystl::vector<complex> vector;
+	vector v(array, array + 10);
+
+	complex first = *(v.begin());
+	vector::iterator it = v.erase_unordered(v.begin());
+	CHECK(it == v.begin());
+	CHECK(v.size() == 9);
+	CHECK( std::count(v.begin(), v.end(), first) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	complex last = *(v.end() - 1);
+	it = v.erase_unordered(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::count(v.begin(), v.end(), last) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	first = *(v.begin());
+	last = *(v.end() - 1);
+	v.erase_unordered(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK( std::count(v.begin(), v.end(), first) == 1 );
+	CHECK( std::count(v.begin(), v.end(), last) == 1 );
+}
+
+TEST(vector_complex_insert) {
+	const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	tinystl::vector<complex> v(array, array + 10);
+
+	v.insert(v.begin(), "0");
+	CHECK(v.size() == 11);
+	CHECK(v[0] == "0");
+	CHECK( std::equal(v.begin() + 1, v.end(), array) );
+
+	v.insert(v.end(), "11");
+	CHECK(v.size() == 12);
+	CHECK(v[0] == "0");
+	CHECK( std::equal(array, array + 10, v.begin() + 1) );
+	CHECK(v.back() == "11");
+
+	const complex array2[3] = {"11", "12", "13"};
+	const complex finalarray[] = {"0", "1", "2", "3", "11", "12", "13", "4", "5", "6", "7", "8", "9", "10", "11"};
+	v.insert(v.begin() + 4, array2, array2 + 3);
+	CHECK( v.size() == 15 );
+	CHECK( std::equal(v.begin(), v.end(), finalarray) );
+}
+
+TEST(vector_complex_iterator) {
+	const complex array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+
+	tinystl::vector<complex> v(array, array + 10);
+	const tinystl::vector<complex>& cv = v;
+
+	CHECK(v.data() == &*v.begin());
+	CHECK(v.data() == &v[0]);
+	CHECK(v.data() + v.size() == &*v.end());
+	CHECK(v.begin() == cv.begin());
+	CHECK(v.end() == cv.end());
+	CHECK(v.data() == cv.data());
+
+	tinystl::vector<complex> w = v;
+	CHECK(v.begin() != w.begin());
+	CHECK(v.end() != w.end());
+}

+ 28 - 0
test/vector_header.cpp

@@ -0,0 +1,28 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Test that header is standalone
+#include <tinystl/vector.h>

+ 259 - 0
test/vector_nodefault.cpp

@@ -0,0 +1,259 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+#include <tinystl/vector.h>
+#include <algorithm>
+#include <string.h>
+#include <stdlib.h>
+
+#if !BX_COMPILER_MSVC
+#	define _strdup strdup
+#endif // !BX_COMPILER_MSVC
+
+struct nodefault {
+	nodefault(const char* s) { data = _strdup(s); }
+	~nodefault() { free(data); }
+	nodefault(const nodefault& other) { data = 0; if (other.data) data = _strdup(other.data); }
+	nodefault& operator=(const nodefault& other) { nodefault(other).swap(*this); return *this; }
+	void swap(nodefault& other) { std::swap(data, other.data); }
+
+	char* data;
+
+	struct tinystl_nomove_construct;
+};
+
+static inline bool operator==(const nodefault& lhs, const nodefault& rhs) {
+	if (lhs.data == 0 && rhs.data == 0)
+		return true;
+	if (lhs.data != 0 && rhs.data != 0)
+		return 0 == strcmp(lhs.data, rhs.data);
+	return false;
+}
+
+TEST(vector_nodefault_constructor) {
+	typedef tinystl::vector<nodefault> vector;
+
+	{
+		vector v;
+		CHECK( v.empty() );
+		CHECK( v.size() == 0 );
+	}
+	{
+		const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector v(array, array + 10);
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+	}
+	{
+		const nodefault value = "127";
+		const size_t count = 24;
+		vector v(count, value);
+
+		CHECK( v.size() == count );
+
+		vector::iterator it = v.begin(), end = v.end();
+		for (; it != end; ++it)
+			CHECK(*it == value);
+	}
+	{
+		const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector other(array, array + 10);
+		vector v = other;
+
+		CHECK( v.size() == other.size() );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_nodefault_assignment) {
+	typedef tinystl::vector<nodefault> vector;
+
+	{
+		const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+		vector other(array, array + 10);
+
+		vector v;
+		v = other;
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+		CHECK( other.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_nodefault_pushback) {
+	tinystl::vector<nodefault> v;
+	v.push_back("42");
+
+	CHECK(v.size() == 1);
+	CHECK(v[0] == "42");
+}
+
+TEST(vector_nodefault_vector) {
+	tinystl::vector< tinystl::vector<nodefault> > v(10, tinystl::vector<nodefault>());
+
+	tinystl::vector< tinystl::vector<nodefault> >::iterator it = v.begin(), end = v.end();
+	for (; it != end; ++it) {
+		CHECK( (*it).empty() );
+		CHECK( (*it).size() == 0 );
+		CHECK( (*it).begin() == (*it).end() );
+	}
+}
+
+TEST(vector_nodefault_swap) {
+	tinystl::vector<nodefault> v1;
+	v1.push_back("12");
+	v1.push_back("20");
+
+	tinystl::vector<nodefault> v2;
+	v2.push_back("54");
+
+	v1.swap(v2);
+
+	CHECK(v1.size() == 1);
+	CHECK(v2.size() == 2);
+	CHECK(v1[0] == "54");
+	CHECK(v2[0] == "12");
+	CHECK(v2[1] == "20");
+}
+
+TEST(vector_nodefault_popback) {
+	tinystl::vector<nodefault> v;
+	v.push_back("12");
+	v.push_back("24");
+
+	CHECK(v.back() == "24");
+	
+	v.pop_back();
+
+	CHECK(v.back() == "12");
+	CHECK(v.size() == 1);
+}
+
+TEST(vector_nodefault_assign) {
+	tinystl::vector<nodefault> v;
+
+	CHECK(v.size() == 0);
+
+	const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	v.assign(array, array + 10);
+	CHECK(v.size() == 10);
+	CHECK( std::equal(v.begin(), v.end(), array) );
+}
+
+TEST(vector_nodefault_erase) {
+	const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	tinystl::vector<nodefault> v(array, array + 10);
+
+	tinystl::vector<nodefault>::iterator it = v.erase(v.begin());
+	CHECK(*it == "2");
+	CHECK(v.size() == 9);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	it = v.erase(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	v.erase(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK(v[0] == "2");
+	CHECK(v[1] == "9");
+}
+
+TEST(vector_nodefault_erase_unordered) {
+	const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	typedef tinystl::vector<nodefault> vector;
+	vector v(array, array + 10);
+
+	nodefault first = *(v.begin());
+	vector::iterator it = v.erase_unordered(v.begin());
+	CHECK(it == v.begin());
+	CHECK(v.size() == 9);
+	CHECK( std::count(v.begin(), v.end(), first) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	nodefault last = *(v.end() - 1);
+	it = v.erase_unordered(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::count(v.begin(), v.end(), last) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	first = *(v.begin());
+	last = *(v.end() - 1);
+	v.erase_unordered(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK( std::count(v.begin(), v.end(), first) == 1 );
+	CHECK( std::count(v.begin(), v.end(), last) == 1 );
+}
+
+TEST(vector_nodefault_insert) {
+	const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+	tinystl::vector<nodefault> v(array, array + 10);
+
+	v.insert(v.begin(), "0");
+	CHECK(v.size() == 11);
+	CHECK(v[0] == "0");
+	CHECK( std::equal(v.begin() + 1, v.end(), array) );
+
+	v.insert(v.end(), "11");
+	CHECK(v.size() == 12);
+	CHECK(v[0] == "0");
+	CHECK( std::equal(array, array + 10, v.begin() + 1) );
+	CHECK(v.back() == "11");
+
+	const nodefault array2[3] = {"11", "12", "13"};
+	const nodefault finalarray[] = {"0", "1", "2", "3", "11", "12", "13", "4", "5", "6", "7", "8", "9", "10", "11"};
+	v.insert(v.begin() + 4, array2, array2 + 3);
+	CHECK( v.size() == 15 );
+	CHECK( std::equal(v.begin(), v.end(), finalarray) );
+}
+
+TEST(vector_nodefault_iterator) {
+	const nodefault array[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+
+	tinystl::vector<nodefault> v(array, array + 10);
+	const tinystl::vector<nodefault>& cv = v;
+
+	//CHECK(v.data() == &*v.begin());
+	//CHECK(v.data() == &v[0]);
+	//CHECK(v.data() + v.size() == &*v.end());
+	CHECK(v.begin() == cv.begin());
+	CHECK(v.end() == cv.end());
+	//CHECK(v.data() == cv.data());
+
+	tinystl::vector<nodefault> w = v;
+	CHECK(v.begin() != w.begin());
+	CHECK(v.end() != w.end());
+}

+ 242 - 0
test/vector_primitive.cpp

@@ -0,0 +1,242 @@
+/*-
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+#include <tinystl/vector.h>
+#include <algorithm>
+
+TEST(vector_constructor) {
+	typedef tinystl::vector<int> vector;
+
+	{
+		vector v;
+		CHECK( v.empty() );
+		CHECK( v.size() == 0 );
+	}
+	{
+		const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+		vector v(array, array + 10);
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+	}
+	{
+		const int value = 127;
+		const size_t count = 24;
+		vector v(count, value);
+
+		CHECK( v.size() == count );
+
+		vector::iterator it = v.begin(), end = v.end();
+		for (; it != end; ++it)
+			CHECK(*it == value);
+	}
+	{
+		const size_t count = 24;
+		vector v(count);
+
+		CHECK(v.size() == count);
+		vector::iterator it = v.begin(), end = v.end();
+		for (; it != end; ++it)
+			CHECK(*it == 0);
+	}
+	{
+		const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+		vector other(array, array + 10);
+		vector v = other;
+
+		CHECK( v.size() == other.size() );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_assignment) {
+	typedef tinystl::vector<int> vector;
+
+	{
+		const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+		vector other(array, array + 10);
+
+		vector v;
+		v = other;
+
+		CHECK( v.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), array) );
+		CHECK( other.size() == 10 );
+		CHECK( std::equal(v.begin(), v.end(), other.begin()) );
+	}
+}
+
+TEST(vector_pushback) {
+	tinystl::vector<int> v;
+	v.push_back(42);
+
+	CHECK(v.size() == 1);
+	CHECK(v[0] == 42);
+}
+
+TEST(vector_vector) {
+	tinystl::vector< tinystl::vector<int> > v(10, tinystl::vector<int>());
+
+	tinystl::vector< tinystl::vector<int> >::iterator it = v.begin(), end = v.end();
+	for (; it != end; ++it) {
+		CHECK( (*it).empty() );
+		CHECK( (*it).size() == 0 );
+		CHECK( (*it).begin() == (*it).end() );
+	}
+}
+
+TEST(vector_swap) {
+	tinystl::vector<int> v1;
+	v1.push_back(12);
+	v1.push_back(20);
+
+	tinystl::vector<int> v2;
+	v2.push_back(54);
+
+	v1.swap(v2);
+
+	CHECK(v1.size() == 1);
+	CHECK(v2.size() == 2);
+	CHECK(v1[0] == 54);
+	CHECK(v2[0] == 12);
+	CHECK(v2[1] == 20);
+}
+
+TEST(vector_popback) {
+	tinystl::vector<int> v;
+	v.push_back(12);
+	v.push_back(24);
+
+	CHECK(v.back() == 24);
+	
+	v.pop_back();
+
+	CHECK(v.back() == 12);
+	CHECK(v.size() == 1);
+}
+
+TEST(vector_assign) {
+	tinystl::vector<int> v;
+
+	CHECK(v.size() == 0);
+
+	const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+	v.assign(array, array + 10);
+	CHECK(v.size() == 10);
+	CHECK( std::equal(v.begin(), v.end(), array) );
+}
+
+TEST(vector_erase) {
+	const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+	tinystl::vector<int> v(array, array + 10);
+
+	tinystl::vector<int>::iterator it = v.erase(v.begin());
+	CHECK(*it == 2);
+	CHECK(v.size() == 9);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	it = v.erase(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::equal(v.begin(), v.end(), array + 1) );
+
+	v.erase(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK(v[0] == 2);
+	CHECK(v[1] == 9);
+}
+
+TEST(vector_erase_unordered) {
+	const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+	typedef tinystl::vector<int> vector;
+	vector v(array, array + 10);
+
+	int first = *(v.begin());
+	vector::iterator it = v.erase_unordered(v.begin());
+	CHECK(it == v.begin());
+	CHECK(v.size() == 9);
+	CHECK( std::count(v.begin(), v.end(), first) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	int last = *(v.end() - 1);
+	it = v.erase_unordered(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 8);
+	CHECK( std::count(v.begin(), v.end(), last) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	first = *(v.begin());
+	last = *(v.end() - 1);
+	v.erase_unordered(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK( std::count(v.begin(), v.end(), first) == 1 );
+	CHECK( std::count(v.begin(), v.end(), last) == 1 );
+}
+
+TEST(vector_insert) {
+	const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+	tinystl::vector<int> v(array, array + 10);
+
+	v.insert(v.begin(), 0);
+	CHECK(v.size() == 11);
+	CHECK(v[0] == 0);
+	CHECK( std::equal(v.begin() + 1, v.end(), array) );
+
+	v.insert(v.end(), 11);
+	CHECK(v.size() == 12);
+	CHECK(v[0] == 0);
+	CHECK( std::equal(array, array + 10, v.begin() + 1) );
+	CHECK(v.back() == 11);
+
+	const int array2[3] = {11, 12, 13};
+	const int finalarray[] = {0, 1, 2, 3, 11, 12, 13, 4, 5, 6, 7, 8, 9, 10, 11};
+	v.insert(v.begin() + 4, array2, array2 + 3);
+	CHECK( v.size() == 15 );
+	CHECK( std::equal(v.begin(), v.end(), finalarray) );
+}
+
+TEST(vector_iterator) {
+	const int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+
+	tinystl::vector<int> v(array, array + 10);
+	const tinystl::vector<int>& cv = v;
+
+	CHECK(v.data() == &*v.begin());
+	CHECK(v.data() == &v[0]);
+	CHECK(v.data() + v.size() == &*v.end());
+	CHECK(v.begin() == cv.begin());
+	CHECK(v.end() == cv.end());
+	CHECK(v.data() == cv.data());
+
+	tinystl::vector<int> w = v;
+	CHECK(v.begin() != w.begin());
+	CHECK(v.end() != w.end());
+}