From: <ric...@us...> - 2013-06-19 02:23:07
|
Revision: 1184 http://sourceforge.net/p/loki-lib/code/1184 Author: rich_sposato Date: 2013-06-19 02:23:00 +0000 (Wed, 19 Jun 2013) Log Message: ----------- Added SmartAssert to Loki. Modified Paths: -------------- trunk/Loki.cbp trunk/Loki.sln trunk/Loki.workspace trunk/include/loki/ScopeGuard.h Added Paths: ----------- trunk/include/loki/Concatenate.h trunk/include/loki/SmartAssert.hpp trunk/src/SmartAssert.cpp trunk/test/SmartAssert/ trunk/test/SmartAssert/SmartAssert.cbp trunk/test/SmartAssert/SmartAssert.vcxproj trunk/test/SmartAssert/main.cpp Modified: trunk/Loki.cbp =================================================================== --- trunk/Loki.cbp 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.cbp 2013-06-19 02:23:00 UTC (rev 1184) @@ -6,9 +6,9 @@ <Option compiler="cygwin" /> <Build> <Target title="Debug_GCC"> - <Option output="./lib/GCC/Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\GCC\Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Debug_GCC/" /> + <Option object_output="obj\Debug_GCC\" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> @@ -17,27 +17,27 @@ <Add option="-W" /> <Add option="-DDEBUG" /> <Add directory="." /> - <Add directory="./include" /> - <Add directory="./include/loki" /> + <Add directory=".\include" /> + <Add directory=".\include\loki" /> </Compiler> </Target> <Target title="Release_GCC"> - <Option output="./lib/GCC/Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\GCC\Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Release_GCC/" /> + <Option object_output="obj\Release_GCC\" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory="./include/loki" /> - <Add directory="./include" /> + <Add directory=".\include\loki" /> + <Add directory=".\include" /> </Compiler> </Target> <Target title="Debug_Cygwin"> - <Option output="./lib/Cygwin/Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\Cygwin\Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Debug_Cygwin/" /> + <Option object_output="obj\Debug_Cygwin\" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> @@ -45,88 +45,90 @@ <Add option="-W" /> <Add option="-g" /> <Add directory="." /> - <Add directory="./include" /> - <Add directory="./include/loki" /> + <Add directory=".\include" /> + <Add directory=".\include\loki" /> </Compiler> </Target> <Target title="Release_Cygwin"> - <Option output="./lib/Cygwin/Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\Cygwin\Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Release_Cygwin/" /> + <Option object_output="obj\Release_Cygwin\" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory="./include/loki" /> - <Add directory="./include" /> + <Add directory=".\include\loki" /> + <Add directory=".\include" /> </Compiler> </Target> </Build> - <Unit filename="include/loki/AbstractFactory.h" /> - <Unit filename="include/loki/Allocator.h" /> - <Unit filename="include/loki/AssocVector.h" /> - <Unit filename="include/loki/CachedFactory.h" /> - <Unit filename="include/loki/CheckReturn.h" /> - <Unit filename="include/loki/Checker.h" /> - <Unit filename="include/loki/ConstPolicy.h" /> - <Unit filename="include/loki/DataGenerators.h" /> - <Unit filename="include/loki/EmptyType.h" /> - <Unit filename="include/loki/Factory.h" /> - <Unit filename="include/loki/Function.h" /> - <Unit filename="include/loki/Functor.h" /> - <Unit filename="include/loki/HierarchyGenerators.h" /> - <Unit filename="include/loki/Key.h" /> - <Unit filename="include/loki/LevelMutex.h" /> - <Unit filename="include/loki/LockingPtr.h" /> - <Unit filename="include/loki/LokiExport.h" /> - <Unit filename="include/loki/LokiTypeInfo.h" /> - <Unit filename="include/loki/MultiMethods.h" /> - <Unit filename="include/loki/NullType.h" /> - <Unit filename="include/loki/OrderedStatic.h" /> - <Unit filename="include/loki/Pimpl.h" /> - <Unit filename="include/loki/RefToValue.h" /> - <Unit filename="include/loki/Register.h" /> - <Unit filename="include/loki/SPCachedFactory.h" /> - <Unit filename="include/loki/SafeBits.h" /> - <Unit filename="include/loki/SafeFormat.h" /> - <Unit filename="include/loki/ScopeGuard.h" /> - <Unit filename="include/loki/Sequence.h" /> - <Unit filename="include/loki/Singleton.h" /> - <Unit filename="include/loki/SmallObj.h" /> - <Unit filename="include/loki/SmartPtr.h" /> - <Unit filename="include/loki/StrongPtr.h" /> - <Unit filename="include/loki/ThreadLocal.h" /> - <Unit filename="include/loki/Threads.h" /> - <Unit filename="include/loki/Tuple.h" /> - <Unit filename="include/loki/TypeManip.h" /> - <Unit filename="include/loki/TypeTraits.h" /> - <Unit filename="include/loki/Typelist.h" /> - <Unit filename="include/loki/TypelistMacros.h" /> - <Unit filename="include/loki/Visitor.h" /> - <Unit filename="include/loki/flex/allocatorstringstorage.h" /> - <Unit filename="include/loki/flex/cowstringopt.h" /> - <Unit filename="include/loki/flex/flex_string.h" /> - <Unit filename="include/loki/flex/flex_string_details.h" /> - <Unit filename="include/loki/flex/flex_string_shell.h" /> - <Unit filename="include/loki/flex/simplestringstorage.h" /> - <Unit filename="include/loki/flex/smallstringopt.h" /> - <Unit filename="include/loki/flex/vectorstringstorage.h" /> - <Unit filename="include/loki/static_check.h" /> - <Unit filename="include/loki/yasli/platform.h" /> - <Unit filename="include/loki/yasli/random.h" /> - <Unit filename="include/loki/yasli/yasli_fill_iterator.h" /> - <Unit filename="include/loki/yasli/yasli_memory.h" /> - <Unit filename="include/loki/yasli/yasli_protocols.h" /> - <Unit filename="include/loki/yasli/yasli_traits.h" /> - <Unit filename="include/loki/yasli/yasli_vector.h" /> - <Unit filename="src/LevelMutex.cpp" /> - <Unit filename="src/OrderedStatic.cpp" /> - <Unit filename="src/SafeFormat.cpp" /> - <Unit filename="src/Singleton.cpp" /> - <Unit filename="src/SmallObj.cpp" /> - <Unit filename="src/SmartPtr.cpp" /> - <Unit filename="src/StrongPtr.cpp" /> + <Unit filename="include\loki\AbstractFactory.h" /> + <Unit filename="include\loki\Allocator.h" /> + <Unit filename="include\loki\AssocVector.h" /> + <Unit filename="include\loki\CachedFactory.h" /> + <Unit filename="include\loki\CheckReturn.h" /> + <Unit filename="include\loki\Checker.h" /> + <Unit filename="include\loki\ConstPolicy.h" /> + <Unit filename="include\loki\DataGenerators.h" /> + <Unit filename="include\loki\EmptyType.h" /> + <Unit filename="include\loki\Factory.h" /> + <Unit filename="include\loki\Function.h" /> + <Unit filename="include\loki\Functor.h" /> + <Unit filename="include\loki\HierarchyGenerators.h" /> + <Unit filename="include\loki\Key.h" /> + <Unit filename="include\loki\LevelMutex.h" /> + <Unit filename="include\loki\LockingPtr.h" /> + <Unit filename="include\loki\LokiExport.h" /> + <Unit filename="include\loki\LokiTypeInfo.h" /> + <Unit filename="include\loki\MultiMethods.h" /> + <Unit filename="include\loki\NullType.h" /> + <Unit filename="include\loki\OrderedStatic.h" /> + <Unit filename="include\loki\Pimpl.h" /> + <Unit filename="include\loki\RefToValue.h" /> + <Unit filename="include\loki\Register.h" /> + <Unit filename="include\loki\SPCachedFactory.h" /> + <Unit filename="include\loki\SafeBits.h" /> + <Unit filename="include\loki\SafeFormat.h" /> + <Unit filename="include\loki\ScopeGuard.h" /> + <Unit filename="include\loki\Sequence.h" /> + <Unit filename="include\loki\Singleton.h" /> + <Unit filename="include\loki\SmallObj.h" /> + <Unit filename="include\loki\SmartAssert.hpp" /> + <Unit filename="include\loki\SmartPtr.h" /> + <Unit filename="include\loki\StrongPtr.h" /> + <Unit filename="include\loki\ThreadLocal.h" /> + <Unit filename="include\loki\Threads.h" /> + <Unit filename="include\loki\Tuple.h" /> + <Unit filename="include\loki\TypeManip.h" /> + <Unit filename="include\loki\TypeTraits.h" /> + <Unit filename="include\loki\Typelist.h" /> + <Unit filename="include\loki\TypelistMacros.h" /> + <Unit filename="include\loki\Visitor.h" /> + <Unit filename="include\loki\flex\allocatorstringstorage.h" /> + <Unit filename="include\loki\flex\cowstringopt.h" /> + <Unit filename="include\loki\flex\flex_string.h" /> + <Unit filename="include\loki\flex\flex_string_details.h" /> + <Unit filename="include\loki\flex\flex_string_shell.h" /> + <Unit filename="include\loki\flex\simplestringstorage.h" /> + <Unit filename="include\loki\flex\smallstringopt.h" /> + <Unit filename="include\loki\flex\vectorstringstorage.h" /> + <Unit filename="include\loki\static_check.h" /> + <Unit filename="include\loki\yasli\platform.h" /> + <Unit filename="include\loki\yasli\random.h" /> + <Unit filename="include\loki\yasli\yasli_fill_iterator.h" /> + <Unit filename="include\loki\yasli\yasli_memory.h" /> + <Unit filename="include\loki\yasli\yasli_protocols.h" /> + <Unit filename="include\loki\yasli\yasli_traits.h" /> + <Unit filename="include\loki\yasli\yasli_vector.h" /> + <Unit filename="src\LevelMutex.cpp" /> + <Unit filename="src\OrderedStatic.cpp" /> + <Unit filename="src\SafeFormat.cpp" /> + <Unit filename="src\Singleton.cpp" /> + <Unit filename="src\SmallObj.cpp" /> + <Unit filename="src\SmartAssert.cpp" /> + <Unit filename="src\SmartPtr.cpp" /> + <Unit filename="src\StrongPtr.cpp" /> <Extensions> <code_completion /> <envvars /> Modified: trunk/Loki.sln =================================================================== --- trunk/Loki.sln 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.sln 2013-06-19 02:23:00 UTC (rev 1184) @@ -1,7 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Loki", "src\library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Factory", "test\Factory\Factory.vcxproj", "{925D5863-2F77-41B7-96F1-CC814762C40F}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} @@ -23,6 +21,9 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScopeGuard", "test\ScopeGuard\ScopeGuard.vcxproj", "{D5E7BAC2-A961-4ECC-ADA4-82D7510952BA}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Singleton", "test\Singleton\Singleton.vcxproj", "{9F489E5D-9F29-4235-A9D4-79B5BA4EC48D}" ProjectSection(ProjectDependencies) = postProject @@ -30,8 +31,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Visitor", "test\Visitor\Visitor.vcxproj", "{0A696379-10A2-43FB-A26C-B42456FCF657}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flex_string", "test\flex_string\flex_string.vcxproj", "{2022B9AD-34CA-4FDA-80C2-42805FABE65B}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmallObjCompare", "test\SmallObj\SmallObjCompare.vcxproj", "{0A98B714-818C-4DD3-A07C-BDD16399F362}" ProjectSection(ProjectDependencies) = postProject @@ -44,8 +51,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeletableSingleton", "test\DeletableSingleton\DeletableSingleton.vcxproj", "{B87B3522-7DAA-400D-A47D-A74B9B8B3552}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DefaultAlloc", "test\SmallObj\DefaultAlloc.vcxproj", "{D490B134-B794-42CF-8AF8-9FDA524B9D3B}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmartPtr", "test\SmartPtr\SmartPtr.vcxproj", "{D7AB4FEF-E7AF-443D-93A5-37F323F2042D}" ProjectSection(ProjectDependencies) = postProject @@ -58,6 +71,9 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pimpl", "test\Pimpl\Pimpl.vcxproj", "{21D2B291-80F4-476C-A643-B8A7034DF95F}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LockingPtr", "test\LockingPtr\LockingPtr.vcxproj", "{25766C3F-C0D8-429F-A212-5FA3537B3E1C}" ProjectSection(ProjectDependencies) = postProject @@ -65,10 +81,19 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Function", "test\Function\Function.vcxproj", "{2DE18D06-0F3A-4C6D-AF2B-40E074B3C3DC}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CachedFactory", "test\CachedFactory\CachedFactory.vcxproj", "{8D186AB4-E544-42D6-B192-1AE2C946875E}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CheckReturn", "test\CheckReturn\CheckReturn.vcxproj", "{C0826A05-9143-4545-B5DE-811C188CB54E}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Checker", "test\Checker\Checker.vcxproj", "{B1C04D81-E666-466A-A394-A3E74C830692}" ProjectSection(ProjectDependencies) = postProject @@ -81,8 +106,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SafeBits", "test\SafeBits\SafeBits.vcxproj", "{ECD7ED50-B99D-44BE-BA38-E17D6110C3E5}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssocVector", "test\AssocVector\AssocVector.vcxproj", "{0605A820-D075-48AC-ABB6-D3FF05D5CD1F}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadLocal", "test\ThreadLocal\ThreadLocal.vcxproj", "{27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}" EndProject @@ -91,23 +122,24 @@ {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtomicThread", "test\AtomicThread\AtomicThread.vcxproj", "{BF3C905E-512C-4E64-B737-A6C5B3A18C7E}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Register", "test\Register\Register.vcxproj", "{873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "src\Library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmartAssert", "test\SmartAssert\SmartAssert.vcxproj", "{DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.Build.0 = Debug|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.ActiveCfg = Release|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.Build.0 = Release|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Debug|Win32.ActiveCfg = Debug|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Debug|Win32.Build.0 = Debug|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Release|Win32.ActiveCfg = Release|Win32 @@ -208,14 +240,18 @@ {22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.Build.0 = Debug|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.ActiveCfg = Release|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.Build.0 = Release|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Debug|Win32.ActiveCfg = Debug|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Debug|Win32.Build.0 = Debug|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Release|Win32.ActiveCfg = Release|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Release|Win32.Build.0 = Release|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Debug|Win32.ActiveCfg = Debug|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Debug|Win32.Build.0 = Debug|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Release|Win32.ActiveCfg = Release|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Release|Win32.Build.0 = Release|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.Build.0 = Debug|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.ActiveCfg = Release|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.Build.0 = Release|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Debug|Win32.ActiveCfg = Debug|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Debug|Win32.Build.0 = Debug|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.ActiveCfg = Release|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modified: trunk/Loki.workspace =================================================================== --- trunk/Loki.workspace 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.workspace 2013-06-19 02:23:00 UTC (rev 1184) @@ -14,7 +14,7 @@ <Project filename="test/Factory/Factory.cbp" /> <Project filename="test/flex_string/flex_string.cbp" /> <Project filename="test/Function/Function.cbp" /> - <Project filename="test/LevelMutex/LevelMutex.cbp" active="1"> + <Project filename="test/LevelMutex/LevelMutex.cbp"> <Depends filename="Loki.cbp" /> </Project> <Project filename="test/Lockable/Lockable.cbp"> @@ -50,5 +50,8 @@ <Project filename="test/SmallObj/SmallObjSingleton.cbp"> <Depends filename="Loki.cbp" /> </Project> + <Project filename="test/SmartAssert/SmartAssert.cbp" active="1"> + <Depends filename="Loki.cbp" /> + </Project> </Workspace> </CodeBlocks_workspace_file> Added: trunk/include/loki/Concatenate.h =================================================================== --- trunk/include/loki/Concatenate.h (rev 0) +++ trunk/include/loki/Concatenate.h 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// 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. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_MACRO_CONCATENATE_INC_ +#define LOKI_MACRO_CONCATENATE_INC_ + +// $Id$ + +/** @note This header file provides a common definition of macros used to + concatenate names or numbers together into a single name or number. + */ + +#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 +#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) + + +#endif Property changes on: trunk/include/loki/Concatenate.h ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Modified: trunk/include/loki/ScopeGuard.h =================================================================== --- trunk/include/loki/ScopeGuard.h 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/include/loki/ScopeGuard.h 2013-06-19 02:23:00 UTC (rev 1184) @@ -31,7 +31,9 @@ #include <exception> // needed for calls to uncaught_exception. #include <loki/RefToValue.h> +#include <loki/Concatenate.h> + /// \defgroup ExceptionGroup Exception-safe code namespace Loki @@ -699,8 +701,6 @@ } // namespace Loki -#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 -#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__) #define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard Added: trunk/include/loki/SmartAssert.hpp =================================================================== --- trunk/include/loki/SmartAssert.hpp (rev 0) +++ trunk/include/loki/SmartAssert.hpp 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,666 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// 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. +//////////////////////////////////////////////////////////////////////////////// + + +#ifndef LOKI_SMART_ASSERT_HPP_INCLUDED +#define LOKI_SMART_ASSERT_HPP_INCLUDED + + +#include <loki/Concatenate.h> + +#if defined ( DEBUG ) || defined( DEBUG_ ) || defined( _DEBUG ) + #define LOKI_SMART_ASSERT_DEBUG +#endif + +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable : 4514 ) + #pragma warning( disable : 4711 ) +#endif + +#if !defined( nullptr ) + #define LOKI_DEFINED_NULLPTR + #define nullptr 0 +#endif + + +namespace Loki +{ + +// --------------------------------------------------------------------- + +/** + @par SmartAssert Versus Dumb Assertions + Loki's SmartAssert provides features traditional assertions don't. + - Add a meaningful message to each assertion. + - Output values of variables when assertions fail. + - Different severity levels per assertion. + - Allows program to do something besides abort when assertions fail. + - Can ask user how to respond to assertions instead of just failing. + - Customizable output. + - Customizable way to ask user for response. + - Customizable way to start debugger. + - Allows program to do cleanup before dying. + + @par How to Use SmartAssert in 5 Minutes + The simplest way to use Loki's SmartAssert is to follow these steps. This is + the simplest way to use SmartAssert, and it gives you the same (or similar) + behaviors as assert. + - Add this line to your file: #include <loki/SmartAssert.hpp> + - Replace "assert( condition );" with "LOKI_SMART_ASSERT( condition );" + - Make sure you define one of these macros: DEBUG, _DEBUG, or DEBUG_. + - Compile and run your program. + + @par Adding Messages to your Assertions. + SmartAssert can output simple C-style strings as messages when an assertion + fails. Each assertion may have only one message. If you add more than one, + then only the right-most message is sent to output. To add a simple message + to your assertions, use the .Msg() function. + @code + LOKI_SMART_ASSERT( cond ).Msg( "Something is rotten in the state of Denmark." ); + @endcode + + @par Adding Variables to Your Assertions. + You can make SmartAssert output the values of variables by adding each + variable within a pair of parantheses. It will output them in the same order + they were added. You may chain as many variables to the assertion, but you + may only place fundamental types in the assertion. You can put them in any + order, but SmartAssert will store and output them in the reverse order in + which you add them. (i.e. Leftmost variables get outputted last, and + rightmost ones get outputted first.) Storing them in reverse order makes an + efficiency gain of O(n) over O(n*n). + @code + LOKI_SMART_ASSERT( cond )( a )( b ); + LOKI_SMART_ASSERT( cond )( a )( e )( c )( b )( d ); + @endcode + + SmartAssert won't know the purpose of those variables; only their type and + value. You can make SmartAssert output the names of the variables by using + the "stringify" preprocessor operator. This causes SmartAssert to create a + separate storage for the name and the variable itself. + @code + LOKI_SMART_ASSERT( cond )( a )( "a" )( b )( "b" ); + LOKI_SMART_ASSERT( cond )( a )( "a" )( e )( "e" )( b )( "b" ); + @endcode + + @par Setting the Severity Level + Assertions treat all error conditions as an excuse to commit suicide. That + one-size-fits-all solution seems overly drastic for minor errors. At least + SmartAssert gives the developer more detailed output to help understand why + the program died. + + SmartAssert provides multiple severity levels so developers have more options + besides seeing their programs die. The basic options are to start a debugger, + ignore the assertion that time, ignore it as long as the program runs, or + stop the program. The four severity levels and their effects are: + - Info: Just output the assertion info and continue on. + - Warn: Ask user to either ignore now, ignore always, or start debugger. + - Error: Same as above, but also give user option to abort program. + - Fatal: Program always ends when assertion fails and never asks user. + + SmartAssert's default severity level is Fatal so you can use it as a drop-in + replacement for assert and still get the same behavior. + + Here are some example calls to set the severity level. As you can see, the + calls may occur in any order within the assertion. + @code + LOKI_SMART_ASSERT( cond )( a )( b ).Info(); + LOKI_SMART_ASSERT( cond ).Warn()( a )( b ); + LOKI_SMART_ASSERT( cond )( a ).Error().( b ); + LOKI_SMART_ASSERT( cond ).Fatal().Msg( "Goodbye cruel world!" ); + LOKI_SMART_ASSERT( cond )( d ); // No severity level implies Fatal! + @endcode + + You could specify more than one severity level, but only the rightmost call + matters. In this example, Info() is further to the right so it overrides the + Fatal() call. + @code + LOKI_SMART_ASSERT( cond ).Fatal()( a )( b ).Info(); + @endcode + + @par User Intervention. + Since SmartAssert's default behaviors mimic assert, it normally doesn't ask + the user how to respond to an assertion failure. SmartAssert asks the user + only if the developer puts a call to operator() at the end of the assertion. + There is no need to ask the user to intervene if the severity level is Info. + If you write a policy class to either ask the user or call the debugger, you + should always add the call to operator(). + @code + LOKI_SMART_ASSERT( cond ).Warn()( a )(); // Asks user to intervene. + LOKI_SMART_ASSERT( cond ).Warn()( a ); // Does not ask user. + @endcode + + @par Write Your Own Policy. + Many parts of Loki were implemented using policy-based software design, and + SmartAssert follows that tradition. SmartAssert has a default policy that + mimics the behaviors of assert. If you want to make your own policy class, + write that class to have the same function signatures as + CommandLineAssertPolicy, and use the LOKI_SMART_ASSERT_POLICIED macro instead + of LOKI_SMART_ASSERT. + + @par Potential Policies + - To call a special debugger rather than the default one. + - To send output to a log file instead of to cout. + - To create a popup dialog box to ask the user. + - To attempt last moment cleanup before the program dies. + + @code + class MyPolicy + { + static void Output( const SmartAssertBase * asserter ); + static void Debugger( const SmartAssertBase * asserter ); + static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); + static void AbortNow( const SmartAssertBase * asserter ); + }; + LOKI_SMART_ASSERT_POLICIED( cond, MyPolicy ); + @endcode + + @par Thread Safety. + Each SmartAssert object is declared locally within a function, so it is only + accessible by the thread executing it. However, each SmartAssert makes its + own static boolean flag for whether to ignore its future failures. That + boolean flag is not thread_local, so telling SmartAssert to ignore it each + time applies to all threads. SmartAssert relies on a policy class, so it is + only as thread-safe as the functions in its policy class. + + @par Exception Safety. + SmartAssert wraps calls to the policy class within try-catch blocks. If an + exception occurs for Info or Warning level conditions, SmartAssert stops + processing the assertion and allows the calling function to continue. If an + exception occurs when processing an Error or Fatal assertion, SmartAssert + will abort immediately. + + @par Memory Usage. + SmartAssert does not allocate any memory or other resources, but functions + within policy classes might. + + @par Run-Time Efficiency. + No function call or operation within SmartAssert takes more than O(n) steps, + where n is the number of variables passed into SmartAssert. Most actions + complete in constant time. Functions in policy classes may not have the same + low run-time efficiency. +*/ + +// --------------------------------------------------------------------- + +/** @class AssertInfo Stores extra info user wants to pass into assertion. + This class has one constructor for each primitive data type so developers + can pass any primitive variable into the assert. + */ +class AssertInfo +{ +public: + + /** @enum DataTypeTag One tag for each primitive data type, plus a + few for pointers to char data types. + */ + enum DataTypeTag + { + Unknown = 0, + Boolean, + JustChar, + SignedChar, + UnsignedChar, + SignedShort, + UnsignedShort, + JustInt, + SignedInt, + UnsignedInt, + Long, + UnsignedLong, + LongInt, + UnsignedLongInt, + CharPtr, + SignedCharPtr, + UnsignedCharPtr, + VoidPtr, + Float, + Double, + LongDouble, + }; + + static const char * GetName( DataTypeTag tag ); + + /// @union DataValue Can be configured as any primitive data type. + union DataValue + { + bool m_bool; + char m_char; + signed char m_s_char; + unsigned char m_u_char; + signed short int m_s_short; + unsigned short int m_u_short; + int m_int; + unsigned int m_u_int; + long m_long; + unsigned long m_u_long; + signed long long int m_s_long_int; + unsigned long long int m_u_long_int; + const char * m_p_char; + const signed char * m_p_s_char; + const unsigned char * m_p_u_char; + const void * m_p_v; + float m_float; + double m_double; + long double m_l_double; + + DataValue() : m_bool( true ) {} + DataValue( const bool v ) : m_bool( v ) {} + DataValue( const char v ) : m_char( v ) {} + DataValue( const signed char v ) : m_s_char( v ) {} + DataValue( const unsigned char v ) : m_u_char( v ) {} + DataValue( const signed short int v ) : m_s_short( v ) {} + DataValue( const unsigned short int v ) : m_u_short( v ) {} + DataValue( const int v ) : m_int( v ) {} + DataValue( const unsigned int v ) : m_u_int( v ) {} + DataValue( const long v ) : m_long( v ) {} + DataValue( const unsigned long v ) : m_u_long( v ) {} + DataValue( const long long int v ) : m_s_long_int( v ) {} + DataValue( const unsigned long long int v ) : m_u_long_int( v ) {} + DataValue( const char * v ) : m_p_char( v ) {} + DataValue( const signed char * v ) : m_p_s_char( v ) {} + DataValue( const unsigned char * v ) : m_p_u_char( v ) {} + DataValue( const void * v ) : m_p_v( v ) {} + DataValue( const float v ) : m_float( v ) {} + DataValue( const double v ) : m_double( v ) {} + DataValue( const long double v ) : m_l_double( v ) {} + + void Output( DataTypeTag type ) const; + }; + + AssertInfo() : m_type( Unknown ), m_value(), m_next( nullptr ) {} + AssertInfo( bool v ) : m_type( Boolean ), m_value( v ), m_next( nullptr ) {} + AssertInfo( char v ) : m_type( JustChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed char v ) : m_type( SignedChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned char v ) : m_type( UnsignedChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed short v ) : m_type( SignedShort ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned short v ) : m_type( UnsignedShort ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed int v ) : m_type( SignedInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned int v ) : m_type( UnsignedInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long v ) : m_type( Long ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned long v ) : m_type( UnsignedLong ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long long int v ) : m_type( LongInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned long long int v ) : m_type( UnsignedLongInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const char * v ) : m_type( CharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const signed char * v ) : m_type( SignedCharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const unsigned char * v ) : m_type( UnsignedCharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const void * v ) : m_type( VoidPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( float v ) : m_type( Float ), m_value( v ), m_next( nullptr ) {} + AssertInfo( double v ) : m_type( Double ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long double v ) : m_type( LongDouble ), m_value( v ), m_next( nullptr ) {} + + /// Function provides default output action. + void Output() const; + + DataTypeTag m_type; ///< What type of data this stores. + DataValue m_value; ///< Value of that data. + mutable const AssertInfo * m_next; ///< Pointer to next piece of info, if any. +}; + +// --------------------------------------------------------------------- + +/** @class AssertContext Stores info about file, line, and function + where assertion occurred. Only two or three of these per SmartAssert. + + @note This class is optimized for storing info about the assertion's + location, not for storing general values. Use AssertInfo for storing + values of arbitary primitive types. + */ +class AssertContext +{ +public: + + /// Constructs context for source code line within file. + AssertContext( const char * description, unsigned int line ); + + /// Constructs context for source code filename or function name. + AssertContext( const char * description, const char * value ); + + /// Function provides default output action. + void Output() const; + + unsigned int m_line; ///< Line number within file. + const char * m_value; ///< Pointer to either filename or function name. + const char * m_description; ///< C-style string for describing piece of context. + mutable const AssertContext * m_next; ///< Pointer to next piece of context, if any. +}; + +// --------------------------------------------------------------------- + +class SmartAssertBase +{ +public: + + enum SeverityLevel + { + Info_, ///< Just warn user and do nothing else. (same as Warning and Ignore-Each-Time) + Warn_, ///< Give user options: (Ignore Once, Ignore Always, Debug) + Error_, ///< Give user options: (Ignore Once, Ignore Always, Debug, Abort) + Fatal_ ///< Always abort on failure. User gets no option to choose otherwise. + }; + + /// @enum Possible replies by the user when asked what to do about assertion. + enum UserResponse + { + /// Program continues as if assertion never happened, and asks + /// user what to do when assertion occurs again. + IgnoreThisTime = 'I', + /// Program continues executing, and never checks assertion for + /// the rest of the program's execution. If the program ends and + /// restarts, SmartAssert will check it again. + IgnoreEachTime = 'E', + /// Start the debugger at the place where the assertion failed. + DebugNow = 'D', + /// End the program now. + AbortProgram = 'A' + }; + + /// Gets one word description of severity level. + static const char * GetName( SeverityLevel level ); + + /// These three C-style strings contain descriptions used for assertion contexts. + static const char * const FileDesc; + static const char * const LineDesc; + static const char * const FunctionDesc; + + mutable const AssertContext * m_context; /// Linked-list of contexts of where assertion occurred. + mutable const AssertInfo * m_info; ///< Linked-list of values provided for output purposes. + SeverityLevel m_level; ///< How bad is this assertion? + bool * m_ignore; ///< Pointer to ignore-always flag. + const char * m_expression; ///< Pointer to C-style string of failed assertion expression. + const char * m_message; ///< Simple message made by developer. + bool m_handled; ///< True if this assertion was handled before destructor. + +protected: + + /// Default constructor is used for release builds. It ignores assertions. + SmartAssertBase(); + + /** This constructor gets used in debug builds. + @param ignore Pointer to boolean flag to ignore this assertion each time. + @param expression C-style string showing failed assertion. + */ + SmartAssertBase( bool * ignore, const char * expression ); + + /// Destructor handles assertion only when if not handled earlier. + virtual ~SmartAssertBase(); + + /// Called by derived class to add context information. + SmartAssertBase & AddContext( const AssertContext & info ); + + /// Called by derived class to add values used to display info about assertion. + SmartAssertBase & AddInfo( const AssertInfo & info ); + + /// Called to handle assertion failure. + void HandleFailure(); + + /// Default implementation of code to output information about assertion. + virtual void CallOutput() const; + + /// Default implementation of code to call debugger. + virtual void CallDebugger() const; + + /// Default implementation of code to ask user what to do. + virtual UserResponse AskUser() const; + + /// Default implementation of code to abort program. + virtual void AbortNow() const; + + /// Ignore-always flag used by assertions created in release builds. + static bool s_alwaysIgnore; +}; + +// --------------------------------------------------------------------- + +/** @class CommandLineAssertPolicy Default policy for command line programs. + Developers can implement their own policies to handle assertions by making a + class with the same function signatures as this class. If you write your own + policy class, you should also use the LOKI_SMART_ASSERT_POLICIED macro, and + not the LOKI_SMART_ASSERT macro. +*/ +class CommandLineAssertPolicy +{ +public: + + /// Displays information about assertion to the user. + static void Output( const SmartAssertBase * asserter ); + + /// Asks user how to handle assertion. + static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); + + /// Calls debugger. + static void Debugger( const SmartAssertBase * asserter ); + + /// This call should end the program. + static void AbortNow( const SmartAssertBase * asserter ); + +}; + +// --------------------------------------------------------------------- + +/** @class class SmartAssert + */ +template< class AssertPolicy > +class SmartAssert : public SmartAssertBase +{ +public: + + /// Default constructor used for when assertion passes. Should get optimized away. + SmartAssert() : SmartAssertBase() {} + + /// Constructor used when assertion fails. + SmartAssert( bool * ignore, const char * expression ) + : SmartAssertBase( ignore, expression ) {} + + /// Destructor is trivial. + virtual ~SmartAssert() {} + + /// Provides simple hard-coded C-style string message for output. + SmartAssert & Msg( const char * message ) { m_message = message; return *this; } + + SmartAssert & Info() { m_level = SmartAssertBase::Info_; return *this; } + SmartAssert & Warn() { m_level = SmartAssertBase::Warn_; return *this; } + SmartAssert & Error() { m_level = SmartAssertBase::Error_; return *this; } + SmartAssert & Fatal() { m_level = SmartAssertBase::Fatal_; return *this; } + + /// Called to do non-default actions when assertion fails. + void operator ()() { HandleFailure(); } + + /// Adds one piece of information to assertion, generally a variable or result of function call. + SmartAssert & operator ()( const AssertInfo & info ) + { + return static_cast< SmartAssert & >( AddInfo( info ) ); + } + + /// Called to add one piece of context to assertion, such as filename, line, or function name. + SmartAssert & Add( const AssertContext & info ) + { + return static_cast< SmartAssert & >( AddContext( info ) ); + } + +private: + + virtual void CallOutput() const + { + AssertPolicy::Output( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual void CallDebugger() const + { + AssertPolicy::Debugger( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual SmartAssertBase::UserResponse AskUser() const + { + return AssertPolicy::AskUser( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual void AbortNow() const + { + AssertPolicy::AbortNow( dynamic_cast< const SmartAssertBase * >( this ) ); + } + +}; + +// --------------------------------------------------------------------- + +} // namespace Loki + + +/// These lines let Loki put filename and line into AssertContext. +// note: using 'const char LOKI_SMART_ASSERT_FILE[] = __FILE__' +// does not work, since __FILE__ = "SmartAssert.hpp" +#define LOKI_SMART_ASSERT_FILE __FILE__ +#define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __LINE__ + + +/** These lines determine if Loki can get the function name into AssertContext. + They also declare the macro used for creating unique names for SmartAssert + classes and variables. + */ +#define LOKI_SMART_ASSERT_FUNCTION_EXISTS + +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) + # define LOKI_SMART_ASSERT_FUNCTION __PRETTY_FUNCTION__ + # undef LOKI_USE_NUMBER_FOR_UNIQUE_NAME + # define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __COUNTER__ + +#elif defined(__FUNCSIG__) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCSIG__ + +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) + # define LOKI_SMART_ASSERT_FUNCTION __FUNC__ + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + # define LOKI_SMART_ASSERT_FUNCTION __func__ + +#elif (defined __MSC_VER) && (__MSC_VER >= 1300) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCDNAME__ + # undef LOKI_USE_NUMBER_FOR_UNIQUE_NAME + # define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __COUNTER__ + +#elif defined(__IBMCPP__) && (__IBMCPP__ <= 500) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCTION__ + +#elif (defined __HP_aCC) && (__HP_aCC <= 33300) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCTION__ + +#else + # undef LOKI_SMART_ASSERT_FUNCTION_EXISTS +#endif + +#define LOKI_MAKE_UNIQUE_NAME( str ) LOKI_CONCATENATE( str, LOKI_USE_NUMBER_FOR_UNIQUE_NAME ) +#define LOKI_SMART_ASSERT_IGNORE_NAME LOKI_MAKE_UNIQUE_NAME( smartAssert_ignore_ ) +#define LOKI_SMART_ASSERT_CLASS_NAME LOKI_MAKE_UNIQUE_NAME( SmartAssert_ ) +#define LOKI_SMART_ASSERT_HIDDEN_CLASS LOKI_SMART_ASSERT_CLASS( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME ) + + +// --------------------------------------------------------------------- + +// @note This checks if LOKI_SMART_ASSERT_CONTEXT was defined already in +// case developers made their own context-creating macro. If you make +// your own context chain, follow the example here and expect SmartAssert +// to display the context information in the reverse order of how they +// are added here. (e.g. - The contexts are added in function-line-file +// order, but shown in file-line-function order.) +#ifndef LOKI_SMART_ASSERT_CONTEXT + + #ifdef LOKI_SMART_ASSERT_FUNCTION_EXISTS + #define LOKI_SMART_ASSERT_CONTEXT \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FunctionDesc, LOKI_SMART_ASSERT_FUNCTION ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::LineDesc, __LINE__ ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FileDesc, LOKI_SMART_ASSERT_FILE ) ) + #else + #define LOKI_SMART_ASSERT_CONTEXT \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::LineDesc, __LINE__ ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FileDesc, LOKI_SMART_ASSERT_FILE ) ) + #endif + +#endif // LOKI_SMART_ASSERT_CONTEXT + + +// --------------------------------------------------------------------- + +#define LOKI_MAKE_SMART_ASSERT( class_name, ignore_var_name, expr ) \ + static bool ignore_var_name = false; \ + class class_name : public ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > \ + { public: \ + typedef ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > BaseClass; \ + class_name( bool * ignore, const char * expression ) \ + : BaseClass( ignore, expression ) {} \ + virtual ~class_name() {} \ + }; \ + if ( ignore_var_name || ( expr ) ) ; else \ + class_name( &ignore_var_name, #expr ).LOKI_SMART_ASSERT_CONTEXT + + +#ifdef LOKI_SMART_ASSERT_DEBUG + #define LOKI_SMART_ASSERT( expr ) \ + LOKI_MAKE_SMART_ASSERT( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME, (expr) ) + +#else + #define LOKI_SMART_ASSERT( expr ) \ + if ( true ) ; else \ + ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy >() + // Do nothing. Compiler should optimize away the else branch. +#endif + + +// --------------------------------------------------------------------- + +#define LOKI_MAKE_SMART_ASSERT_POLICIED( class_name, ignore_var_name, expr, policy ) \ + static bool ignore_var_name = false; \ + class class_name : public ::Loki::SmartAssert< policy > \ + { public: \ + typedef ::Loki::SmartAssert< policy > BaseClass; \ + class_name( bool * ignore, const char * expression ) \ + : BaseClass( ignore, expression ) {} \ + virtual ~class_name() {} \ + }; \ + if ( ignore_var_name || ( expr ) ) ; else \ + class_name( &ignore_var_name, #expr ).LOKI_SMART_ASSERT_CONTEXT + + +#ifdef LOKI_SMART_ASSERT_DEBUG + #define LOKI_SMART_ASSERT_POLICIED( expr, policy ) \ + LOKI_MAKE_SMART_ASSERT_POLICIED( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME, (expr), policy ) + +#else + #define LOKI_SMART_ASSERT_POLICIED( expr, policy ) \ + if ( true ) ; else \ + ::Loki::SmartAssert< policy >() + // Do nothing. Compiler should optimize away the else branch. +#endif + +// --------------------------------------------------------------------- + +#if defined( LOKI_DEFINED_NULLPTR ) + #undef LOKI_DEFINED_NULLPTR + #undef nullptr +#endif + +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + +#endif // LOKI_SMART_ASSERT_HPP_INCLUDED Property changes on: trunk/include/loki/SmartAssert.hpp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/src/SmartAssert.cpp =================================================================== --- trunk/src/SmartAssert.cpp (rev 0) +++ trunk/src/SmartAssert.cpp 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,527 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// 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. +//////////////////////////////////////////////////////////////////////////////// + + +#include <loki/SmartAssert.hpp> + +#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 ) + #include <Windows.h> +#endif + +#include <iostream> + +#include <cassert> +#include <cstdlib> + +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable : 4365 ) + #pragma warning( disable : 4514 ) + #pragma warning( disable : 4710 ) + #pragma warning( disable : 4711 ) +#endif + +#if !defined( nullptr ) + #define nullptr 0 +#endif + + +using namespace ::std; + +namespace Loki +{ + +bool SmartAssertBase::s_alwaysIgnore = true; + +const char * const SmartAssertBase::FileDesc = "file"; +const char * const SmartAssertBase::LineDesc = "line"; +const char * const SmartAssertBase::FunctionDesc = "function"; + + +// --------------------------------------------------------------------- + +const char * AssertInfo::GetName( DataTypeTag tag ) +{ + switch ( tag ) + { + case Unknown: return "Unknown"; + case Boolean: return "boolean"; + case JustChar: return "char"; + case SignedChar: return "signed char"; + case UnsignedChar: return "char"; + case SignedShort: return "signed short"; + case UnsignedShort: return "unsigned short"; + case JustInt: return "int"; + case SignedInt: return "signed int"; + case UnsignedInt: return "unsigned int"; + case Long: return "long"; + case UnsignedLong: return "unsigned long"; + case LongInt: return "long int"; + case UnsignedLongInt: return "unsigned long int"; + case CharPtr: return "char *"; + case SignedCharPtr: return "signed char *"; + case UnsignedCharPtr: return "unsigned char *"; + case VoidPtr: return "void *"; + case Float: return "float"; + case Double: return "double"; + case LongDouble: return "long double"; + default: break; + } + return "undefined data type"; +} + +// --------------------------------------------------------------------- + +void AssertInfo::DataValue::Output( DataTypeTag theType ) const +{ + switch ( theType ) + { + case Unknown: + { + cout << "\t Error! Unknown data type! " << theType; + break; + } + case Boolean: + { + const char * message = m_bool ? "true" : "false"; + cout << message; + break; + } + case JustChar: + { + cout << m_char; + break; + } + case SignedChar: + { + cout << m_s_char; + break; + } + case UnsignedChar: + { + cout << m_u_char; + break; + } + case SignedShort: + { + cout << m_s_short; + break; + } + case UnsignedShort: + { + cout << m_u_short; + break; + } + case JustInt: + { + cout << m_int; + break; + } + case SignedInt: + { + cout << m_int; + break; + } + case UnsignedInt: + { + cout << m_u_int; + break; + } + case Long: + { + cout << m_long; + break; + } + case UnsignedLong: + { + cout << m_u_long; + break; + } + case LongInt: + { + cout << m_s_long_int; + break; + } + case UnsignedLongInt: + { + cout << m_u_long_int; + break; + } + case CharPtr: + { + cout << m_p_char; + break; + } + case SignedCharPtr: + { + cout << m_p_s_char; + break; + } + case UnsignedCharPtr: + { + cout << m_p_u_char; + break; + } + case VoidPtr: + { + cout << m_p_v; + break; + } + case Float: + { + cout << m_float; + break; + } + case Double: + { + cout << m_double; + break; + } + case LongDouble: + { + cout << m_l_double; + break; + } + default: + { + cout << "\t Error! Undefined data type! " << theType; + break; + } + } +} + +// --------------------------------------------------------------------- + +void AssertInfo::Output() const +{ + cout << "\t" << GetName( m_type ) << ": "; + m_value.Output( m_type ); + cout << endl; +} + +// --------------------------------------------------------------------- + +AssertContext::AssertContext( const char * description, unsigned int line ) + : m_line( line ) + , m_value( nullptr ) + , m_description( description ) + , m_next( nullptr ) +{ +} + +// --------------------------------------------------------------------- + +AssertContext::AssertContext( const char * description, const char * value ) + : m_line( 0 ) + , m_value( value ) + , m_description( description ) + , m_next( nullptr ) +{ +} + +// --------------------------------------------------------------------- + +void AssertContext::Output() const +{ + cout << m_description << ": "; + if ( m_value != nullptr ) + { + cout << m_value; + } + else + { + cout << m_line; + } +} + +// --------------------------------------------------------------------- + +const char * SmartAssertBase::GetName( SeverityLevel level ) +{ + switch ( level ) + { + case Info_: return "Info"; + case Warn_: return "Warning"; + case Error_: return "Error"; + case Fatal_: return "Fatal"; + } + return "unknown"; +} + +// --------------------------------------------------------------------- + +SmartAssertBase::SmartAssertBase() + : m_context( nullptr ) + , m_info( nullptr ) + , m_level( Warn_ ) + , m_ignore( &s_alwaysIgnore ) + , m_expression( nullptr ) + , m_message( nullptr ) + , m_handled( false ) +{ +} + +// --------------------------------------------------------------------- + +SmartAssertBase::SmartAssertBase( bool * ignore, const char * expression ) + : m_context( nullptr ) + , m_info( nullptr ) + , m_level( Fatal_ ) ///< @note Default level is fatal to match behavior of assert. + , m_ignore( ignore ) + , m_expression( expression ) + , m_message( nullptr ) + , m_handled( false ) +{ +} + +// --------------------------------------------------------------------- + +SmartAssertBase::~SmartAssertBase() +{ + if ( m_handled ) + { + return; + } + + try + { + CallOutput(); + if ( ( Fatal_ == m_level ) || ( Error_ == m_level ) ) + { + AbortNow(); + } + } + catch ( ... ) + { + if ( ( Fatal_ == m_level ) || ( Error_ == m_level ) ) + { + // In other situations, I might allow a destructor to do nothing + // when an exception occurs, but since this exception occurred + // while processing a failed assertion, it is probably not safe + // to ignore the exception. Just end the program abruptly. + ::std::abort(); + } + } +} + +// --------------------------------------------------------------------- + +SmartAssertBase & SmartAssertBase::AddContext( const AssertContext & context ) +{ + // Contexts are always added to the head of the linked-list since that + // is cheaper than traversing the list every time, but the list is in + // reverse order from how the entries are declared. + assert( m_context != &context ); + context.m_next = m_context; + m_context = &context; + return *this; +} + +// --------------------------------------------------------------------- + +SmartAssertBase & SmartAssertBase::AddInfo( const AssertInfo & info ) +{ + // AssertInfo's are always added to the head of the linked-list since + // that is cheaper than traversing the list every time, but the list + // is in reverse order from how the entries are declared. + assert( m_info != &info ); + info.m_next = m_info; + m_info = &info; + return *this; +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::CallOutput() const +{ + CommandLineAssertPolicy::Output( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::CallDebugger() const +{ + CommandLineAssertPolicy::Debugger( this ); +} + +// --------------------------------------------------------------------- + +SmartAssertBase::UserResponse SmartAssertBase::AskUser() const +{ + return CommandLineAssertPolicy::AskUser( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::AbortNow() const +{ + CommandLineAssertPolicy::AbortNow( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::HandleFailure() +{ + m_handled = true; + + try + { + if ( Info_ == m_level ) + { + CallOutput(); + return; + } + CallOutput(); + if ... [truncated message content] |