Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
exception.cpp
Go to the documentation of this file.
1
27// expand _TEST_EXPORT macros
28#define _RWSTD_TEST_SRC
29
30#include <rw_exception.h>
31#include <rw_driver.h>
32#include <rw_printf.h>
33
34#include <string.h> // for size_t, strcpy()
35#include <stdlib.h> // for free()
36#include <stdarg.h> // for va_arg(), va_list
37#include <new> // for std::bad_alloc
38
39
42rw_vasnprintf (char**, size_t*, const char*, va_list);
43
44static int
45_rw_format (char** pbuf, size_t* pbufsize, const char* file, int line,
46 const char* function, const char* fmt, va_list va);
47
48
51{
52}
53
54
57{
58private:
59 struct ExceptionString;
60
61public:
62 char buf_ [256];
63 ExceptionString* ex_str_;
64
67
69
71
72 void format (const char* file, int line, const char* function,
73 const char* fmt, va_list va);
74
75 const char* what () const;
76
77private:
78
79 struct ExceptionString
80 {
81 long refs_;
82 char* str_;
83
84 void init (char* str)
85 {
86 refs_ = 1;
87 str_ = str;
88 }
89
90 void addref () { ++refs_; }
91
92 long release ()
93 {
94 if (0 == --refs_) {
95 free (str_);
96 str_ = 0;
97 }
98 return refs_;
99 }
100
101 private:
102 // not defined
103 ExceptionString (const ExceptionString&);
104 ExceptionString& operator= (const ExceptionString&);
105 };
106
107
108 void free_ ();
109};
110
112{
113 buf_ [0] = '\0';
114}
115
117{
118 *this = ex;
119}
120
122{
123 free_ ();
124}
125
127{
128 if (&ex != this) {
129
130 free_ ();
131
132 if (ex.ex_str_) {
133 ex_str_ = ex.ex_str_;
134 ex_str_->addref ();
135 }
136 else
137 strcpy (buf_, ex.buf_);
138 }
139
140 return *this;
141}
142
143
145format (const char* file, int line,
146 const char* function, const char* fmt, va_list va)
147{
148 free_ ();
149
150 char* tmpbuf = 0;
151 size_t bufsize = 0;
152
153 const int nchars =
154 _rw_format (&tmpbuf, &bufsize, file, line, function, fmt, va);
155
156 if (0 > nchars)
157 return;
158
159 if (sizeof buf_ <= size_t (nchars)) {
160 // tmpbuf_ size is too small
161 ex_str_ = _RWSTD_STATIC_CAST (ExceptionString*,
162 malloc (sizeof (*ex_str_)));
163
164 if (ex_str_) {
165 ex_str_->init (tmpbuf);
166 return;
167 }
168 }
169
170 // buf_ size if enough or cannot allocate memory for the ex_str_
171 const size_t len =
172 size_t (nchars) < sizeof buf_ ? size_t (nchars) : sizeof buf_ - 1;
173 memcpy (buf_, tmpbuf, len);
174 buf_ [len] = '\0';
175 free (tmpbuf);
176}
177
178
179const char* ExceptionBase::what () const
180{
181 return ex_str_ && ex_str_->str_ ? ex_str_->str_ : buf_;
182}
183
184void ExceptionBase::free_ ()
185{
186 buf_ [0] = '\0';
187
188 if (ex_str_ && 0 == ex_str_->release ()) {
189 free (ex_str_);
190 ex_str_ = 0;
191 }
192}
193
194
197{
199 {
200 }
201
203 {
204 }
205
207
208 const char* what () const _THROWS (())
209 {
210 const char* msg = ExceptionBase::what ();
211 return (msg && msg[0]) ? msg : std::bad_alloc::what ();
212 }
213};
214
215
218{
220 {
221 }
222
225 {
226 }
227
228 const char* what () const
229 {
230 return ExceptionBase::what ();
231 }
232};
233
234
236static int
237_rw_format (char** pbuf, size_t* pbufsize, const char* file, int line,
238 const char* function, const char* fmt, va_list va)
239{
240 const int nchars1 = function ?
241 rw_asnprintf (pbuf, pbufsize, "\"%s\", %d, \"%s\" ",
242 file, line, function) :
243 rw_asnprintf (pbuf, pbufsize, "\"%s\", %d, ", file, line);
244
245 if (0 > nchars1)
246 return nchars1;
247
248 char *tmpbuf = 0;
249 size_t tmpsize = 0;
250
251 const int nchars2 = rw_vasnprintf (&tmpbuf, &tmpsize, fmt, va);
252
253 if (0 > nchars2) {
254 free (tmpbuf);
255 return nchars1;
256 }
257
258 const int nchars3 = rw_asnprintf (pbuf, pbufsize, "%{+}%s", tmpbuf);
259
260 free (tmpbuf);
261
262 return 0 > nchars3 ? nchars1 : nchars1 + nchars3;
263}
264
265_TEST_EXPORT void
266rw_throw (ExceptionId exid, const char *file, int line,
267 const char *function, const char *fmt, ...)
268{
269 va_list va;
270 va_start (va, fmt);
271
273 base.format (file, line, function, fmt, va);
274
275 va_end (va);
276
277 switch (exid) {
278
279 case ex_stream:
280 throw StreamException (base);
281
282 case ex_bad_alloc:
283 throw BadAlloc (base);
284
285 default:
286 throw ex_unknown;
287 }
288}
#define nchars
Definition 17.names.cpp:502
#define msg
Definition 17.names.cpp:498
#define line
Definition 17.names.cpp:490
#define len
Definition 17.names.cpp:488
#define _THROWS()
#define va_end(ignore)
#define va_start(va, name)
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
std::mbstate_t init
Definition codecvt1.cpp:80
const char * str
Definition exec.cpp:170
ExceptionId
@ ex_stream
@ ex_unknown
@ ex_bad_alloc
_TEST_EXPORT int rw_asnprintf(char **pbuf, _RWSTD_SIZE_T *pbufsize, const char *fmt,...)
#define _TEST_EXPORT
Definition rw_testdefs.h:55
BadAlloc(const ExceptionBase &ex)
~BadAlloc() _THROWS(())
const char * what() const _THROWS(())
char buf_[256]
Definition exception.cpp:62
void format(const char *file, int line, const char *function, const char *fmt, va_list va)
const char * what() const
ExceptionBase & operator=(const ExceptionBase &)
ExceptionString * ex_str_
Definition exception.cpp:63
virtual ~Exception()
Definition exception.cpp:50
const char * what() const
StreamException(const ExceptionBase &ex)
_TEST_EXPORT void rw_throw(ExceptionId exid, const char *file, int line, const char *function, const char *fmt,...)
_TEST_EXPORT int rw_vasnprintf(char **, size_t *, const char *, va_list)
Definition printf.cpp:946