RCFProto
 All Classes Functions Typedefs
Assert.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_UTIL_ASSERT_HPP
20 #define INCLUDE_UTIL_ASSERT_HPP
21 
22 #include <cassert>
23 #include <exception>
24 #include <iostream>
25 
26 #include <boost/current_function.hpp>
27 
28 #include "Throw.hpp"
29 #include "VariableArgMacro.hpp"
30 
31 #if defined(_MSC_VER) && !defined(NDEBUG)
32 #include <crtdbg.h>
33 #endif
34 
35 namespace util {
36 
37  class AssertFunctor : public VariableArgMacroFunctor
38  {
39  public:
40 
41  AssertFunctor() : mExpr(NULL)
42  {
43  }
44 
45  AssertFunctor(const char * expr) : mExpr(expr)
46  {
47  }
48 
49 #if defined(_MSC_VER) && !defined(NDEBUG)
50 #pragma warning(push)
51 #pragma warning(disable: 4995) // 'sprintf': name was marked as #pragma deprecated
52 #pragma warning(disable: 4996) // 'sprintf': This function or variable may be unsafe.
53 
54  ~AssertFunctor()
55  {
56  const char * msg =
57  "%s\n"
58  "Values: %s\n"
59  "Function: %s";
60 
61  std::string values(mArgs->str(), static_cast<std::size_t>(mArgs->tellp()));
62 
63  char szBuffer[512] = {0};
64  sprintf(szBuffer, "%s(%d): Assert failed. Expression: %s.\n", mFile, mLine, mExpr);
65  OutputDebugStringA(szBuffer);
66  std::cout << szBuffer;
67  int ret = _CrtDbgReport(_CRT_ASSERT, mFile, mLine, "", msg, mExpr, values.c_str(), mFunc);
68  if (ret == 1)
69  {
70  // __debugbreak() is more likely to give a proper call stack.
71  //DebugBreak();
72  __debugbreak();
73  }
74  }
75 
76 #pragma warning(pop)
77 #else
78 
79  ~AssertFunctor()
80  {
81  std::string values(mArgs->str(), static_cast<std::size_t>(mArgs->tellp()));
82 
83  std::cout
84  << mFile << ":" << mLine
85  << ": Assertion failed. " << mExpr
86  << " . Values: " << values << std::endl;
87 
88  assert(0 && "See line above for assertion details.");
89  }
90 
91 #endif
92 
93  const char * mExpr;
94  };
95 
96  class VarArgAbort
97  {
98  public:
99  VarArgAbort()
100  {
101  abort();
102  }
103 
104  template<typename T>
105  VarArgAbort &operator()(const T &)
106  {
107  return *this;
108  }
109  };
110 
111 
112 #if 0
113 #define UTIL_ASSERT_DEBUG(cond, e, logName, logLevel) \
114  if (cond) ; \
115  else util::VarArgAssert(__FILE__, __LINE__, #cond)
116 #endif
117 
118 #ifdef _MSC_VER
119 #pragma warning( push )
120 #pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
121 #endif
122 
123 #if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
124 #define UTIL_ASSERT_DEBUG_GCC_33_HACK (const util::VariableArgMacro<util::ThrowFunctor> &)
125 #else
126 #define UTIL_ASSERT_DEBUG_GCC_33_HACK
127 #endif
128 
129  DECLARE_VARIABLE_ARG_MACRO( UTIL_ASSERT_DEBUG, util::AssertFunctor );
130  #define UTIL_ASSERT_DEBUG(expr, e, logName, logLevel) \
131  if (expr); \
132  else\
133  UTIL_ASSERT_DEBUG_GCC_33_HACK \
134  util::VariableArgMacro<util::AssertFunctor>(#expr) \
135  .init( \
136  "", \
137  "", \
138  __FILE__, \
139  __LINE__, \
140  BOOST_CURRENT_FUNCTION) \
141  .cast( (util::VariableArgMacro<util::AssertFunctor> *) NULL) \
142  .UTIL_ASSERT_DEBUG_A
143 
144 
145 
146  #define UTIL_ASSERT_DEBUG_A(x) UTIL_ASSERT_DEBUG_OP(x, B)
147  #define UTIL_ASSERT_DEBUG_B(x) UTIL_ASSERT_DEBUG_OP(x, A)
148  #define UTIL_ASSERT_DEBUG_OP(x, next) UTIL_ASSERT_DEBUG_A.notify_((x), #x).UTIL_ASSERT_DEBUG_ ## next
149 
150 #ifdef _MSC_VER
151 #pragma warning( pop )
152 #endif
153 
154 
155 
156 
157  #ifdef RCF_ALWAYS_ABORT_ON_ASSERT
158 
159  #define UTIL_ASSERT_RELEASE(cond, e, logName, logLevel) \
160  if (cond) ; \
161  else util::VarArgAbort()
162 
163  #else
164 
165  #define UTIL_ASSERT_RELEASE(cond, e, logName, logLevel) \
166  if (cond) ; \
167  else UTIL_THROW(e, logName, logLevel)(cond)
168 
169  #endif
170 
171  #define UTIL_ASSERT_NULL(cond, E) \
172  DUMMY_VARIABLE_ARG_MACRO()
173 
174  #ifdef NDEBUG
175  #define UTIL_ASSERT UTIL_ASSERT_RELEASE
176  #else
177  #define UTIL_ASSERT UTIL_ASSERT_DEBUG
178  #endif
179 
180 } // namespace util
181 
182 #endif