/work/dcmtk-install/include/dcmtk/ofstd/ofcond.h
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (C) 2001-2025, OFFIS e.V. |
4 | | * All rights reserved. See COPYRIGHT file for details. |
5 | | * |
6 | | * This software and supporting documentation were developed by |
7 | | * |
8 | | * OFFIS e.V. |
9 | | * R&D Division Health |
10 | | * Escherweg 2 |
11 | | * D-26121 Oldenburg, Germany |
12 | | * |
13 | | * |
14 | | * Module: ofstd |
15 | | * |
16 | | * Author: Marco Eichelberg, Uli Schlachter |
17 | | * |
18 | | * Purpose: class OFCondition and helper classes |
19 | | * |
20 | | */ |
21 | | |
22 | | |
23 | | #ifndef OFCOND_H |
24 | | #define OFCOND_H |
25 | | |
26 | | #include "dcmtk/config/osconfig.h" /* include OS specific configuration first */ |
27 | | |
28 | | #include "dcmtk/ofstd/oftypes.h" /* for class OFBool */ |
29 | | #include "dcmtk/ofstd/ofstring.h" /* for class OFString */ |
30 | | #include "dcmtk/ofstd/ofcast.h" |
31 | | #include "dcmtk/ofstd/ofdiag.h" |
32 | | #include <cstring> |
33 | | #include <cstdlib> /* for free() */ |
34 | | |
35 | | // include this file in doxygen documentation |
36 | | |
37 | | /** @file ofcond.h |
38 | | * @brief Error handling, codes and strings for all modules |
39 | | */ |
40 | | |
41 | | |
42 | | /** this enumeration describes the return status of an operation. |
43 | | */ |
44 | | enum OFStatus |
45 | | { |
46 | | /// no error, operation has completed successfully |
47 | | OF_ok, |
48 | | |
49 | | /// operation has not completed successfully |
50 | | OF_error, |
51 | | |
52 | | /// application failure |
53 | | OF_failure |
54 | | }; |
55 | | |
56 | | |
57 | | /** A constant data structure which can be used for an OFCondition. |
58 | | * The reason this exists is because we need a trivially constructible class |
59 | | * (= needs no constructor to be run before being usable) that can hold static |
60 | | * condition codes. |
61 | | */ |
62 | | struct DCMTK_OFSTD_EXPORT OFConditionConst |
63 | | { |
64 | | |
65 | | /// module identifier. 0 is reserved for global codes. |
66 | | unsigned short theModule; |
67 | | |
68 | | /// status code that is unique for each module |
69 | | unsigned short theCode; |
70 | | |
71 | | /// condition status enum |
72 | | OFStatus theStatus; |
73 | | |
74 | | /// error text |
75 | | const char *theText; |
76 | | |
77 | | /** comparison operator. Compares status, code and module |
78 | | * but not error text. |
79 | | * @param arg error to compare to |
80 | | * @return true if equal, false otherwise |
81 | | */ |
82 | | inline OFBool operator==(const OFConditionConst& arg) const |
83 | | { |
84 | | return ((theStatus == arg.theStatus) && (theCode == arg.theCode) && (theModule == arg.theModule)); |
85 | | } |
86 | | |
87 | | /** comparison operator. Compares status, code and module |
88 | | * but not error text. |
89 | | * @param arg error to compare to |
90 | | * @return true if equal, false otherwise |
91 | | */ |
92 | | inline OFBool operator!=(const OFConditionConst& arg) const |
93 | | { |
94 | | return !(*this == arg); |
95 | | } |
96 | | |
97 | | }; |
98 | | |
99 | | |
100 | | /** @name global condition constants. |
101 | | * All constants defined here use module number 0, which is reserved for |
102 | | * global definitions. Other constants are defined in other modules. |
103 | | */ |
104 | | ///@{ |
105 | | |
106 | | /// condition constant: successful completion |
107 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_Normal; |
108 | | /// condition constant: error, function called with illegal parameters |
109 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IllegalParameter; |
110 | | /// condition constant: failure, memory exhausted |
111 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_MemoryExhausted; |
112 | | |
113 | | /// condition constant: error, no character encoding library available |
114 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_NoEncodingLibrary; |
115 | | /// condition constant: error, no character encoding selected |
116 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_NoEncodingSelected; |
117 | | |
118 | | /// condition constant: error, could not create temporary file |
119 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_CouldNotCreateTemporaryFile; |
120 | | /// condition constant: error, invalid filename |
121 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_InvalidFilename; |
122 | | /// condition constant: error, could not generate filename |
123 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_CouldNotGenerateFilename; |
124 | | |
125 | | /// condition constant: error, directory does not exist |
126 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_DirectoryDoesNotExist; |
127 | | /// condition constant: error, directory is not writable |
128 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_DirectoryNotWritable; |
129 | | /// condition constant: error, could not generate directory name |
130 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_CouldNotGenerateDirectoryName; |
131 | | /// condition constant: error, call to setuid() failed |
132 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_setuidFailed; |
133 | | |
134 | | /// condition constant: error, function not yet implemented |
135 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_NotYetImplemented; |
136 | | |
137 | | /// status code constant: error, cannot open character encoding |
138 | | extern DCMTK_OFSTD_EXPORT const unsigned short EC_CODE_CannotOpenEncoding; |
139 | | /// status code constant: error, cannot close character encoding |
140 | | extern DCMTK_OFSTD_EXPORT const unsigned short EC_CODE_CannotCloseEncoding; |
141 | | /// status code constant: error, cannot convert character encoding |
142 | | extern DCMTK_OFSTD_EXPORT const unsigned short EC_CODE_CannotConvertEncoding; |
143 | | /// status code constant: error, cannot control character encoding converter |
144 | | extern DCMTK_OFSTD_EXPORT const unsigned short EC_CODE_CannotControlConverter; |
145 | | /// status code constant: error, cannot create directory |
146 | | extern DCMTK_OFSTD_EXPORT const unsigned short EC_CODE_CannotCreateDirectory; |
147 | | |
148 | | /// condition constant: error, IPC message queue already initialized |
149 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCMessageQueueExists; |
150 | | /// condition constant: error, IPC message queue not initialized |
151 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCMessageNoQueue; |
152 | | /// condition constant: error, IPC message queue operation failed |
153 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCMessageQueueFailure; |
154 | | /// condition constant: error, IPC message queue empty |
155 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCMessageQueueEmpty; |
156 | | /// condition constant: error, IPC message empty (zero length) |
157 | | extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCEmptyMessage; |
158 | | |
159 | | ///@} |
160 | | |
161 | | |
162 | | /** use this macro for creating static OFCondition instances. Instead of an |
163 | | * OFCondition instance which needs a constructor, an instance of |
164 | | * OFConditionConst is created. This avoids the problem of static initializers |
165 | | * (and deinitializers) being executed in undefined order (some other static |
166 | | * initializer might want to use this OFCondition / OFConditionConst instance). |
167 | | */ |
168 | | #define makeOFConditionConst(name, module, code, status, text) \ |
169 | | const OFConditionConst name = { (module), (code), (status), (text) } |
170 | | |
171 | | |
172 | | /** General purpose class for condition codes. Objects of this class can be |
173 | | * efficiently passed by value. To make this possible, the contained string is |
174 | | * not copied when possible. |
175 | | */ |
176 | | class DCMTK_OFSTD_EXPORT OFCondition |
177 | | { |
178 | | public: |
179 | | |
180 | | /** constructor for condition code with text |
181 | | * @param aModule module identifier. 0 is reserved for global codes, |
182 | | * other constants are defined elsewhere. |
183 | | * @param aCode status code that is unique for each module |
184 | | * @param aStatus condition status enum |
185 | | * @param aText error text. |
186 | | */ |
187 | | OFCondition(unsigned short aModule, unsigned short aCode, OFStatus aStatus, const char *aText) |
188 | | : theCondition() |
189 | | , ownsText(OFTrue) |
190 | | { |
191 | | theCondition.theModule = aModule; |
192 | | theCondition.theCode = aCode; |
193 | | theCondition.theStatus = aStatus; |
194 | | /* Be nice when someone dares to pass in NULL */ |
195 | | if (aText != NULL) { |
196 | | theCondition.theText = strdup(aText); |
197 | | ownsText = OFTrue; |
198 | | } else { |
199 | | theCondition.theText = ""; |
200 | | ownsText = OFFalse; |
201 | | } |
202 | | } |
203 | | |
204 | | /** constructor for condition code from constant data |
205 | | * @param aConst OFConditionConst to use |
206 | | */ |
207 | | OFCondition(const OFConditionConst& aConst = EC_Normal) |
208 | | : theCondition(aConst) |
209 | | , ownsText(OFFalse) |
210 | | { |
211 | | } |
212 | | |
213 | | /** copy constructor |
214 | | * @param arg OFCondition to copy |
215 | | */ |
216 | | OFCondition(const OFCondition& arg) |
217 | | : theCondition(arg.theCondition) |
218 | | , ownsText(arg.ownsText) |
219 | | { |
220 | | // Do we need our own copy of the text? |
221 | | if (ownsText) |
222 | | { |
223 | | theCondition.theText = strdup(theCondition.theText); |
224 | | } |
225 | | } |
226 | | |
227 | | // suppress spurious gcc 12 warning about use-after-free. |
228 | | // this is a known bug in gcc. |
229 | | #include DCMTK_DIAGNOSTIC_PUSH |
230 | | #include DCMTK_DIAGNOSTIC_IGNORE_USE_AFTER_FREE |
231 | | |
232 | | /// destructor |
233 | | ~OFCondition() |
234 | 128 | { |
235 | 128 | if (ownsText) |
236 | 0 | { |
237 | 0 | free(OFconst_cast(char *, theCondition.theText)); // cast away const |
238 | 0 | } |
239 | 128 | } |
240 | | |
241 | | #include DCMTK_DIAGNOSTIC_POP |
242 | | |
243 | | /** copy assignment operator |
244 | | * @param arg The OFCondition instance to copy |
245 | | * @return *this |
246 | | */ |
247 | | OFCondition& operator=(const OFCondition& arg) |
248 | | { |
249 | | if (&arg != this) |
250 | | { |
251 | | if (ownsText) |
252 | | { |
253 | | free(OFconst_cast(char *, theCondition.theText)); // cast away const |
254 | | } |
255 | | theCondition = arg.theCondition; |
256 | | ownsText = arg.ownsText; |
257 | | if (ownsText) |
258 | | { |
259 | | theCondition.theText = strdup(arg.theCondition.theText); |
260 | | } |
261 | | } |
262 | | return *this; |
263 | | } |
264 | | |
265 | | /** get the module identifier for this object. |
266 | | * @return the module identifier for this object. |
267 | | * @see code() |
268 | | */ |
269 | | inline unsigned short module() const |
270 | 0 | { |
271 | 0 | return theCondition.theModule; |
272 | 0 | } |
273 | | |
274 | | /** get the status code identifier for this object. This uniquely identifies |
275 | | * the error code within the module. |
276 | | * @return the status code identifier for this object. |
277 | | * @see module() |
278 | | */ |
279 | | inline unsigned short code() const |
280 | 0 | { |
281 | 0 | return theCondition.theCode; |
282 | 0 | } |
283 | | |
284 | | /** get the error status this object represents. |
285 | | * @return the status for this object. |
286 | | */ |
287 | | inline OFStatus status() const |
288 | 0 | { |
289 | 0 | return theCondition.theStatus; |
290 | 0 | } |
291 | | |
292 | | /** get a human readable text representation of this error code. The returned |
293 | | * string is owned by this OFCondition instance and must not be modified or |
294 | | * freed. |
295 | | * @return the error message text for this object. |
296 | | */ |
297 | | inline const char *text() const |
298 | | { |
299 | | return theCondition.theText; |
300 | | } |
301 | | |
302 | | /** internal function only, don't use yourself. |
303 | | * @return an equivalent OFConditionConst for this object. |
304 | | */ |
305 | | inline const OFConditionConst& condition() const |
306 | | { |
307 | | return theCondition; |
308 | | } |
309 | | |
310 | | /** check if the status is OK. |
311 | | * @return true if status is OK, else false |
312 | | */ |
313 | | inline OFBool good() const |
314 | 192 | { |
315 | 192 | OFStatus s = theCondition.theStatus; |
316 | 192 | return (s == OF_ok); |
317 | 192 | } |
318 | | |
319 | | /** check if the status is not OK, i.e.\ error or failure. |
320 | | * @return true if status is not OK, else false |
321 | | */ |
322 | | inline OFBool bad() const |
323 | | { |
324 | | OFStatus s = theCondition.theStatus; |
325 | | return (s != OF_ok); |
326 | | } |
327 | | |
328 | | #ifdef OFCONDITION_IMPLICIT_BOOL_CONVERSION |
329 | | /* Implicit conversion from OFCondition to bool might |
330 | | * not always be a good idea since it can hide unwanted constructs. |
331 | | * Therefore, we disable this operator by default. |
332 | | * @remark this method is only available if DCMTK is compiled with |
333 | | * implicit conversion from OFCondition to bool being enabled (see macro |
334 | | * OFCONDITION_IMPLICIT_BOOL_CONVERSION) |
335 | | */ |
336 | | |
337 | | /** conversion operator to bool. |
338 | | * @return true if status is OK, false otherwise |
339 | | */ |
340 | | inline operator OFBool() const |
341 | | { |
342 | | return good(); |
343 | | } |
344 | | #endif |
345 | | |
346 | | /** comparison operator. Compares status, code and module |
347 | | * but not error text. |
348 | | * @param arg error to compare to |
349 | | * @return true if equal, false otherwise |
350 | | */ |
351 | | inline OFBool operator==(const OFCondition& arg) const |
352 | 0 | { |
353 | 0 | return theCondition == arg.theCondition; |
354 | 0 | } |
355 | | |
356 | | /** comparison operator. Compares status, code and module |
357 | | * but not error text. |
358 | | * @param arg error to compare to |
359 | | * @return true if equal, false otherwise |
360 | | */ |
361 | | inline OFBool operator!=(const OFCondition& arg) const |
362 | 0 | { |
363 | 0 | return theCondition != arg.theCondition; |
364 | 0 | } |
365 | | |
366 | | private: |
367 | | |
368 | | /// The condition information |
369 | | OFConditionConst theCondition; |
370 | | |
371 | | /// Does theCondition.theText point to our own heap string which must be freed? |
372 | | OFBool ownsText; |
373 | | |
374 | | }; |
375 | | |
376 | | |
377 | | /** returns true if lhs refers to the same OFCondition as rhs |
378 | | * @param lhs left-hand side condition |
379 | | * @param rhs right-hand side condition |
380 | | * @return true if OFCondition::operator==() returns true |
381 | | */ |
382 | | inline OFBool operator== (const OFConditionConst& lhs, const OFCondition& rhs) |
383 | | { |
384 | | return lhs == rhs.condition(); |
385 | | } |
386 | | |
387 | | /** returns true if lhs refers to the same OFCondition as rhs |
388 | | * @param lhs left-hand side condition |
389 | | * @param rhs right-hand side condition |
390 | | * @return true if OFCondition::operator==() returns true |
391 | | */ |
392 | | inline OFBool operator== (const OFCondition& lhs, const OFConditionConst& rhs) |
393 | | { |
394 | | return lhs.condition() == rhs; |
395 | | } |
396 | | |
397 | | /** returns true if lhs refers to a different OFCondition as rhs |
398 | | * @param lhs left-hand side condition |
399 | | * @param rhs right-hand side condition |
400 | | * @return true if OFCondition::operator!=() returns true |
401 | | */ |
402 | | inline OFBool operator!= (const OFConditionConst& lhs, const OFCondition& rhs) |
403 | 0 | { |
404 | 0 | return lhs != rhs.condition(); |
405 | 0 | } |
406 | | |
407 | | /** returns true if lhs refers to a different OFCondition as rhs |
408 | | * @param lhs left-hand side condition |
409 | | * @param rhs right-hand side condition |
410 | | * @return true if OFCondition::operator!=() returns true |
411 | | */ |
412 | | inline OFBool operator!= (const OFCondition& lhs, const OFConditionConst& rhs) |
413 | | { |
414 | | return lhs.condition() != rhs; |
415 | | } |
416 | | |
417 | | |
418 | | /** this macro is a shortcut for creating user-specific error messages. |
419 | | */ |
420 | | #define makeOFCondition(A, B, C, D) OFCondition((A), (B), (C), (D)) |
421 | | |
422 | | |
423 | | #endif |