1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/09/06 15:28:49 $
7 Version: $Revision: 1.59 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
18 #include "gdcmDocEntrySet.h"
20 #include "gdcmDebug.h"
21 #include "gdcmCommon.h"
22 #include "gdcmDictSet.h"
23 #include "gdcmGlobal.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmSeqEntry.h"
26 #include "gdcmValEntry.h"
27 #include "gdcmBinEntry.h"
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 DocEntrySet::DocEntrySet()
38 //-----------------------------------------------------------------------------
41 * \brief Get the "std::string representable" value of the Dicom entry
42 * @param group Group number of the searched tag.
43 * @param elem Element number of the searched tag.
44 * @return Corresponding element value when it exists,
45 * and the string GDCM_UNFOUND otherwise.
47 std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
49 ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
51 return entry->GetValue();
56 * \brief Gets (from Header) a 'non string' element value
57 * @param group group number of the Entry
58 * @param elem element number of the Entry
59 * @return Pointer to the 'non string' area
61 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem)
63 BinEntry *entry = GetBinEntry(group, elem);
65 return entry->GetBinArea();
70 * \brief Return the value of the BinEntry if it's "std::string representable"
71 * @param group Group number of the searched tag.
72 * @param elem Element number of the searched tag.
73 * @return Corresponding element value when it's "std::string representable"
74 * and the string GDCM_NOTASCII otherwise.
76 std::string DocEntrySet::GetEntryForcedAsciiValue(uint16_t group, uint16_t elem)
78 DocEntry *d = GetDocEntry(group,elem);
82 if (ValEntry *v = dynamic_cast<ValEntry *>(d))
85 if (BinEntry *b = dynamic_cast<BinEntry *>(d))
87 uint8_t *a = b->GetBinArea();
89 return GDCM_NOTLOADED;
90 // TODO : unify those two methods.
91 if (Util::IsCleanArea(a, b->GetLength()) )
92 return Util::CreateCleanString(a, b->GetLength());
98 * \brief Searches within Header Entries (Dicom Elements) parsed with
99 * the public and private dictionaries
100 * for the value length of a given tag..
101 * @param group Group number of the searched tag.
102 * @param elem Element number of the searched tag.
103 * @return Corresponding element length; -2 if not found
105 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
107 DocEntry *entry = GetDocEntry(group, elem);
109 return entry->GetLength();
114 * \brief Searches within Header Entries (Dicom Elements) parsed with
115 * the public [and private dictionaries]
116 * for the element value representation of a given tag..
117 * Obtaining the VR (Value Representation) might be needed by caller
118 * to convert the string typed content to caller's native type
119 * (think of C++ vs Python). The VR is actually of a higher level
120 * of semantics than just the native C++ type.
121 * @param group Group number of the searched tag.
122 * @param elem Element number of the searched tag.
123 * @return Corresponding element value representation when it exists,
124 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
126 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
128 DocEntry *entry = GetDocEntry(group, elem);
130 return entry->GetVR();
135 * \brief Same as \ref Document::GetDocEntry except it only
136 * returns a result when the corresponding entry is of type
138 * @param group Group number of the searched Dicom Element
139 * @param elem Element number of the searched Dicom Element
140 * @return When present, the corresponding ValEntry.
142 ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
144 DocEntry *currentEntry = GetDocEntry(group, elem);
148 return dynamic_cast<ValEntry*>(currentEntry);
152 * \brief Same as \ref Document::GetDocEntry except it only
153 * returns a result when the corresponding entry is of type
155 * @param group Group number of the searched Dicom Element
156 * @param elem Element number of the searched Dicom Element
157 * @return When present, the corresponding BinEntry.
159 BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
161 DocEntry *currentEntry = GetDocEntry(group, elem);
164 gdcmWarningMacro( "No corresponding BinEntry " << std::hex << group <<
169 return dynamic_cast<BinEntry*>(currentEntry);
173 * \brief Same as \ref Document::GetDocEntry except it only
174 * returns a result when the corresponding entry is of type
176 * @param group Group number of the searched Dicom Element
177 * @param elem Element number of the searched Dicom Element
178 * @return When present, the corresponding SeqEntry.
180 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
182 DocEntry *currentEntry = GetDocEntry(group, elem);
185 gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
190 return dynamic_cast<SeqEntry*>(currentEntry);
194 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
195 * through it's (group, element) and modifies it's content with
197 * @param content new value (string) to substitute with
198 * @param group group number of the Dicom Element to modify
199 * @param elem element number of the Dicom Element to modify
201 bool DocEntrySet::SetValEntry(std::string const &content,
202 uint16_t group, uint16_t elem)
204 ValEntry *entry = GetValEntry(group, elem);
207 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
208 "," << elem << " element (try promotion first).");
211 return SetValEntry(content,entry);
215 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
216 * through it's (group, element) and modifies it's content with
218 * @param content new value (void* -> uint8_t*) to substitute with
219 * @param lgth new value length
220 * @param group group number of the Dicom Element to modify
221 * @param elem element number of the Dicom Element to modify
223 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth,
224 uint16_t group, uint16_t elem)
226 BinEntry *entry = GetBinEntry(group, elem);
229 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
230 "," << elem << " element (try promotion first).");
234 return SetBinEntry(content,lgth,entry);
238 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
239 * and modifies it's content with the given value.
240 * @param content new value (string) to substitute with
241 * @param entry Entry to be modified
243 bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
247 entry->SetValue(content);
254 * \brief Accesses an existing BinEntry (i.e. a Dicom Element)
255 * and modifies it's content with the given value.
256 * @param content new value (void* -> uint8_t*) to substitute with
257 * @param entry Entry to be modified
258 * @param lgth new value length
260 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
264 entry->SetBinArea(content);
265 entry->SetLength(lgth);
266 entry->SetValue(GDCM_BINLOADED);
273 * \brief Modifies the value of a given Doc Entry (Dicom Element)
274 * when it exists. Create it with the given value when unexistant.
275 * @param value (string) Value to be set
276 * @param group Group number of the Entry
277 * @param elem Element number of the Entry
278 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
279 * \return pointer to the modified/created Header Entry (NULL when creation
282 ValEntry *DocEntrySet::InsertValEntry(std::string const &value,
283 uint16_t group, uint16_t elem,
286 ValEntry *valEntry = 0;
287 DocEntry *currentEntry = GetDocEntry( group, elem );
291 valEntry = dynamic_cast<ValEntry *>(currentEntry);
295 if ( valEntry->GetVR()!=vr )
298 // if currentEntry doesn't correspond to the requested valEntry
301 if ( !RemoveEntry(currentEntry) )
303 gdcmWarningMacro( "Removal of previous DocEntry failed.");
310 // Create a new valEntry if necessary
313 valEntry = NewValEntry( group, elem, vr );
315 if ( !AddEntry(valEntry) )
317 gdcmWarningMacro("AddEntry failed although this is a creation.");
324 // Set the binEntry value
325 SetValEntry(value, valEntry); // The std::string value
330 * \brief Modifies the value of a given Header Entry (Dicom Element)
331 * when it exists. Create it with the given value when unexistant.
332 * A copy of the binArea is made to be kept in the Document.
333 * @param binArea (binary) value to be set
334 * @param lgth length of the Bin Area we want to set
335 * @param group Group number of the Entry
336 * @param elem Element number of the Entry
337 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
338 * \return pointer to the modified/created Header Entry (NULL when creation
341 BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth,
342 uint16_t group, uint16_t elem,
345 BinEntry *binEntry = 0;
346 DocEntry *currentEntry = GetDocEntry( group, elem );
348 // Verify the currentEntry
351 binEntry = dynamic_cast<BinEntry *>(currentEntry);
355 if ( binEntry->GetVR()!=vr )
358 // if currentEntry doesn't correspond to the requested valEntry
361 if ( !RemoveEntry(currentEntry) )
363 gdcmWarningMacro( "Removal of previous DocEntry failed.");
370 // Create a new binEntry if necessary
373 binEntry = NewBinEntry(group, elem, vr);
375 if ( !AddEntry(binEntry) )
377 gdcmWarningMacro( "AddEntry failed although this is a creation.");
384 // Set the binEntry value
386 if ( lgth>0 && binArea )
388 tmpArea = new uint8_t[lgth];
389 memcpy(tmpArea,binArea,lgth);
395 if ( !SetBinEntry(tmpArea,lgth,binEntry) )
407 * \brief Modifies the value of a given Doc Entry (Dicom Element)
408 * when it exists. Creates it when unexistant.
409 * @param group Group number of the Entry
410 * @param elem Element number of the Entry
411 * \return pointer to the modified/created SeqEntry (NULL when creation
414 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
416 SeqEntry *seqEntry = 0;
417 DocEntry *currentEntry = GetDocEntry( group, elem );
419 // Verify the currentEntry
422 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
428 // if currentEntry doesn't correspond to the requested seqEntry
431 if (!RemoveEntry(currentEntry))
433 gdcmWarningMacro( "Removal of previous DocEntry failed.");
439 // Create a new seqEntry if necessary
442 seqEntry = NewSeqEntry(group, elem);
444 if ( !AddEntry(seqEntry) )
446 gdcmWarningMacro( "AddEntry failed although this is a creation.");
453 // TODO : Find a trick to insert a SequenceDelimitationItem
454 // in the SeqEntry, at the end.
459 * \brief Checks if a given Dicom Element exists within the H table
460 * @param group Group number of the searched Dicom Element
461 * @param elem Element number of the searched Dicom Element
462 * @return true is found
464 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
466 return GetDocEntry(group,elem)!=NULL;
470 * \brief Build a new Val Entry from all the low level arguments.
471 * Check for existence of dictionary entry, and build
472 * a default one when absent.
473 * @param group Group number of the new Entry
474 * @param elem Element number of the new Entry
475 * @param vr V(alue) R(epresentation) of the new Entry
477 ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
480 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
481 gdcmAssertMacro(dictEntry);
483 ValEntry *newEntry = new ValEntry(dictEntry);
486 gdcmWarningMacro( "Failed to allocate ValEntry");
494 * \brief Build a new Bin Entry from all the low level arguments.
495 * Check for existence of dictionary entry, and build
496 * a default one when absent.
497 * @param group Group number of the new Entry
498 * @param elem Element number of the new Entry
499 * @param vr V(alue) R(epresentation) of the new Entry
501 BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
504 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
505 gdcmAssertMacro(dictEntry);
507 BinEntry *newEntry = new BinEntry(dictEntry);
510 gdcmWarningMacro( "Failed to allocate BinEntry");
517 * \brief Build a new Seq Entry from all the low level arguments.
518 * Check for existence of dictionary entry, and build
519 * a default one when absent.
520 * @param group Group number of the new Entry
521 * @param elem Element number of the new Entry
523 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
525 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
526 gdcmAssertMacro(dictEntry);
528 SeqEntry *newEntry = new SeqEntry( dictEntry );
531 gdcmWarningMacro( "Failed to allocate SeqEntry");
538 * \brief Request a new virtual dict entry to the dict set
539 * @param group Group number of the underlying DictEntry
540 * @param elem Element number of the underlying DictEntry
541 * @param vr V(alue) R(epresentation) of the underlying DictEntry
542 * @param vm V(alue) M(ultiplicity) of the underlying DictEntry
543 * @param name english name
545 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
548 TagName const &name )
550 return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
553 //-----------------------------------------------------------------------------
556 * \brief Searches [both] the public [and the shadow dictionary (when they
557 * exist)] for the presence of the DictEntry with given
558 * group and element. The public dictionary has precedence on the
559 * shadow one(s), if any.
560 * @param group Group number of the searched DictEntry
561 * @param elem Element number of the searched DictEntry
562 * @return Corresponding DictEntry when it exists, NULL otherwise.
564 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
566 DictEntry *found = 0;
567 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
570 gdcmWarningMacro( "We SHOULD have a default dictionary");
574 found = pubDict->GetEntry(group, elem);
580 * \brief Searches [both] the public [and the shadow dictionary (when they
581 * exist)] for the presence of the DictEntry with given
582 * group and element, and create a new virtual DictEntry if necessary
583 * @param group group number of the searched DictEntry
584 * @param elem element number of the searched DictEntry
585 * @param vr V(alue) R(epresentation) to use, if necessary
586 * @return Corresponding DictEntry when it exists, NULL otherwise.
588 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
591 DictEntry *dictEntry = GetDictEntry(group,elem);
592 DictEntry *goodEntry = dictEntry;
593 std::string goodVR = vr;
595 if (elem == 0x0000) goodVR="UL";
599 if ( goodVR != goodEntry->GetVR()
600 && goodVR != GDCM_UNKNOWN )
606 // Create a new virtual DictEntry if necessary
611 goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME",
612 dictEntry->GetName() );
616 goodEntry = NewVirtualDictEntry(group, elem, goodVR);
622 //-----------------------------------------------------------------------------
625 //-----------------------------------------------------------------------------
628 //-----------------------------------------------------------------------------
629 } // end namespace gdcm