1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
/*
Copyright (c) 2004-2015, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file KM_error.h
\version $Id$
\brief error reporting support
*/
#ifndef _KM_ERROR_H_
#define _KM_ERROR_H_
#include <string>
#define KM_DECLARE_RESULT(sym, i, l) const Result_t RESULT_##sym = Result_t(i, #sym, l);
namespace Kumu
{
// Result code container. Both a signed integer and a text string are stored in the object.
// When defining your own codes your choice of integer values is mostly unconstrained, but pay
// attention to the numbering in the other libraries that use Kumu. Values between -99 and 99
// are reserved for Kumu.
class Result_t
{
int value;
std::string label, symbol, message;
Result_t();
public:
// Return registered Result_t for the given "value" code.
static const Result_t& Find(int value);
// Unregister the Result_t matching the given "value" code. Returns
// RESULT_FALSE if "value" does not match a registered Result_t.
// Returns RESULT_FAIL if ( value < -99 || value > 99 ) (Kumu core
// codes may not be deleted).
static Result_t Delete(int value);
// Iteration through registered result codes, not thread safe.
// Get accepts contiguous values from 0 to End() - 1.
static unsigned int End();
static const Result_t& Get(unsigned int);
Result_t(int v, const std::string& s, const std::string& l);
Result_t(const Result_t& rhs);
const Result_t& operator=(const Result_t& rhs);
~Result_t();
const Result_t operator()(const std::string& message) const;
const Result_t operator()(const int& line, const char* filename) const;
const Result_t operator()(const std::string& message, const int& line, const char* filename) const;
inline bool operator==(const Result_t& rhs) const { return value == rhs.value; }
inline bool operator!=(const Result_t& rhs) const { return value != rhs.value; }
inline bool Success() const { return ! ( value < 0 ); }
inline bool Failure() const { return ( value < 0 ); }
inline int Value() const { return value; }
inline operator int() const { return value; }
inline const char* Label() const { return label.c_str(); }
inline operator const char*() const { return label.c_str(); }
inline const char* Symbol() const { return symbol.c_str(); }
inline const char* Message() const { return message.c_str(); }
};
KM_DECLARE_RESULT(FALSE, 1, "Successful but not true.");
KM_DECLARE_RESULT(OK, 0, "Success.");
KM_DECLARE_RESULT(FAIL, -1, "An undefined error was detected.");
KM_DECLARE_RESULT(PTR, -2, "An unexpected NULL pointer was given.");
KM_DECLARE_RESULT(NULL_STR, -3, "An unexpected empty string was given.");
KM_DECLARE_RESULT(ALLOC, -4, "Error allocating memory.");
KM_DECLARE_RESULT(PARAM, -5, "Invalid parameter.");
KM_DECLARE_RESULT(NOTIMPL, -6, "Unimplemented Feature.");
KM_DECLARE_RESULT(SMALLBUF, -7, "The given buffer is too small.");
KM_DECLARE_RESULT(INIT, -8, "The object is not yet initialized.");
KM_DECLARE_RESULT(NOT_FOUND, -9, "The requested file does not exist on the system.");
KM_DECLARE_RESULT(NO_PERM, -10, "Insufficient privilege exists to perform the operation.");
KM_DECLARE_RESULT(STATE, -11, "Object state error.");
KM_DECLARE_RESULT(CONFIG, -12, "Invalid configuration option detected.");
KM_DECLARE_RESULT(FILEOPEN, -13, "File open failure.");
KM_DECLARE_RESULT(BADSEEK, -14, "An invalid file location was requested.");
KM_DECLARE_RESULT(READFAIL, -15, "File read error.");
KM_DECLARE_RESULT(WRITEFAIL, -16, "File write error.");
KM_DECLARE_RESULT(ENDOFFILE, -17, "Attempt to read past end of file.");
KM_DECLARE_RESULT(FILEEXISTS, -18, "Filename already exists.");
KM_DECLARE_RESULT(NOTAFILE, -19, "Filename not found.");
KM_DECLARE_RESULT(UNKNOWN, -20, "Unknown result code.");
KM_DECLARE_RESULT(DIR_CREATE, -21, "Unable to create directory.");
KM_DECLARE_RESULT(NOT_EMPTY, -22, "Unable to delete non-empty directory.");
// 23-100 are reserved
} // namespace Kumu
//--------------------------------------------------------------------------------
// convenience macros
// Convenience macros for managing return values in predicates
# define KM_SUCCESS(v) (((v) < 0) ? 0 : 1)
# define KM_FAILURE(v) (((v) < 0) ? 1 : 0)
// Returns RESULT_PTR if the given argument is NULL.
// See Result_t above for an explanation of RESULT_* symbols.
# define KM_TEST_NULL(p) \
if ( (p) == 0 ) { \
return Kumu::RESULT_PTR(__LINE__, __FILE__); \
}
// Returns RESULT_PTR if the given argument is NULL. See Result_t
// in WaimeaCore for an explanation of RESULT_* symbols. It then assumes
// that the argument is a pointer to a string and returns
// RESULT_NULL_STR if the first character is '\0'.
//
# define KM_TEST_NULL_STR(p) \
KM_TEST_NULL(p); \
if ( (p)[0] == '\0' ) { \
return Kumu::RESULT_NULL_STR(__LINE__, __FILE__); \
}
// RESULT_STATE is ambiguous. Use these everywhere it is assigned to provide some context
#define KM_RESULT_STATE_TEST_IMPLICIT() \
if ( result == Kumu::RESULT_STATE ) { \
Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__); \
}
#define KM_RESULT_STATE_TEST_THIS(_this__r_) \
if ( _this__r_ == Kumu::RESULT_STATE ) { \
Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__); \
}
#define KM_RESULT_STATE_HERE() \
Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__);
namespace Kumu
{
// simple tracing mechanism
class DTrace_t
{
DTrace_t();
protected:
const char* m_Label;
Result_t* m_Watch;
int m_Line;
const char* m_File;
int m_Sequence;
public:
DTrace_t(const char* Label, Result_t* Watch, int Line, const char* File);
~DTrace_t();
};
}
#ifdef KM_TRACE
#define WDTRACE(l) DTrace_t __wl__Trace__((l), 0, __LINE__, __FILE__)
#define WDTRACER(l,r) DTrace_t __wl__Trace__((l), &(r), __LINE__, __FILE__)
#else
#define WDTRACE(l)
#define WDTRACER(l,r)
#endif
#endif // _KM_ERROR_H_
//
// end KM_error.h
//
|