0032402: Coding Rules - eliminate msvc warning C4668 (symbol is not defined as a...
[occt.git] / src / Standard / Standard_Failure.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <Standard_Failure.hxx>
16
17 #include <Standard_ErrorHandler.hxx>
18 #include <Standard_Macro.hxx>
19 #include <Standard_NoSuchObject.hxx>
20 #include <Standard_PCharacter.hxx>
21 #include <Standard_Type.hxx>
22 #include <Standard_TypeMismatch.hxx>
23
24 #include <string.h>
25
26 IMPLEMENT_STANDARD_RTTIEXT(Standard_Failure,Standard_Transient)
27
28 namespace
29 {
30   //! Global parameter defining default length of stack trace.
31   static Standard_Integer Standard_Failure_DefaultStackTraceLength = 0;
32 }
33
34 // =======================================================================
35 // function : StringRef::allocate_message
36 // purpose  :
37 // =======================================================================
38 Standard_Failure::StringRef* Standard_Failure::StringRef::allocate_message (const Standard_CString theString)
39 {
40   if (theString == NULL
41   || *theString == '\0')
42   {
43     return NULL;
44   }
45
46   const Standard_Size aLen = strlen (theString);
47   StringRef* aStrPtr = (StringRef* )malloc (aLen + sizeof(Standard_Integer) + 1);
48   if (aStrPtr != NULL)
49   {
50     strcpy ((char* )&aStrPtr->Message[0], theString);
51     aStrPtr->Counter = 1;
52   }
53   return aStrPtr;
54 }
55
56 // =======================================================================
57 // function : StringRef::copy_message
58 // purpose  :
59 // =======================================================================
60 Standard_Failure::StringRef* Standard_Failure::StringRef::copy_message (Standard_Failure::StringRef* theString)
61 {
62   if (theString == NULL)
63   {
64     return NULL;
65   }
66
67   ++theString->Counter;
68   return theString;
69 }
70
71 // =======================================================================
72 // function : StringRef::deallocate_message
73 // purpose  :
74 // =======================================================================
75 void Standard_Failure::StringRef::deallocate_message (Standard_Failure::StringRef* theString)
76 {
77   if (theString != NULL)
78   {
79     if (--theString->Counter == 0)
80     {
81       free ((void* )theString);
82     }
83   }
84 }
85
86 // =======================================================================
87 // function : Standard_Failure
88 // purpose  :
89 // =======================================================================
90 Standard_Failure::Standard_Failure()
91 : myMessage (NULL),
92   myStackTrace (NULL)
93 {
94   const Standard_Integer aStackLength = Standard_Failure_DefaultStackTraceLength;
95   if (aStackLength > 0)
96   {
97     int aStackBufLen = Max (aStackLength * 200, 2048);
98     char* aStackBuffer = (char* )alloca (aStackBufLen);
99     if (aStackBuffer != NULL)
100     {
101       memset (aStackBuffer, 0, aStackBufLen);
102       if (Standard::StackTrace (aStackBuffer, aStackBufLen, aStackLength, NULL, 1))
103       {
104         myStackTrace = StringRef::allocate_message (aStackBuffer);
105       }
106     }
107   }
108 }
109
110 // =======================================================================
111 // function : Standard_Failure
112 // purpose  :
113 // =======================================================================
114 Standard_Failure::Standard_Failure (const Standard_CString theDesc)
115 : myMessage (NULL),
116   myStackTrace (NULL)
117 {
118   myMessage = StringRef::allocate_message (theDesc);
119   const Standard_Integer aStackLength = Standard_Failure_DefaultStackTraceLength;
120   if (aStackLength > 0)
121   {
122     int aStackBufLen = Max (aStackLength * 200, 2048);
123     char* aStackBuffer = (char* )alloca (aStackBufLen);
124     if (aStackBuffer != NULL)
125     {
126       memset (aStackBuffer, 0, aStackBufLen);
127       Standard::StackTrace (aStackBuffer, aStackBufLen, aStackLength, NULL, 1);
128       myStackTrace = StringRef::allocate_message (aStackBuffer);
129     }
130   }
131 }
132
133 // =======================================================================
134 // function : Standard_Failure
135 // purpose  :
136 // =======================================================================
137 Standard_Failure::Standard_Failure (const Standard_CString theDesc,
138                                     const Standard_CString theStackTrace)
139 : myMessage (NULL),
140   myStackTrace (NULL)
141 {
142   myMessage = StringRef::allocate_message (theDesc);
143   myStackTrace = StringRef::allocate_message (theStackTrace);
144 }
145
146 // =======================================================================
147 // function : Standard_Failure
148 // purpose  :
149 // =======================================================================
150 Standard_Failure::Standard_Failure (const Standard_Failure& theFailure)
151 : Standard_Transient (theFailure),
152   myMessage (NULL),
153   myStackTrace (NULL)
154 {
155   myMessage    = StringRef::copy_message (theFailure.myMessage);
156   myStackTrace = StringRef::copy_message (theFailure.myStackTrace);
157 }
158
159 // =======================================================================
160 // function : ~Standard_Failure
161 // purpose  :
162 // =======================================================================
163 Standard_Failure::~Standard_Failure()
164 {
165   StringRef::deallocate_message (myMessage);
166   StringRef::deallocate_message (myStackTrace);
167 }
168
169 // =======================================================================
170 // function : GetMessageString
171 // purpose  :
172 // =======================================================================
173 Standard_CString Standard_Failure::GetMessageString() const
174 {
175   return myMessage != NULL
176        ? myMessage->GetMessage()
177        : "";
178 }
179
180 // =======================================================================
181 // function : SetMessageString
182 // purpose  :
183 // =======================================================================
184 void Standard_Failure::SetMessageString (const Standard_CString theDesc)
185 {
186   if (theDesc == GetMessageString())
187   {
188     return;
189   }
190
191   StringRef::deallocate_message (myMessage);
192   myMessage = StringRef::allocate_message (theDesc);
193 }
194
195 // =======================================================================
196 // function : GetStackString
197 // purpose  :
198 // =======================================================================
199 Standard_CString Standard_Failure::GetStackString() const
200 {
201   return myStackTrace != NULL
202        ? myStackTrace->GetMessage()
203        : "";
204 }
205
206 // =======================================================================
207 // function : SetStackString
208 // purpose  :
209 // =======================================================================
210 void Standard_Failure::SetStackString (const Standard_CString theStack)
211 {
212   if (theStack == GetStackString())
213   {
214     return;
215   }
216
217   StringRef::deallocate_message (myStackTrace);
218   myStackTrace = StringRef::allocate_message (theStack);
219 }
220
221 // =======================================================================
222 // function : Raise
223 // purpose  :
224 // =======================================================================
225 void Standard_Failure::Raise (const Standard_CString theDesc)
226
227   Handle(Standard_Failure) aFailure = new Standard_Failure();
228   aFailure->Reraise (theDesc);
229 }
230
231 // =======================================================================
232 // function : Raise
233 // purpose  :
234 // =======================================================================
235 void Standard_Failure::Raise (const Standard_SStream& theReason)
236
237   Handle(Standard_Failure) aFailure = new Standard_Failure();
238   aFailure->Reraise (theReason);
239 }
240
241 // =======================================================================
242 // function : Reraise
243 // purpose  :
244 // =======================================================================
245 void Standard_Failure::Reraise (const Standard_CString theDesc)
246 {
247   SetMessageString (theDesc);
248   Reraise();
249 }
250
251 // =======================================================================
252 // function : Reraise
253 // purpose  :
254 // =======================================================================
255 void Standard_Failure::Reraise (const Standard_SStream& theReason)
256 {
257   SetMessageString (theReason.str().c_str());
258   Reraise();
259 }
260
261 // =======================================================================
262 // function : Reraise
263 // purpose  :
264 // =======================================================================
265 void Standard_Failure::Reraise()
266 {
267   Throw();
268 }
269
270 // =======================================================================
271 // function : Jump
272 // purpose  :
273 // =======================================================================
274 void Standard_Failure::Jump()
275 {
276 #if defined (OCC_CONVERT_SIGNALS)
277   Standard_ErrorHandler::Error (this);
278   Standard_ErrorHandler::Abort (this);
279 #else
280   Throw();
281 #endif
282 }
283
284 // =======================================================================
285 // function : Throw
286 // purpose  :
287 // =======================================================================
288 void Standard_Failure::Throw() const
289 {
290   throw *this;
291 }
292
293 // =======================================================================
294 // function : Print
295 // purpose  :
296 // =======================================================================
297 void Standard_Failure::Print (Standard_OStream& theStream) const
298 {
299   if (myMessage != NULL)
300   {
301     theStream << DynamicType() << ": " << GetMessageString();
302   }
303   else
304   {
305     theStream << DynamicType();
306   }
307   if (myStackTrace != NULL)
308   {
309     theStream << GetStackString();
310   }
311 }
312
313 // =======================================================================
314 // function : NewInstance
315 // purpose  :
316 // =======================================================================
317 Handle(Standard_Failure) Standard_Failure::NewInstance (Standard_CString theString)
318 {
319   return new Standard_Failure (theString);
320 }
321
322 // =======================================================================
323 // function : NewInstance
324 // purpose  :
325 // =======================================================================
326 Handle(Standard_Failure) Standard_Failure::NewInstance (Standard_CString theMessage,
327                                                         Standard_CString theStackTrace)
328 {
329   return new Standard_Failure (theMessage, theStackTrace);
330 }
331
332 // =======================================================================
333 // function : GetNbStackTraces
334 // purpose  :
335 // =======================================================================
336 Standard_Integer Standard_Failure::DefaultStackTraceLength()
337 {
338   return Standard_Failure_DefaultStackTraceLength;
339 }
340
341 // =======================================================================
342 // function : SetNbStackTraces
343 // purpose  :
344 // =======================================================================
345 void Standard_Failure::SetDefaultStackTraceLength (Standard_Integer theNbStackTraces)
346 {
347   Standard_Failure_DefaultStackTraceLength = theNbStackTraces;
348 }