|
From: <ric...@us...> - 2013-08-06 22:56:33
|
Revision: 1191
http://sourceforge.net/p/loki-lib/code/1191
Author: rich_sposato
Date: 2013-08-06 22:56:31 +0000 (Tue, 06 Aug 2013)
Log Message:
-----------
Improved SmartAssert component.
Modified Paths:
--------------
trunk/Loki.sln
trunk/include/loki/SmartAssert.hpp
trunk/src/SmartAssert.cpp
trunk/test/SmartAssert/SmartAssert.cbp
trunk/test/SmartAssert/main.cpp
Modified: trunk/Loki.sln
===================================================================
--- trunk/Loki.sln 2013-06-24 06:10:50 UTC (rev 1190)
+++ trunk/Loki.sln 2013-08-06 22:56:31 UTC (rev 1191)
@@ -115,8 +115,6 @@
{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
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lockable", "test\Lockable\Lockable.vcxproj", "{22A34627-1480-4180-A8B6-4C05E77E27F8}"
ProjectSection(ProjectDependencies) = postProject
{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}
@@ -127,13 +125,15 @@
{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}"
+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
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadLocal", "test\ThreadLocal\ThreadLocal.vcxproj", "{27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -232,10 +232,6 @@
{0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Debug|Win32.Build.0 = Debug|Win32
{0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Release|Win32.ActiveCfg = Release|Win32
{0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Release|Win32.Build.0 = Release|Win32
- {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.ActiveCfg = Debug|Win32
- {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.Build.0 = Debug|Win32
- {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.ActiveCfg = Release|Win32
- {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.Build.0 = Release|Win32
{22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.ActiveCfg = Debug|Win32
{22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.Build.0 = Debug|Win32
{22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.ActiveCfg = Release|Win32
@@ -252,6 +248,10 @@
{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
+ {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.ActiveCfg = Debug|Win32
+ {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.Build.0 = Debug|Win32
+ {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.ActiveCfg = Release|Win32
+ {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Modified: trunk/include/loki/SmartAssert.hpp
===================================================================
--- trunk/include/loki/SmartAssert.hpp 2013-06-24 06:10:50 UTC (rev 1190)
+++ trunk/include/loki/SmartAssert.hpp 2013-08-06 22:56:31 UTC (rev 1191)
@@ -104,8 +104,8 @@
@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
+ Typical 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.
@@ -153,20 +153,15 @@
@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.
+ mimics the behaviors of assert. You can implement your own policies to handle
+ assertions by making a class with the function signatures shown below. If you
+ write your own policy class, you should also use the LOKI_SMART_ASSERT_POLICIED
+ macro, and not the LOKI_SMART_ASSERT macro.
- @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 bool FixedProblem( const SmartAssertBase * asserter );
static void Output( const SmartAssertBase * asserter );
static void Debugger( const SmartAssertBase * asserter );
static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter );
@@ -175,6 +170,16 @@
LOKI_SMART_ASSERT_POLICIED( cond, MyPolicy );
@endcode
+ @par Potential Policies You Can Create
+ - To provide a different output message than the default one.
+ - To call a special debugger rather than the default one.
+ - To send output to a log file, syslog, or cout, instead of to cerr.
+ - To create a popup dialog box to ask the user.
+ - To attempt last moment cleanup before the program dies.
+ - To correct the problem.
+ - To fix data invariants caused by the problem.
+ - Handle assertion by throwing exception.
+
@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
@@ -239,6 +244,7 @@
LongDouble
};
+ /// Provides human readable name of data type.
static const char * GetName( DataTypeTag tag );
/// @union DataValue Can be configured as any primitive data type.
@@ -285,7 +291,11 @@
DataValue( const double v ) : m_double( v ) {}
DataValue( const long double v ) : m_l_double( v ) {}
- void Output( DataTypeTag type ) const;
+ /** Sends output of datatype and value to cerr or cout.
+ @param type What type of data is in the union.
+ @param use_cerr True to send output to standard error instead of standard out.
+ */
+ void Output( DataTypeTag type, bool use_cerr ) const;
};
AssertInfo() : m_type( Unknown ), m_value(), m_next( nullptr ) {}
@@ -309,11 +319,13 @@
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;
+ /** Provides default output action.
+ @param use_cerr True to send output to standard error instead of standard out.
+ */
+ void Output( bool use_cerr ) const;
- DataTypeTag m_type; ///< What type of data this stores.
- DataValue m_value; ///< Value of that data.
+ 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.
};
@@ -337,7 +349,7 @@
AssertContext( const char * description, const char * value );
/// Function provides default output action.
- void Output() const;
+ void Output( bool use_cerr ) const;
unsigned int m_line; ///< Line number within file.
const char * m_value; ///< Pointer to either filename or function name.
@@ -383,14 +395,16 @@
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.
+ /// @note All the variables are public so developers can access them through policy classes.
+ 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.
@@ -414,34 +428,38 @@
/// Called to handle assertion failure.
void HandleFailure();
- /// Default implementation of code to output information about assertion.
+private:
+
+ /// @note Virtual functions are private to prevent policy classes from using them.
+
+ /// Calls policy class to find out if host program fixed problem.
+ virtual bool FixedProblem() const = 0;
+
+ /// Calls policy class to output information about assertion.
virtual void CallOutput() const;
- /// Default implementation of code to call debugger.
- virtual void CallDebugger() const;
+ /// Calls policy class to invoke debugger.
+ virtual void CallDebugger() const = 0;
- /// Default implementation of code to ask user what to do.
- virtual UserResponse AskUser() const;
+ /// Calls policy class to ask user what to do.
+ virtual UserResponse AskUser() const = 0;
- /// Default implementation of code to abort program.
+ /// Calls policy class 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 CoutAssertPolicy This is a policy for command line programs. It
+ sends assertion messages to the standard output stream, std::cout.
*/
-class CommandLineAssertPolicy
+class CoutAssertPolicy
{
public:
+ /// SmartAssert will ignore error if this returns true.
+ static bool FixedProblem( const SmartAssertBase * asserter );
+
/// Displays information about assertion to the user.
static void Output( const SmartAssertBase * asserter );
@@ -458,6 +476,24 @@
// ---------------------------------------------------------------------
+/** @class CerrAssertPolicy This is a policy for command line programs. It
+ sends assertion messages to the standard error stream, std::cerr. This is
+ the default policy for SmartAssert.
+*/
+class CerrAssertPolicy : public CoutAssertPolicy
+{
+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 );
+
+};
+
+// ---------------------------------------------------------------------
+
/** @class class SmartAssert
*/
template< class AssertPolicy >
@@ -486,7 +522,10 @@
/// 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.
+ /** Adds one piece of information to assertion, generally a variable or result of function call.
+ This function relies on conversion constructors in AssertInfo to create an AssertInfo from a
+ single variable.
+ */
SmartAssert & operator ()( const AssertInfo & info )
{
return static_cast< SmartAssert & >( AddInfo( info ) );
@@ -500,21 +539,33 @@
private:
+ /// @note Virtual functions are private to prevent policy classes from using them.
+
+ /// Calls policy class to find out if host program fixed problem.
+ virtual bool FixedProblem() const
+ {
+ return AssertPolicy::FixedProblem( dynamic_cast< const SmartAssertBase * >( this ) );
+ }
+
+ /// Calls policy class to output information about assertion.
virtual void CallOutput() const
{
AssertPolicy::Output( dynamic_cast< const SmartAssertBase * >( this ) );
}
+ /// Calls policy class to invoke debugger.
virtual void CallDebugger() const
{
AssertPolicy::Debugger( dynamic_cast< const SmartAssertBase * >( this ) );
}
+ /// Calls policy class to ask user what to do.
virtual SmartAssertBase::UserResponse AskUser() const
{
return AssertPolicy::AskUser( dynamic_cast< const SmartAssertBase * >( this ) );
}
+ /// Calls policy class to abort program.
virtual void AbortNow() const
{
AssertPolicy::AbortNow( dynamic_cast< const SmartAssertBase * >( this ) );
@@ -603,9 +654,9 @@
#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 > \
+ class class_name : public ::Loki::SmartAssert< ::Loki::CerrAssertPolicy > \
{ public: \
- typedef ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > BaseClass; \
+ typedef ::Loki::SmartAssert< ::Loki::CerrAssertPolicy > BaseClass; \
class_name( bool * ignore, const char * expression ) \
: BaseClass( ignore, expression ) {} \
virtual ~class_name() {} \
@@ -621,7 +672,7 @@
#else
#define LOKI_SMART_ASSERT( expr ) \
if ( true ) ; else \
- ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy >()
+ ::Loki::SmartAssert< ::Loki::CerrAssertPolicy >()
// Do nothing. Compiler should optimize away the else branch.
#endif
Modified: trunk/src/SmartAssert.cpp
===================================================================
--- trunk/src/SmartAssert.cpp 2013-06-24 06:10:50 UTC (rev 1190)
+++ trunk/src/SmartAssert.cpp 2013-08-06 22:56:31 UTC (rev 1191)
@@ -51,7 +51,7 @@
namespace Loki
{
-bool SmartAssertBase::s_alwaysIgnore = true;
+static bool s_alwaysIgnore = true;
const char * const SmartAssertBase::FileDesc = "file";
const char * const SmartAssertBase::LineDesc = "line";
@@ -92,119 +92,121 @@
// ---------------------------------------------------------------------
-void AssertInfo::DataValue::Output( DataTypeTag theType ) const
+void AssertInfo::DataValue::Output( DataTypeTag theType, bool use_cerr ) const
{
+ ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout;
+
switch ( theType )
{
case Unknown:
{
- cout << "\t Error! Unknown data type! " << theType;
+ out << "\t Error! Unknown data type! " << theType;
break;
}
case Boolean:
{
const char * message = m_bool ? "true" : "false";
- cout << message;
+ out << message;
break;
}
case JustChar:
{
- cout << m_char;
+ out << m_char;
break;
}
case SignedChar:
{
- cout << m_s_char;
+ out << m_s_char;
break;
}
case UnsignedChar:
{
- cout << m_u_char;
+ out << m_u_char;
break;
}
case SignedShort:
{
- cout << m_s_short;
+ out << m_s_short;
break;
}
case UnsignedShort:
{
- cout << m_u_short;
+ out << m_u_short;
break;
}
case JustInt:
{
- cout << m_int;
+ out << m_int;
break;
}
case SignedInt:
{
- cout << m_int;
+ out << m_int;
break;
}
case UnsignedInt:
{
- cout << m_u_int;
+ out << m_u_int;
break;
}
case Long:
{
- cout << m_long;
+ out << m_long;
break;
}
case UnsignedLong:
{
- cout << m_u_long;
+ out << m_u_long;
break;
}
case LongInt:
{
- cout << m_s_long_int;
+ out << m_s_long_int;
break;
}
case UnsignedLongInt:
{
- cout << m_u_long_int;
+ out << m_u_long_int;
break;
}
case CharPtr:
{
- cout << m_p_char;
+ out << m_p_char;
break;
}
case SignedCharPtr:
{
- cout << m_p_s_char;
+ out << m_p_s_char;
break;
}
case UnsignedCharPtr:
{
- cout << m_p_u_char;
+ out << m_p_u_char;
break;
}
case VoidPtr:
{
- cout << m_p_v;
+ out << m_p_v;
break;
}
case Float:
{
- cout << m_float;
+ out << m_float;
break;
}
case Double:
{
- cout << m_double;
+ out << m_double;
break;
}
case LongDouble:
{
- cout << m_l_double;
+ out << m_l_double;
break;
}
default:
{
- cout << "\t Error! Undefined data type! " << theType;
+ out << "\t Error! Undefined data type! " << theType;
break;
}
}
@@ -212,11 +214,12 @@
// ---------------------------------------------------------------------
-void AssertInfo::Output() const
+void AssertInfo::Output( bool use_cerr ) const
{
- cout << "\t" << GetName( m_type ) << ": ";
- m_value.Output( m_type );
- cout << endl;
+ ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout;
+ out << "\t" << GetName( m_type ) << ": ";
+ m_value.Output( m_type, use_cerr );
+ out << endl;
}
// ---------------------------------------------------------------------
@@ -241,16 +244,17 @@
// ---------------------------------------------------------------------
-void AssertContext::Output() const
+void AssertContext::Output( bool use_cerr ) const
{
- cout << m_description << ": ";
+ ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout;
+ out << m_description << ": ";
if ( m_value != nullptr )
{
- cout << m_value;
+ out << m_value;
}
else
{
- cout << m_line;
+ out << m_line;
}
}
@@ -354,28 +358,14 @@
void SmartAssertBase::CallOutput() const
{
- CommandLineAssertPolicy::Output( this );
+ CerrAssertPolicy::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 );
+ CerrAssertPolicy::AbortNow( this );
}
// ---------------------------------------------------------------------
@@ -383,15 +373,18 @@
void SmartAssertBase::HandleFailure()
{
m_handled = true;
+ if ( FixedProblem() )
+ {
+ return;
+ }
try
{
+ CallOutput();
if ( Info_ == m_level )
{
- CallOutput();
return;
}
- CallOutput();
if ( m_level == Fatal_ )
{
AbortNow();
@@ -431,57 +424,42 @@
// ---------------------------------------------------------------------
-void CommandLineAssertPolicy::Output( const SmartAssertBase * asserter )
+void CommonOutput( const SmartAssertBase * asserter, bool use_cerr )
{
- cout << SmartAssertBase::GetName( asserter->m_level )
- << "! Assertion failed! " << asserter->m_expression << endl;
+ ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout;
+ out << SmartAssertBase::GetName( asserter->m_level )
+ << "! Assertion failed! " << asserter->m_expression << endl;
if ( nullptr != asserter->m_context )
{
- cout << "\t";
- asserter->m_context->Output();
+ out << "\t";
+ asserter->m_context->Output( use_cerr );
for ( const AssertContext * p = asserter->m_context->m_next; ( p != nullptr ); p = p->m_next )
{
- cout << " ";
- p->Output();
+ out << " ";
+ p->Output( use_cerr );
}
- cout << endl;
+ out << endl;
}
if ( ( nullptr != asserter->m_message ) && ( '\0' != *asserter->m_message ) )
{
- cout << "\t" << asserter->m_message << endl;
+ out << "\t" << asserter->m_message << endl;
}
for ( const AssertInfo * p = asserter->m_info; ( p != nullptr ); p = p->m_next )
{
- p->Output();
+ p->Output( use_cerr );
}
}
// ---------------------------------------------------------------------
-void CommandLineAssertPolicy::Debugger( const SmartAssertBase * )
+SmartAssertBase::UserResponse CommonAskUser( const SmartAssertBase * asserter, bool use_cerr )
{
-#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 )
- ::DebugBreak(); // Win32
+ ::std::basic_ostream< char > & output = ( use_cerr ) ? ::std::cerr : ::std::cout;
-#elif ( defined _MSC_VER ) || ( defined __BORLANDC__) || ( defined __MWERKS__ )
- __asm { int 3 };
-
-#elif defined(__GNUC__) // GCC
- __asm ("int $0x3");
-
-#else
- # error "Please supply instruction to DebugBreak (like 'int 3' on Intel processors)"
-#endif
-}
-
-// ---------------------------------------------------------------------
-
-SmartAssertBase::UserResponse CommandLineAssertPolicy::AskUser( const SmartAssertBase * asserter )
-{
const char * prompt = ( SmartAssertBase::Error_ == asserter->m_level ) ?
"\tChoose option: (I)gnore This Time, Ignore (E)ach Time, (D)ebug, (A)bort " :
"\tChoose option: (I)gnore This Time, Ignore (E)ach Time, (D)ebug ";
- ::std::cout << prompt;
+ output << prompt;
bool keep_asking = true;
while ( keep_asking )
@@ -502,7 +480,7 @@
}
if ( !isspace( ch ) && keep_asking ) // ignore spaces
{
- std::cout << prompt;
+ output << prompt;
}
}
@@ -511,8 +489,48 @@
// ---------------------------------------------------------------------
-void CommandLineAssertPolicy::AbortNow( const SmartAssertBase * )
+bool CoutAssertPolicy::FixedProblem( const SmartAssertBase * )
{
+ return false;
+}
+
+// ---------------------------------------------------------------------
+
+void CoutAssertPolicy::Output( const SmartAssertBase * asserter )
+{
+ CommonOutput( asserter, false );
+}
+
+// ---------------------------------------------------------------------
+
+void CoutAssertPolicy::Debugger( const SmartAssertBase * )
+{
+#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 )
+ ::DebugBreak(); // Win32
+
+#elif ( defined _MSC_VER ) || ( defined __BORLANDC__) || ( defined __MWERKS__ )
+ __asm { int 3 };
+
+#elif defined(__GNUC__) // GCC
+ __asm ("int $0x3");
+
+#else
+ # error "Please supply instruction to DebugBreak (like 'int 3' on Intel processors)"
+#endif
+}
+
+// ---------------------------------------------------------------------
+
+SmartAssertBase::UserResponse CoutAssertPolicy::AskUser( const SmartAssertBase * asserter )
+{
+ const SmartAssertBase::UserResponse reply = CommonAskUser( asserter, false );
+ return reply;
+}
+
+// ---------------------------------------------------------------------
+
+void CoutAssertPolicy::AbortNow( const SmartAssertBase * )
+{
// This might be a good time to call any cleanup services,
// and to log any useful information to a file.
abort();
@@ -520,6 +538,21 @@
// ---------------------------------------------------------------------
+void CerrAssertPolicy::Output( const SmartAssertBase * asserter )
+{
+ CommonOutput( asserter, true );
+}
+
+// ---------------------------------------------------------------------
+
+SmartAssertBase::UserResponse CerrAssertPolicy::AskUser( const SmartAssertBase * asserter )
+{
+ const SmartAssertBase::UserResponse reply = CommonAskUser( asserter, true );
+ return reply;
+}
+
+// ---------------------------------------------------------------------
+
#if defined( _MSC_VER )
#pragma warning( pop )
#endif
Modified: trunk/test/SmartAssert/SmartAssert.cbp
===================================================================
(Binary files differ)
Modified: trunk/test/SmartAssert/main.cpp
===================================================================
--- trunk/test/SmartAssert/main.cpp 2013-06-24 06:10:50 UTC (rev 1190)
+++ trunk/test/SmartAssert/main.cpp 2013-08-06 22:56:31 UTC (rev 1191)
@@ -37,6 +37,9 @@
#include <iostream>
+#include <cassert>
+
+
// ---------------------------------------------------------------------
class Bogus { };
@@ -138,6 +141,66 @@
// ---------------------------------------------------------------------
+/** @class ListAssertInfoOnSameLine
+ This policy class demonstrates how to write and use your own policies.
+ It lists assert info descriptions on the same line as their values. It
+ assumes that if an AssertInfo type is a C-style string, then it must be
+ a description of the next AssertInfo value. It also puts a blank at the
+ start of the output to vertically separate the assertion info from any
+ previous output by the host program.
+ */
+class ListAssertInfoOnSameLine : public Loki::CerrAssertPolicy
+{
+public:
+ /// Displays information about assertion to the user.
+ static void Output( const Loki::SmartAssertBase * asserter );
+};
+
+// ---------------------------------------------------------------------
+
+void ListAssertInfoOnSameLine::Output( const ::Loki::SmartAssertBase * asserter )
+{
+ assert( nullptr != asserter );
+
+ ::std::cerr << ::std::endl << ::Loki::SmartAssertBase::GetName( asserter->m_level )
+ << "! Assertion failed! " << asserter->m_expression << ::std::endl;
+ if ( nullptr != asserter->m_context )
+ {
+ ::std::cerr << "\t";
+ asserter->m_context->Output( true );
+ for ( const ::Loki::AssertContext * p = asserter->m_context->m_next; ( p != nullptr ); p = p->m_next )
+ {
+ ::std::cerr << " ";
+ p->Output( true );
+ }
+ ::std::cerr << ::std::endl;
+ }
+ if ( ( nullptr != asserter->m_message ) && ( '\0' != *asserter->m_message ) )
+ {
+ ::std::cerr << "\t" << asserter->m_message << ::std::endl;
+ }
+
+ const char * description = nullptr;
+ for ( const ::Loki::AssertInfo * p = asserter->m_info; ( p != nullptr ); p = p->m_next )
+ {
+ if ( ( ::Loki::AssertInfo::CharPtr == p->m_type )
+ && ( p->m_next != nullptr ) )
+ {
+ description = p->m_value.m_p_char;
+ p = p->m_next;
+ }
+ else
+ {
+ description = "";
+ }
+ ::std::cerr << "\t" << Loki::AssertInfo::GetName( p->m_type ) << ": " << description << " (";
+ p->m_value.Output( p->m_type, true );
+ ::std::cerr << ')' << ::std::endl;
+ }
+}
+
+// ---------------------------------------------------------------------
+
int main( int argc, const char * argv[] )
{
@@ -156,9 +219,24 @@
int a3 = 3;
LOKI_SMART_ASSERT( 0 == argc ).Warn()( a1 )( a2 )( a3 )();
- // Show how to put names of variables into assertion info.
- LOKI_SMART_ASSERT( 0 == argc ).Warn()( a1 )( "a1" )( a2 )( "a2" )( a3 )( "a3" )();
+ const unsigned int counted = 57;
+ const char * name = "Darth Cuddles";
+ const bool result = true;
+ // Show how to put variables names into assertion info.
+ LOKI_SMART_ASSERT( 0 == argc ).Warn()( counted )( "counted" )( name )( "name" )( result )( "result" )();
+ // Same as before, but this shows how to use a policy to put variable names on the same line as their values.
+ LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn()
+ ( counted )( "counted" )( name )( "name" )( result )( "result" )();
+
+ // Same as before, but this shows how to use a policy to put variable descriptions on the same line as their values.
+ LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn()
+ ( counted )( "death toll" )( name )( "villain" )( result )( "Does evil lose?" )();
+
+ // Same as before, but this shows how to mix names/descriptions and unnamed variables in the same assertion output.
+ LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn()( a1 )
+ ( counted )( "death toll" )( name )( "villain" )( a3 )( result )( "Does evil lose?" )( a2 )();
+
test_data_types( argc, argv );
test_ignore( argc );
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|