Coverage Report

Created: 2026-06-05 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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