Coverage Report

Created: 2026-06-30 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/dcmtk-install/include/dcmtk/dcmdata/dcdict.h
Line
Count
Source
1
/*
2
 *
3
 *  Copyright (C) 1994-2024, 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:  dcmdata
15
 *
16
 *  Author:  Andrew Hewett
17
 *
18
 *  Purpose: Interface for loadable DICOM data dictionary
19
 *
20
 */
21
22
23
#ifndef DCMDICT_H
24
#define DCMDICT_H
25
26
#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
27
28
#include "dcmtk/ofstd/ofthread.h"
29
#include "dcmtk/dcmdata/dchashdi.h"
30
31
/// maximum length of a line in the loadable DICOM dictionary
32
#define DCM_MAXDICTLINESIZE     2048
33
34
/// maximum number of fields per entry in the loadable DICOM dictionary
35
#define DCM_MAXDICTFIELDS       6
36
37
/// environment variable pointing to the data dictionary file
38
#define DCM_DICT_ENVIRONMENT_VARIABLE   "DCMDICTPATH"
39
40
#ifndef DCM_DICT_DEFAULT_PATH
41
/*
42
** The default dictionary path is system dependent.  It should
43
** be defined in a configuration file included from "osconfig.h"
44
*/
45
#error "DCM_DICT_DEFAULT_PATH is not defined via osconfig.h"
46
#endif /* !DCM_DICT_DEFAULT_PATH */
47
48
#ifndef ENVIRONMENT_PATH_SEPARATOR
49
#define ENVIRONMENT_PATH_SEPARATOR '\n' /* at least define something unlikely */
50
#endif
51
52
/*
53
** Loading of default dictionary:
54
**  DCM_DICT_DEFAULT_USE_NONE: Do not load any default dictionary on startup
55
**  DCM_DICT_DEFAULT_USE_BUILTIN: Load builtin dictionary on startup
56
**  DCM_DICT_DEFAULT_USE_EXTERNAL: Load external (i.e. file-based) dictionary on startup
57
*/
58
#define DCM_DICT_DEFAULT_USE_NONE     0
59
#define DCM_DICT_DEFAULT_USE_BUILTIN  1
60
#define DCM_DICT_DEFAULT_USE_EXTERNAL 2
61
62
63
/** this class implements a loadable DICOM Data Dictionary
64
 */
65
class DCMTK_DCMDATA_EXPORT DcmDataDictionary
66
{
67
public:
68
69
    /** constructor
70
     *  @param loadBuiltin flag indicating if a built-in data dictionary
71
     *    (if any) should be loaded.
72
     *  @param loadExternal flag indicating if an external data dictionary
73
     *    should be read from file.
74
     */
75
    DcmDataDictionary(OFBool loadBuiltin, OFBool loadExternal);
76
77
    /// destructor
78
    ~DcmDataDictionary();
79
80
    /** checks if a data dictionary is loaded (excluding the skeleton dictionary)
81
     *  @return true if loaded, false if no dictionary is present
82
     */
83
    OFBool isDictionaryLoaded() const { return dictionaryLoaded; }
84
85
    /// returns the number of normal (non-repeating) tag entries
86
    int numberOfNormalTagEntries() const { return hashDict.size(); }
87
88
    /// returns the number of repeating groups tag entries
89
    int numberOfRepeatingTagEntries() const { return OFstatic_cast(int, repDict.size()); }
90
91
    /** returns the number of dictionary entries that were loaded
92
     *  either from file or from a built-in dictionary or both.
93
     */
94
    int numberOfEntries() const
95
        { return numberOfNormalTagEntries()
96
              + numberOfRepeatingTagEntries() - skeletonCount; }
97
98
    /** returns the number of skeleton entries. The skeleton is a collection
99
     *  of dictionary entries which are always present, even if neither internal
100
     *  nor external dictionary have been loaded. It contains very basic
101
     *  things like item delimitation and sequence delimitation.
102
     */
103
0
    int numberOfSkeletonEntries() const { return skeletonCount; }
104
105
    /** reload data dictionaries. First, all dictionary entries are deleted.
106
     *  @param loadBuiltin flag indicating if a built-in data dictionary
107
     *    (if any) should be loaded.
108
     *  @param loadExternal flag indicating if an external data dictionary
109
     *    should be read from file.
110
     *  @return true if reload was successful, false if an error occurred
111
     */
112
    OFBool reloadDictionaries(OFBool loadBuiltin, OFBool loadExternal);
113
114
    /** load a particular dictionary from file.
115
     *  @param fileName filename
116
     *  @param errorIfAbsent causes the method to return false if the file
117
     *     cannot be opened
118
     *  @return false if the file contains a parse error or if the file could
119
     *     not be opened and errorIfAbsent was set, true otherwise.
120
     */
121
    OFBool loadDictionary(const char* fileName, OFBool errorIfAbsent = OFTrue);
122
123
    /** dictionary lookup for the given tag key and private creator identifier.
124
     *  First, the normal tags data dictionary is searched.  If not found, the
125
     *  repeating groups data dictionary is searched.
126
     *  @param key tag key to search for
127
     *  @param privCreator private creator identifier, may be NULL
128
     */
129
    const DcmDictEntry* findEntry(const DcmTagKey& key, const char *privCreator) const;
130
131
    /** dictionary lookup for the given attribute name.
132
     *  First, the normal tags data dictionary is searched.  If not found, the
133
     *  repeating groups data dictionary is searched.
134
     *  Mainly considers standard attributes.  Private attributes are also
135
     *  searched, but without their associated private creator identifier.
136
     *  @param name attribute name to search for
137
     */
138
    const DcmDictEntry* findEntry(const char *name) const;
139
140
    /// deletes all dictionary entries
141
    void clear();
142
143
    /** adds an entry to the dictionary.  Must be allocated via new.
144
     *  The entry becomes the property of the dictionary and will be
145
     *  deallocated (via delete) upon clear() or dictionary destruction.
146
     *  If an equivalent entry already exists it will be replaced by
147
     *  the new entry and the old entry deallocated (via delete).
148
     *  @param entry pointer to new entry
149
     */
150
    void addEntry(DcmDictEntry* entry);
151
152
    /* Iterators to access the normal and the repeating entries */
153
154
    /// returns an iterator to the start of the normal (non-repeating) dictionary
155
0
    DcmHashDictIterator normalBegin() { return hashDict.begin(); }
156
157
    /// returns an iterator to the end of the normal (non-repeating) dictionary
158
0
    DcmHashDictIterator normalEnd() { return hashDict.end(); }
159
160
    /// returns an iterator to the start of the repeating groups data dictionary
161
0
    DcmDictEntryListIterator repeatingBegin() { return repDict.begin(); }
162
163
    /// returns an iterator to the end of the repeating groups data dictionary
164
0
    DcmDictEntryListIterator repeatingEnd() { return repDict.end(); }
165
166
private:
167
168
    /** private undefined assignment operator
169
     */
170
    DcmDataDictionary &operator=(const DcmDataDictionary &);
171
172
    /** private undefined copy constructor
173
     */
174
    DcmDataDictionary(const DcmDataDictionary &);
175
176
    /** loads external dictionaries defined via environment variables
177
     *  @return true if successful
178
     */
179
    OFBool loadExternalDictionaries();
180
181
    /** loads a builtin (compiled) data dictionary.
182
     *  Depending on which code is in use, this function may not do anything.
183
     */
184
    void loadBuiltinDictionary();
185
186
    /** loads the skeleton dictionary (the bare minimum needed to run)
187
     *  @return true if successful
188
     */
189
    OFBool loadSkeletonDictionary();
190
191
    /** looks up the given directory entry in the two dictionaries.
192
     *  @param entry the entry to look up
193
     *  @return pointer to entry if found, NULL otherwise
194
     */
195
    const DcmDictEntry* findEntry(const DcmDictEntry& entry) const;
196
197
    /** deletes the given entry from either dictionary
198
     * @param entry the entry to delete
199
     */
200
    void deleteEntry(const DcmDictEntry& entry);
201
202
203
    /** dictionary of normal tags
204
     */
205
    DcmHashDict hashDict;
206
207
    /** dictionary of repeating groups tags
208
     */
209
    DcmDictEntryList repDict;
210
211
    /** the number of skeleton entries
212
     */
213
    int skeletonCount;
214
215
    /** is a dictionary loaded (more than skeleton)
216
     */
217
    OFBool dictionaryLoaded;
218
219
};
220
221
222
/** global singleton DICOM dictionary that is used by DCMTK in order to lookup
223
 *  attribute VR, tag names and so on.  The dictionary is internally populated
224
 *  on first use, if the user accesses it via rdlock() or wrlock().  The
225
 *  dictionary allows safe read (shared) and write (exclusive) access from
226
 *  multiple threads in parallel.
227
 */
228
class DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary
229
{
230
public:
231
  /** constructor.
232
   */
233
  GlobalDcmDataDictionary();
234
235
  /** destructor
236
   */
237
  ~GlobalDcmDataDictionary();
238
239
  /** acquires a read lock and returns a const reference to the dictionary.
240
   *  @return const reference to dictionary
241
   */
242
  const DcmDataDictionary& rdlock();
243
244
  /** acquires a write lock and returns a non-const reference to the dictionary.
245
   *  @return non-const reference to dictionary
246
   */
247
  DcmDataDictionary& wrlock();
248
249
  /** unlocks the read lock which must have been acquired previously.
250
   */
251
  void rdunlock();
252
253
  /** unlocks the write lock which must have been acquired previously.
254
   */
255
  void wrunlock();
256
257
  /** checks if a data dictionary has been loaded. This method acquires and
258
   *  releases a read lock. It must not be called with another lock on the
259
   *  dictionary being held by the calling thread.
260
   *  @return OFTrue if dictionary has been loaded, OFFalse otherwise.
261
   */
262
  OFBool isDictionaryLoaded();
263
264
  /** erases the contents of the dictionary. This method acquires and
265
   *  releases a write lock. It must not be called with another lock on the
266
   *  dictionary being held by the calling thread.  This method is intended
267
   *  as a help for debugging memory leaks.
268
   */
269
  void clear();
270
271
private:
272
  /** private undefined assignment operator
273
   */
274
  GlobalDcmDataDictionary &operator=(const GlobalDcmDataDictionary &);
275
276
  /** private undefined copy constructor
277
   */
278
  GlobalDcmDataDictionary(const GlobalDcmDataDictionary &);
279
280
  /** create the data dictionary instance for this class. Used for first
281
   * initialization.  The caller must not have dataDictLock locked.
282
   */
283
  void createDataDict();
284
285
  /** the data dictionary managed by this class
286
   */
287
  DcmDataDictionary *dataDict;
288
289
#ifdef WITH_THREADS
290
  /** the read/write lock used to protect access from multiple threads
291
   *  @remark this member is only available if DCMTK is compiled with thread
292
   *  support enabled.
293
   */
294
  OFReadWriteLock dataDictLock;
295
#endif
296
};
297
298
299
/** The Global DICOM Data Dictionary.
300
 *  Will be created before main() starts and gets populated on its first use.
301
 *  Tries to load a builtin data dictionary (if compiled in).
302
 *  Tries to load data dictionaries from files specified by the DCMDICTPATH
303
 *  environment variable.  If this environment variable does not exist then a
304
 *  default file is loaded (if it exists).
305
 *  It is possible that no data dictionary gets loaded.  This is likely to
306
 *  cause unexpected behavior in the dcmdata toolkit classes.
307
 */
308
extern DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary dcmDataDict;
309
310
#endif