1 /*
2  *
3  *  Copyright (C) 1994-2018, 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:  Gerd Ehlers, Andrew Hewett
17  *
18  *  Purpose: class DcmTag
19  *
20  */
21 
22 #include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
23 #include "dcmtk/dcmdata/dctag.h"
24 #include "dcmtk/dcmdata/dcerror.h"    /* for dcmdata error constants */
25 #include "dcmtk/dcmdata/dcdict.h"
26 #include "dcmtk/dcmdata/dcdicent.h"
27 #include "dcmtk/ofstd/ofstd.h"
28 
29 #define INCLUDE_CSTDIO
30 #define INCLUDE_CSTRING
31 #include "dcmtk/ofstd/ofstdinc.h"
32 
33 
DcmTag()34 DcmTag::DcmTag()
35   : vr(EVR_UNKNOWN),
36     tagName(NULL),
37     privateCreator(NULL),
38     errorFlag(EC_InvalidTag)
39 {
40 }
41 
DcmTag(const DcmTagKey & akey,const char * privCreator)42 DcmTag::DcmTag(const DcmTagKey& akey, const char *privCreator)
43   : DcmTagKey(akey),
44     vr(EVR_UNKNOWN),
45     tagName(NULL),
46     privateCreator(NULL),
47     errorFlag(EC_InvalidTag)
48 {
49     if (privCreator)
50         updatePrivateCreator(privCreator);
51     lookupVRinDictionary();
52 }
53 
DcmTag(Uint16 g,Uint16 e,const char * privCreator)54 DcmTag::DcmTag(Uint16 g, Uint16 e, const char *privCreator)
55   : DcmTagKey(g, e),
56     vr(EVR_UNKNOWN),
57     tagName(NULL),
58     privateCreator(NULL),
59     errorFlag(EC_InvalidTag)
60 {
61     if (privCreator)
62         updatePrivateCreator(privCreator);
63     lookupVRinDictionary();
64 }
65 
DcmTag(const DcmTagKey & akey,const DcmVR & avr)66 DcmTag::DcmTag(const DcmTagKey& akey, const DcmVR& avr)
67   : DcmTagKey(akey),
68     vr(avr),
69     tagName(NULL),
70     privateCreator(NULL),
71     errorFlag(EC_Normal)
72 {
73 }
74 
DcmTag(Uint16 g,Uint16 e,const DcmVR & avr)75 DcmTag::DcmTag(Uint16 g, Uint16 e, const DcmVR& avr)
76   : DcmTagKey(g, e),
77     vr(avr),
78     tagName(NULL),
79     privateCreator(NULL),
80     errorFlag(EC_Normal)
81 {
82 }
83 
DcmTag(const DcmTag & tag)84 DcmTag::DcmTag(const DcmTag& tag)
85   : DcmTagKey(tag),
86     vr(tag.vr),
87     tagName(NULL),
88     privateCreator(NULL),
89     errorFlag(tag.errorFlag)
90 {
91     updateTagName(tag.tagName);
92     updatePrivateCreator(tag.privateCreator);
93 }
94 
95 
96 // ********************************
97 
98 
~DcmTag()99 DcmTag::~DcmTag()
100 {
101     delete[] tagName;
102     delete[] privateCreator;
103 }
104 
105 
106 // ********************************
107 
108 
operator =(const DcmTag & tag)109 DcmTag& DcmTag::operator=(const DcmTag& tag)
110 {
111     if (this != &tag)
112     {
113         updateTagName(tag.tagName);
114         updatePrivateCreator(tag.privateCreator);
115         DcmTagKey::set(tag);
116         vr = tag.vr;
117         errorFlag = tag.errorFlag;
118     }
119     return *this;
120 }
121 
122 // ********************************
123 
lookupVRinDictionary()124 void DcmTag::lookupVRinDictionary()
125 {
126     const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
127     const DcmDictEntry *dictRef = globalDataDict.findEntry(*this, privateCreator);
128     if (dictRef)
129     {
130         vr = dictRef->getVR();
131         errorFlag = EC_Normal;
132     }
133     dcmDataDict.rdunlock();
134 }
135 
136 // ********************************
137 
138 
setVR(const DcmVR & avr)139 DcmVR DcmTag::setVR(const DcmVR& avr)    // resolve ambiguous VR
140 {
141     vr = avr;
142 
143     if (vr.getEVR() == EVR_UNKNOWN)
144     {
145         errorFlag = EC_InvalidVR;
146     } else {
147         errorFlag = EC_Normal;
148     }
149     return vr;
150 }
151 
152 
getTagName()153 const char *DcmTag::getTagName()
154 {
155     if (tagName)
156         return tagName;
157 
158     const char *newTagName = NULL;
159     const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock();
160     const DcmDictEntry *dictRef = globalDataDict.findEntry(*this, privateCreator);
161     if (dictRef)
162         newTagName=dictRef->getTagName();
163     if (newTagName == NULL)
164         newTagName = DcmTag_ERROR_TagName;
165     updateTagName(newTagName);
166     dcmDataDict.rdunlock();
167 
168     if (tagName)
169         return tagName;
170     return DcmTag_ERROR_TagName;
171 }
172 
isSignable() const173 OFBool DcmTag::isSignable() const
174 {
175     OFBool result = isSignableTag();
176     if (result)
177         result = !isUnknownVR();
178     return result;
179 }
180 
isUnknownVR() const181 OFBool DcmTag::isUnknownVR() const
182 {
183     OFBool result = OFFalse;
184     switch (vr.getValidEVR()) // this is the VR we're going to write in explicit VR
185     {
186         case EVR_UNKNOWN:
187         case EVR_UNKNOWN2B:
188         case EVR_UN:
189             result = OFTrue;
190             break;
191         default:
192             /* nothing */
193             break;
194     }
195     return result;
196 }
197 
198 
findTagFromName(const char * name,DcmTag & value)199 OFCondition DcmTag::findTagFromName(const char *name, DcmTag &value)
200 {
201     OFCondition result = EC_IllegalParameter;
202     /* check parameters first */
203     if ((name != NULL) && (strlen(name) > 0))
204     {
205         result = EC_Normal;
206         unsigned int grp = 0xffff;
207         unsigned int elm = 0xffff;
208         /* check whether tag name has format 'gggg,eeee' */
209         if (sscanf(name, "%x,%x", &grp, &elm) == 2)
210         {
211             /* store resulting tag value */
212             value.set(OFstatic_cast(Uint16, grp), OFstatic_cast(Uint16, elm));
213             value.lookupVRinDictionary();
214         } else {
215             /* it is a name: look up in the dictionary */
216             const DcmDataDictionary &globalDataDict = dcmDataDict.rdlock();
217             const DcmDictEntry *dicent = globalDataDict.findEntry(name);
218             /* store resulting tag value */
219             if (dicent != NULL)
220             {
221               value.set(dicent->getKey());
222               value.setVR(dicent->getVR());
223             }
224             else
225                 result = EC_TagNotFound;
226             dcmDataDict.rdunlock();
227         }
228     }
229     return result;
230 }
231 
232 
getPrivateCreator() const233 const char* DcmTag::getPrivateCreator() const
234 {
235     return privateCreator;
236 }
237 
setPrivateCreator(const char * privCreator)238 void DcmTag::setPrivateCreator(const char *privCreator)
239 {
240     // a new private creator code probably changes the name
241     // of the tag. Enforce new dictionary lookup the next time
242     // getTagName() is called.
243     updateTagName(NULL);
244     updatePrivateCreator(privCreator);
245 }
246 
updateTagName(const char * c)247 void DcmTag::updateTagName(const char *c)
248 {
249     delete[] tagName;
250     if (c)
251     {
252         size_t buflen = strlen(c) + 1;
253         tagName = new char[buflen];
254         if (tagName)
255             OFStandard::strlcpy(tagName, c, buflen);
256     } else
257         tagName = NULL;
258 }
259 
updatePrivateCreator(const char * c)260 void DcmTag::updatePrivateCreator(const char *c)
261 {
262     delete[] privateCreator;
263     if (c)
264     {
265         size_t buflen = strlen(c) + 1;
266         privateCreator = new char[buflen];
267         if (privateCreator)
268             OFStandard::strlcpy(privateCreator, c, buflen);
269     } else
270         privateCreator = NULL;
271 }
272