1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/08/24 12:09:13 $
7 Version: $Revision: 1.58 $
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"
31 //-----------------------------------------------------------------------------
32 // Constructor / Destructor
33 DocEntrySet::DocEntrySet()
37 //-----------------------------------------------------------------------------
40 * \brief Get the "std::string representable" value of the Dicom entry
41 * @param group Group number of the searched tag.
42 * @param elem Element number of the searched tag.
43 * @return Corresponding element value when it exists,
44 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
46 std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
48 ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
50 return entry->GetValue();
55 * \brief Gets (from Header) a 'non string' element value
56 * @param group group number of the Entry
57 * @param elem element number of the Entry
58 * @return Pointer to the 'non string' area
60 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem)
62 BinEntry *entry = GetBinEntry(group, elem);
64 return entry->GetBinArea();
69 * \brief Searches within Header Entries (Dicom Elements) parsed with
70 * the public and private dictionaries
71 * for the value length of a given tag..
72 * @param group Group number of the searched tag.
73 * @param elem Element number of the searched tag.
74 * @return Corresponding element length; -2 if not found
76 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
78 DocEntry *entry = GetDocEntry(group, elem);
80 return entry->GetLength();
85 * \brief Searches within Header Entries (Dicom Elements) parsed with
86 * the public [and private dictionaries]
87 * for the element value representation of a given tag..
88 * Obtaining the VR (Value Representation) might be needed by caller
89 * to convert the string typed content to caller's native type
90 * (think of C++ vs Python). The VR is actually of a higher level
91 * of semantics than just the native C++ type.
92 * @param group Group number of the searched tag.
93 * @param elem Element number of the searched tag.
94 * @return Corresponding element value representation when it exists,
95 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
97 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
99 DocEntry *entry = GetDocEntry(group, elem);
101 return entry->GetVR();
106 * \brief Same as \ref Document::GetDocEntry except it only
107 * returns a result when the corresponding entry is of type
109 * @param group Group number of the searched Dicom Element
110 * @param elem Element number of the searched Dicom Element
111 * @return When present, the corresponding ValEntry.
113 ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
115 DocEntry *currentEntry = GetDocEntry(group, elem);
119 return dynamic_cast<ValEntry*>(currentEntry);
123 * \brief Same as \ref Document::GetDocEntry except it only
124 * returns a result when the corresponding entry is of type
126 * @param group Group number of the searched Dicom Element
127 * @param elem Element number of the searched Dicom Element
128 * @return When present, the corresponding BinEntry.
130 BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
132 DocEntry *currentEntry = GetDocEntry(group, elem);
135 gdcmWarningMacro( "No corresponding BinEntry " << std::hex << group <<
140 return dynamic_cast<BinEntry*>(currentEntry);
144 * \brief Same as \ref Document::GetDocEntry except it only
145 * returns a result when the corresponding entry is of type
147 * @param group Group number of the searched Dicom Element
148 * @param elem Element number of the searched Dicom Element
149 * @return When present, the corresponding SeqEntry.
151 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
153 DocEntry *currentEntry = GetDocEntry(group, elem);
156 gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
161 return dynamic_cast<SeqEntry*>(currentEntry);
165 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
166 * through it's (group, element) and modifies it's content with
168 * @param content new value (string) to substitute with
169 * @param group group number of the Dicom Element to modify
170 * @param elem element number of the Dicom Element to modify
172 bool DocEntrySet::SetValEntry(std::string const &content,
173 uint16_t group, uint16_t elem)
175 ValEntry *entry = GetValEntry(group, elem);
178 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
179 "," << elem << " element (try promotion first).");
182 return SetValEntry(content,entry);
186 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
187 * through it's (group, element) and modifies it's content with
189 * @param content new value (void* -> uint8_t*) to substitute with
190 * @param lgth new value length
191 * @param group group number of the Dicom Element to modify
192 * @param elem element number of the Dicom Element to modify
194 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth,
195 uint16_t group, uint16_t elem)
197 BinEntry *entry = GetBinEntry(group, elem);
200 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
201 "," << elem << " element (try promotion first).");
205 return SetBinEntry(content,lgth,entry);
209 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
210 * and modifies it's content with the given value.
211 * @param content new value (string) to substitute with
212 * @param entry Entry to be modified
214 bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
218 entry->SetValue(content);
225 * \brief Accesses an existing BinEntry (i.e. a Dicom Element)
226 * and modifies it's content with the given value.
227 * @param content new value (void* -> uint8_t*) to substitute with
228 * @param entry Entry to be modified
229 * @param lgth new value length
231 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
235 entry->SetBinArea(content);
236 entry->SetLength(lgth);
237 entry->SetValue(GDCM_BINLOADED);
244 * \brief Modifies the value of a given Doc Entry (Dicom Element)
245 * when it exists. Create it with the given value when unexistant.
246 * @param value (string) Value to be set
247 * @param group Group number of the Entry
248 * @param elem Element number of the Entry
249 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
250 * \return pointer to the modified/created Header Entry (NULL when creation
253 ValEntry *DocEntrySet::InsertValEntry(std::string const &value,
254 uint16_t group, uint16_t elem,
257 ValEntry *valEntry = 0;
258 DocEntry *currentEntry = GetDocEntry( group, elem );
262 valEntry = dynamic_cast<ValEntry *>(currentEntry);
266 if ( valEntry->GetVR()!=vr )
269 // if currentEntry doesn't correspond to the requested valEntry
272 if ( !RemoveEntry(currentEntry) )
274 gdcmWarningMacro( "Removal of previous DocEntry failed.");
281 // Create a new valEntry if necessary
284 valEntry = NewValEntry( group, elem, vr );
286 if ( !AddEntry(valEntry) )
288 gdcmWarningMacro("AddEntry failed although this is a creation.");
295 // Set the binEntry value
296 SetValEntry(value, valEntry); // The std::string value
301 * \brief Modifies the value of a given Header Entry (Dicom Element)
302 * when it exists. Create it with the given value when unexistant.
303 * A copy of the binArea is made to be kept in the Document.
304 * @param binArea (binary) value to be set
305 * @param lgth length of the Bin Area we want to set
306 * @param group Group number of the Entry
307 * @param elem Element number of the Entry
308 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
309 * \return pointer to the modified/created Header Entry (NULL when creation
312 BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth,
313 uint16_t group, uint16_t elem,
316 BinEntry *binEntry = 0;
317 DocEntry *currentEntry = GetDocEntry( group, elem );
319 // Verify the currentEntry
322 binEntry = dynamic_cast<BinEntry *>(currentEntry);
326 if ( binEntry->GetVR()!=vr )
329 // if currentEntry doesn't correspond to the requested valEntry
332 if ( !RemoveEntry(currentEntry) )
334 gdcmWarningMacro( "Removal of previous DocEntry failed.");
341 // Create a new binEntry if necessary
344 binEntry = NewBinEntry(group, elem, vr);
346 if ( !AddEntry(binEntry) )
348 gdcmWarningMacro( "AddEntry failed although this is a creation.");
355 // Set the binEntry value
357 if ( lgth>0 && binArea )
359 tmpArea = new uint8_t[lgth];
360 memcpy(tmpArea,binArea,lgth);
366 if ( !SetBinEntry(tmpArea,lgth,binEntry) )
378 * \brief Modifies the value of a given Doc Entry (Dicom Element)
379 * when it exists. Creates it when unexistant.
380 * @param group Group number of the Entry
381 * @param elem Element number of the Entry
382 * \return pointer to the modified/created SeqEntry (NULL when creation
385 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
387 SeqEntry *seqEntry = 0;
388 DocEntry *currentEntry = GetDocEntry( group, elem );
390 // Verify the currentEntry
393 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
399 // if currentEntry doesn't correspond to the requested seqEntry
402 if (!RemoveEntry(currentEntry))
404 gdcmWarningMacro( "Removal of previous DocEntry failed.");
410 // Create a new seqEntry if necessary
413 seqEntry = NewSeqEntry(group, elem);
415 if ( !AddEntry(seqEntry) )
417 gdcmWarningMacro( "AddEntry failed although this is a creation.");
424 // TODO : Find a trick to insert a SequenceDelimitationItem
425 // in the SeqEntry, at the end.
430 * \brief Checks if a given Dicom Element exists within the H table
431 * @param group Group number of the searched Dicom Element
432 * @param elem Element number of the searched Dicom Element
433 * @return true is found
435 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
437 return GetDocEntry(group,elem)!=NULL;
441 * \brief Build a new Val Entry from all the low level arguments.
442 * Check for existence of dictionary entry, and build
443 * a default one when absent.
444 * @param group Group number of the new Entry
445 * @param elem Element number of the new Entry
446 * @param vr V(alue) R(epresentation) of the new Entry
448 ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
451 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
452 gdcmAssertMacro(dictEntry);
454 ValEntry *newEntry = new ValEntry(dictEntry);
457 gdcmWarningMacro( "Failed to allocate ValEntry");
465 * \brief Build a new Bin Entry from all the low level arguments.
466 * Check for existence of dictionary entry, and build
467 * a default one when absent.
468 * @param group Group number of the new Entry
469 * @param elem Element number of the new Entry
470 * @param vr V(alue) R(epresentation) of the new Entry
472 BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
475 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
476 gdcmAssertMacro(dictEntry);
478 BinEntry *newEntry = new BinEntry(dictEntry);
481 gdcmWarningMacro( "Failed to allocate BinEntry");
488 * \brief Build a new Seq Entry from all the low level arguments.
489 * Check for existence of dictionary entry, and build
490 * a default one when absent.
491 * @param group Group number of the new Entry
492 * @param elem Element number of the new Entry
494 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
496 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
497 gdcmAssertMacro(dictEntry);
499 SeqEntry *newEntry = new SeqEntry( dictEntry );
502 gdcmWarningMacro( "Failed to allocate SeqEntry");
509 * \brief Request a new virtual dict entry to the dict set
510 * @param group Group number of the underlying DictEntry
511 * @param elem Element number of the underlying DictEntry
512 * @param vr V(alue) R(epresentation) of the underlying DictEntry
513 * @param vm V(alue) M(ultiplicity) of the underlying DictEntry
514 * @param name english name
516 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
519 TagName const &name )
521 return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
524 //-----------------------------------------------------------------------------
527 * \brief Searches [both] the public [and the shadow dictionary (when they
528 * exist)] for the presence of the DictEntry with given
529 * group and element. The public dictionary has precedence on the
530 * shadow one(s), if any.
531 * @param group Group number of the searched DictEntry
532 * @param elem Element number of the searched DictEntry
533 * @return Corresponding DictEntry when it exists, NULL otherwise.
535 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
537 DictEntry *found = 0;
538 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
541 gdcmWarningMacro( "We SHOULD have a default dictionary");
545 found = pubDict->GetEntry(group, elem);
551 * \brief Searches [both] the public [and the shadow dictionary (when they
552 * exist)] for the presence of the DictEntry with given
553 * group and element, and create a new virtual DictEntry if necessary
554 * @param group group number of the searched DictEntry
555 * @param elem element number of the searched DictEntry
556 * @param vr V(alue) R(epresentation) to use, if necessary
557 * @return Corresponding DictEntry when it exists, NULL otherwise.
559 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
562 DictEntry *dictEntry = GetDictEntry(group,elem);
563 DictEntry *goodEntry = dictEntry;
564 std::string goodVR = vr;
566 if (elem == 0x0000) goodVR="UL";
570 if ( goodVR != goodEntry->GetVR()
571 && goodVR != GDCM_UNKNOWN )
577 // Create a new virtual DictEntry if necessary
582 goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME",
583 dictEntry->GetName() );
587 goodEntry = NewVirtualDictEntry(group, elem, goodVR);
593 //-----------------------------------------------------------------------------
596 //-----------------------------------------------------------------------------
599 //-----------------------------------------------------------------------------
600 } // end namespace gdcm