icedb  version 0.5.1
Snow particle scattering database API
error.cpp
Go to the documentation of this file.
1 #include "../icedb/error.hpp"
2 #include "../private/options.hpp"
3 #include "../icedb/error_context.h"
4 #include "../icedb/error.h"
5 #include "../icedb/util.h"
6 #include <cstdio>
7 #include <cstring>
8 #include <vector>
9 #include <string>
10 #include <cwchar>
11 #include <complex>
12 #include <list>
13 #include <sstream>
14 
16 
18  if (!err) ICEDB_DEBUG_RAISE_EXCEPTION();
19  return err->code;
20 }
22 
24  if (!err) ICEDB_DEBUG_RAISE_EXCEPTION();
25  size_t total = 1;
26  const size_t buf_size = 1000;
27  char buf[buf_size];
28  if (err->message_text) {
29  total += ICEDB_COMPAT_strncpy_s(buf, buf_size, err->message_text, err->message_size); // Reports the number of characters copied. Note lack of count of null.
30  }
31  // Write the error variables
32  const char* sep = "\t%s\t=\t%s\n";
33  const size_t seplen = strlen(sep);
34 
35 #ifdef ICEDB_USING_SECURE_STRINGS
36  if (err->num_var_fields)
37  for (int i = 0; i < err->num_var_fields; ++i)
38  total += sprintf_s(buf + total, buf_size - total, sep, err->var_vals[i].varname, err->var_vals[i].val);
39 #else
40  size_t expectedSize = 0;
41  if (err->num_var_fields) {
42  for (int i = 0; i < err->num_var_fields; ++i) {
43  // Manually size a temporary buffer, and then copy the data.
44  expectedSize += seplen + strlen(err->var_vals[i].val) + strlen(err->var_vals[i].varname);
45  }
46  }
47  char *tempbuf = (char*)ICEDB_malloc(sizeof(char)*expectedSize);
48  size_t j = 0;
49  if (err->num_var_fields) {
50  for (int i = 0; i < err->num_var_fields; ++i) {
51  j += sprintf(tempbuf + j, sep, err->var_vals[i].varname, err->var_vals[i].val);
52  }
53  }
54  ICEDB_COMPAT_strncpy_s(buf + total, buf_size - total, tempbuf, j);
55  total += j;
56  ICEDB_free(tempbuf);
57 #endif
58 
59  return size_t(total);
60 }
62 
63 size_t error_context_to_message(const struct ICEDB_error_context * err, size_t buf_size, char * buf)
64 {
65  if (!err) ICEDB_DEBUG_RAISE_EXCEPTION();
66  if (!buf) ICEDB_DEBUG_RAISE_EXCEPTION();
67  size_t total = 0;
68  if (err->message_text) {
69  total = ICEDB_COMPAT_strncpy_s(buf, buf_size, err->message_text, err->message_size); // Reports the number of characters copied. Note lack of count of null.
70  }
71  // Write the error variables
72  const char* sep = "\t%s\t=\t%s\n";
73  const size_t seplen = strlen(sep);
74 
75 #ifdef ICEDB_USING_SECURE_STRINGS
76  if (err->num_var_fields)
77  for (int i = 0; i < err->num_var_fields; ++i)
78  total += sprintf_s(buf + total, buf_size - total, sep, err->var_vals[i].varname, err->var_vals[i].val);
79 #else
80  size_t expectedSize = 0;
81  if (err->num_var_fields) {
82  for (int i = 0; i < err->num_var_fields; ++i) {
83  // Manually size a temporary buffer, and then copy the data.
84  expectedSize += seplen + strlen(err->var_vals[i].val) + strlen(err->var_vals[i].varname);
85  }
86  }
87  char *tempbuf = (char*)ICEDB_malloc(sizeof(char)*expectedSize);
88  size_t j = 0;
89  if (err->num_var_fields) {
90  for (int i = 0; i < err->num_var_fields; ++i) {
91  j += sprintf(tempbuf + j, sep, err->var_vals[i].varname, err->var_vals[i].val);
92  }
93  }
94  ICEDB_COMPAT_strncpy_s(buf + total, buf_size - total, tempbuf, j);
95  total += j;
96  ICEDB_free(tempbuf);
97 #endif
98 
99  return size_t(total);
100 }
102 
103 size_t error_context_to_stream(const struct ICEDB_error_context * err, FILE * fp)
104 {
105  if (!err) ICEDB_DEBUG_RAISE_EXCEPTION();
106  if (!fp) ICEDB_DEBUG_RAISE_EXCEPTION();
107  int res = 0;
108  if (err->message_text) {
109  res = ICEDB_COMPAT_fputs_s(err->message_text, fp);
110  }
111  // Error validation
112  if (res == EOF) {
113  printf("Error in writing error context to stream. Error code is %d. Context text is: %s.\n",
114  ferror(fp), err->message_text);
115  }
116 
117  // Write the error variables
118  if (err->num_var_fields) {
119  for (int i = 0; i < err->num_var_fields; ++i)
120  ICEDB_COMPAT_fprintf_s(fp, "\t%s\t=\t%s\n", err->var_vals[i].varname, err->var_vals[i].val);
121  }
122  return uint16_t(res);
123 }
125 
127 {
129  ICEDB_error_context_append_str(cxt, "This is a test.\n");
130  return ICEDB_ERRORCODES_TODO;
131 }
133 
135 {
137  size_t res = (size_t)ICEDB_COMPAT_strnlen_s(ICEDB_ERRORCODES_MAP[err],
138  1000) + 1; // -1,+1 because message_size includes the null character.
139  return res;
140 }
142 
143 size_t error_code_to_message(ICEDB_error_code err, size_t buf_size, char * buf)
144 {
145  if (!buf) ICEDB_DEBUG_RAISE_EXCEPTION();
147  uint16_t cnt = (uint16_t)ICEDB_COMPAT_strnlen_s(ICEDB_ERRORCODES_MAP[err],
148  SIZE_MAX - 1) + 1; // -1,+1 because message_size includes the null character.
149  size_t res = ICEDB_COMPAT_strncpy_s(buf, buf_size, ICEDB_ERRORCODES_MAP[err], cnt);
150  return size_t((res>SIZE_MAX) ? SIZE_MAX : res);
151 }
153 
155 {
156  if (!fp) ICEDB_DEBUG_RAISE_EXCEPTION();
158  size_t res = ICEDB_COMPAT_fputs_s(ICEDB_ERRORCODES_MAP[err], fp);
159 
160  return size_t(res);
161 }
163 
165 {
167 }
169 
171 {
172  if (!c) ICEDB_DEBUG_RAISE_EXCEPTION();
174  if (c->var_vals) { // Should always exist, as the construction function automatically widens / allocates.
175  for (int i = 0; i < c->num_var_fields; ++i) {
176  ICEDB_free(c->var_vals[i].val);
177  ICEDB_free(c->var_vals[i].varname);
178  }
179  ICEDB_free(c->var_vals);
180  }
181  ICEDB_free(c);
182 }
184 
185 const char* error_getOSname() {
186  const char* name =
187 #if defined(__FreeBSD__)
188  "FreeBSD";
189 #elif defined(__NetBSD__)
190  "NetBSD";
191 #elif defined(__OpenBSD__)
192  "OpenBSD";
193 #elif defined(__bsdi__)
194  "bsdi";
195 #elif defined(__DragonFly__)
196  "DragonFly BSD";
197 #elif defined (__APPLE__)
198  "Apple";
199 #elif defined(__linux__)
200  "Linux";
201 #elif defined(_WIN32)
202  "Windows";
203 #elif defined(__unix__)
204  "Generic Unix";
205 #else
206  "UNKNOWN";
207 #endif
208  return name;
209 }
211 
222  error_test,
224 };
225 
227 
228 namespace icedb {
229  namespace error {
231  public:
232  std::list<::icedb::registry::const_options_ptr> stk;
235  std::string emessage;
236  };
238  ep = std::shared_ptr<error_options_inner>(new error_options_inner);
239  ep->et = xe;
240  }
242  const char* xError::what() const noexcept {
243  //static const char* msg = "An unknown error has occurred.";
244  //return msg;
245  std::ostringstream o;
246  o << "error: " << stringify(ep->et) << std::endl;
247  // Pull from stack
248  int i = 1;
249  for (const auto &e : ep->stk) {
250  o << "Throw frame " << i << std::endl;
251  e->enumVals(o);
252  ++i;
253  }
254  ep->emessage = o.str();
255  return ep->emessage.c_str();
256  }
258  {
259  ep->stk.push_back(op);
260  ep->cur = op;
261  return *this;
262  }
264  {
266  ep->stk.push_back(op);
267  ep->cur = op;
268  return *this;
269  }
270 
271  template <class T> xError& xError::add(const std::string &key, const T value)
272  {
273  if (!ep->cur) push();
274  this->ep->cur->add<T>(key, value);
275  return *this;
276  }
277 
278 #define DOTYPES(f) f(int); f(float); f(double); f(long); f(long long); \
279  f(unsigned int); f(unsigned long); f(unsigned long long); f(std::string); f(bool); f(std::complex<double>);
280 
281 #define IMPL_xError_ADD(T) template xError& xError::add<T>(const std::string&, const T);
283 
284  template<> DL_ICEDB xError& xError::add(const std::string &key, char const * const value)
285  {
286  if (!ep->cur) push();
287  this->ep->cur->add<std::string>(key, std::string(value));
288  return *this;
289  }
290 
291 
292 
293  template<> DL_ICEDB std::string stringify<std::string>(error_code_t err) {
294  std::string res;
295  stringify(err, res);
296  return res;
297  }
298  template<> DL_ICEDB const char* stringify<const char*>(error_code_t err) {
299  return ICEDB_ERRORCODES_MAP[err];
300  }
301 
302 
305  }
306 
307  DL_ICEDB void stringify(error_code_t err, std::string &res) {
308  res = std::string(ICEDB_ERRORCODES_MAP[err]);
309  }
310  DL_ICEDB void stringify(error_code_t err, const char** res) {
311  *res = ICEDB_ERRORCODES_MAP[err];
312  }
313  DL_ICEDB void stringify(const error_context_pt &err, std::string &res) {
314  // A few memory copies occur here. Inefficient, but errors should not occur much in properly running code.
315  size_t sz = ICEDB_error_context_to_message_size(err.get());
316  //std::unique_ptr<char[]> buf(new char[sz]);
317  std::vector<char> buf(sz);
318  ICEDB_error_context_to_message(err.get(), sz, buf.data());
319  res = std::string(buf.data());
320  }
321  DL_ICEDB std::string stringify(const error_context_pt &err) {
322  std::string res;
323  stringify(err, res);
324  return res;
325  }
326 
328 
329  }
330 }
331 
#define ICEDB_DEBUG_RAISE_EXCEPTION()
Definition: defs.h:151
#define ICEDB_error_context_append_str
Definition: error_context.h:61
A convenience wrapper for all error functions.
Definition: error.h:104
ICEDB_SYMBOL_SHARED void ICEDB_free(void *obj)
Free memory region. Should not be double-freed.
Definition: util.cpp:97
DL_ICEDB ICEDB_error_context_to_message_f ICEDB_error_context_to_message
Definition: error.cpp:101
#define DL_ICEDB
Definition: defs.h:124
DL_ICEDB error_code_t error_context_to_code(const error_context_pt &err)
Definition: error.cpp:327
Not really an error, but used for counting.
Definition: errorCodes.h:23
DL_ICEDB ICEDB_error_code_to_stream_f ICEDB_error_code_to_stream
Definition: error.cpp:162
#define ICEDB_BEGIN_DECL_C
Definition: defs.h:20
size_t error_context_to_message(const struct ICEDB_error_context *err, size_t buf_size, char *buf)
Definition: error.cpp:63
size_t error_code_to_message_size(ICEDB_error_code err)
Definition: error.cpp:134
std::shared_ptr< ICEDB_error_context > error_context_pt
Definition: error.hpp:56
virtual const char * what() const noexcept
Definition: error.cpp:242
DL_ICEDB const struct ICEDB_error_container_ftable ICEDB_ct_error
Definition: error.cpp:212
static std::shared_ptr< options > generate()
Definition: options.cpp:18
ICEDB_error_code error_code_t
Definition: error.hpp:42
Placeholder error value.
Definition: errorCodes.h:11
size_t(* ICEDB_error_code_to_message_size_f)(ICEDB_error_code err)
Definition: error.h:24
ICEDB_error_code code
Definition: error_context.h:20
DL_ICEDB ICEDB_error_context_to_message_size_f ICEDB_error_context_to_message_size
Definition: error.cpp:61
ICEDB_error_context_var_val * var_vals
Definition: error_context.h:26
size_t(* ICEDB_error_context_to_message_f)(const struct ICEDB_error_context *err, size_t buf_size, char *buf)
Definition: error.h:83
DL_ICEDB ICEDB_error_code_to_message_size_f ICEDB_error_code_to_message_size
Definition: error.cpp:141
#define ICEDB_END_DECL_C
Definition: defs.h:21
DL_ICEDB ICEDB_error_getOSname_f ICEDB_error_getOSname
Definition: error.cpp:210
void error_context_deallocate(struct ICEDB_error_context *c)
Definition: error.cpp:170
size_t(* ICEDB_error_context_to_stream_f)(const struct ICEDB_error_context *err, FILE *fp)
Definition: error.h:92
size_t(* ICEDB_error_context_to_message_size_f)(const struct ICEDB_error_context *)
Definition: error.h:70
DL_ICEDB void stringify(error_code_t err, std::string &res)
Definition: error.cpp:307
DL_ICEDB ICEDB_error_code_to_message_f ICEDB_error_code_to_message
Definition: error.cpp:152
xError & add(const std::string &key, const T value)
Definition: error.cpp:271
ICEDB_BEGIN_DECL_C ICEDB_SYMBOL_SHARED size_t ICEDB_COMPAT_strncpy_s(char *dest, size_t destSz, const char *src, size_t srcSz)
Definition: util.cpp:14
struct ICEDB_error_context * get_error_context_thread_local_c()
Definition: error.cpp:164
size_t error_context_to_message_size(const struct ICEDB_error_context *err)
Definition: error.cpp:23
const char * error_getOSname()
Definition: error.cpp:185
#define IMPL_xError_ADD(T)
Definition: error.cpp:281
size_t error_code_to_message(ICEDB_error_code err, size_t buf_size, char *buf)
Definition: error.cpp:143
size_t error_context_to_stream(const struct ICEDB_error_context *err, FILE *fp)
Definition: error.cpp:103
DL_ICEDB error_context_pt get_error_context_thread_local()
Definition: error.cpp:303
DL_ICEDB ICEDB_error_test_f ICEDB_error_test
Definition: error.cpp:132
struct ICEDB_error_context *(* ICEDB_get_error_context_thread_local_f)()
Definition: error.h:58
ICEDB_error_code error_test()
Definition: error.cpp:126
DL_ICEDB ICEDB_error_context_to_code_f ICEDB_error_context_to_code
Definition: error.cpp:21
size_t error_code_to_stream(ICEDB_error_code err, FILE *fp)
Definition: error.cpp:154
ICEDB_SYMBOL_SHARED void * ICEDB_malloc(size_t numBytes)
Allocate memory in bytes. Generally this is just malloced, but a custom allocator may be substituted...
Definition: util.cpp:90
DL_ICEDB ICEDB_error_context_to_stream_f ICEDB_error_context_to_stream
Definition: error.cpp:124
xError & push()
Definition: error.cpp:263
std::shared_ptr< options > options_ptr
DL_ICEDB ICEDB_error_context_deallocate_f ICEDB_error_context_deallocate
Definition: error.cpp:183
ICEDB_SYMBOL_PRIVATE ICEDB_THREAD_LOCAL ICEDB_error_context * __ICEDB_LOCAL_THREAD_error_context
ICEDB_error_code(* ICEDB_error_test_f)()
Definition: error.h:96
xError(error_types=error_types::xOtherError)
Definition: error.cpp:237
size_t(* ICEDB_error_code_to_stream_f)(ICEDB_error_code err, FILE *fp)
Definition: error.h:47
const char *(* ICEDB_error_getOSname_f)()
Convenience function that returns an immutable string describing the OS type. Staticly allocated...
Definition: error.h:100
void(* ICEDB_error_context_deallocate_f)(struct ICEDB_error_context *)
Definition: error.h:62
ICEDB_SYMBOL_PRIVATE const char * ICEDB_ERRORCODES_MAP[ICEDB_ERRORCODES_TOTAL]
Definition: errorCodes.cpp:3
DL_ICEDB ICEDB_get_error_context_thread_local_f ICEDB_get_error_context_thread_local
Definition: error.cpp:168
DOTYPES(IMPL_xError_ADD)
size_t(* ICEDB_error_code_to_message_f)(ICEDB_error_code err, size_t buf_size, char *buf)
Definition: error.h:38
#define ICEDB_COMPAT_strnlen_s
Definition: util.h:44
#define ICEDB_COMPAT_fputs_s
Definition: util.h:35
ICEDB_error_code(* ICEDB_error_context_to_code_f)(const struct ICEDB_error_context *)
Definition: error.h:66
#define ICEDB_error_context_create(x)
Definition: error_context.h:35
::icedb::registry::options_ptr cur
Definition: error.cpp:233
ICEDB_BEGIN_DECL_C ICEDB_error_code error_context_to_code(const struct ICEDB_error_context *err)
Definition: error.cpp:17
int ICEDB_error_code
Definition: error.h:17
virtual ~xError()
Definition: error.cpp:241
#define ICEDB_COMPAT_fprintf_s
Definition: util.h:26
std::list<::icedb::registry::const_options_ptr > stk
Definition: error.cpp:232