1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/06/24 10:55:59 $
7 Version: $Revision: 1.57 $
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
34 //-----------------------------------------------------------------------------
37 * \brief Get the "std::string representable" value of the Dicom entry
38 * @param group Group number of the searched tag.
39 * @param elem Element number of the searched tag.
40 * @return Corresponding element value when it exists,
41 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
43 std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
45 ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
47 return entry->GetValue();
52 * \brief Gets (from Header) a 'non string' element value
53 * @param group group number of the Entry
54 * @param elem element number of the Entry
55 * @return Pointer to the 'non string' area
57 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem)
59 BinEntry *entry = GetBinEntry(group, elem);
61 return entry->GetBinArea();
66 * \brief Searches within Header Entries (Dicom Elements) parsed with
67 * the public and private dictionaries
68 * for the value length of a given tag..
69 * @param group Group number of the searched tag.
70 * @param elem Element number of the searched tag.
71 * @return Corresponding element length; -2 if not found
73 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
75 DocEntry *entry = GetDocEntry(group, elem);
77 return entry->GetLength();
82 * \brief Searches within Header Entries (Dicom Elements) parsed with
83 * the public [and private dictionaries]
84 * for the element value representation of a given tag..
85 * Obtaining the VR (Value Representation) might be needed by caller
86 * to convert the string typed content to caller's native type
87 * (think of C++ vs Python). The VR is actually of a higher level
88 * of semantics than just the native C++ type.
89 * @param group Group number of the searched tag.
90 * @param elem Element number of the searched tag.
91 * @return Corresponding element value representation when it exists,
92 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
94 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
96 DocEntry *entry = GetDocEntry(group, elem);
98 return entry->GetVR();
103 * \brief Same as \ref Document::GetDocEntry except it only
104 * returns a result when the corresponding entry is of type
106 * @param group Group number of the searched Dicom Element
107 * @param elem Element number of the searched Dicom Element
108 * @return When present, the corresponding ValEntry.
110 ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
112 DocEntry *currentEntry = GetDocEntry(group, elem);
116 return dynamic_cast<ValEntry*>(currentEntry);
120 * \brief Same as \ref Document::GetDocEntry except it only
121 * returns a result when the corresponding entry is of type
123 * @param group Group number of the searched Dicom Element
124 * @param elem Element number of the searched Dicom Element
125 * @return When present, the corresponding BinEntry.
127 BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
129 DocEntry *currentEntry = GetDocEntry(group, elem);
132 gdcmWarningMacro( "No corresponding BinEntry " << std::hex << group <<
137 return dynamic_cast<BinEntry*>(currentEntry);
141 * \brief Same as \ref Document::GetDocEntry except it only
142 * returns a result when the corresponding entry is of type
144 * @param group Group number of the searched Dicom Element
145 * @param elem Element number of the searched Dicom Element
146 * @return When present, the corresponding SeqEntry.
148 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
150 DocEntry *currentEntry = GetDocEntry(group, elem);
153 gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
158 return dynamic_cast<SeqEntry*>(currentEntry);
162 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
163 * through it's (group, element) and modifies it's content with
165 * @param content new value (string) to substitute with
166 * @param group group number of the Dicom Element to modify
167 * @param elem element number of the Dicom Element to modify
169 bool DocEntrySet::SetValEntry(std::string const &content,
170 uint16_t group, uint16_t elem)
172 ValEntry *entry = GetValEntry(group, elem);
175 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
176 "," << elem << " element (try promotion first).");
179 return SetValEntry(content,entry);
183 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
184 * through it's (group, element) and modifies it's content with
186 * @param content new value (void* -> uint8_t*) to substitute with
187 * @param lgth new value length
188 * @param group group number of the Dicom Element to modify
189 * @param elem element number of the Dicom Element to modify
191 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth,
192 uint16_t group, uint16_t elem)
194 BinEntry *entry = GetBinEntry(group, elem);
197 gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
198 "," << elem << " element (try promotion first).");
202 return SetBinEntry(content,lgth,entry);
206 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
207 * and modifies it's content with the given value.
208 * @param content new value (string) to substitute with
209 * @param entry Entry to be modified
211 bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
215 entry->SetValue(content);
222 * \brief Accesses an existing BinEntry (i.e. a Dicom Element)
223 * and modifies it's content with the given value.
224 * @param content new value (void* -> uint8_t*) to substitute with
225 * @param entry Entry to be modified
226 * @param lgth new value length
228 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
232 entry->SetBinArea(content);
233 entry->SetLength(lgth);
234 entry->SetValue(GDCM_BINLOADED);
241 * \brief Modifies the value of a given Doc Entry (Dicom Element)
242 * when it exists. Create it with the given value when unexistant.
243 * @param value (string) Value to be set
244 * @param group Group number of the Entry
245 * @param elem Element number of the Entry
246 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
247 * \return pointer to the modified/created Header Entry (NULL when creation
250 ValEntry *DocEntrySet::InsertValEntry(std::string const &value,
251 uint16_t group, uint16_t elem,
254 ValEntry *valEntry = 0;
255 DocEntry *currentEntry = GetDocEntry( group, elem );
259 valEntry = dynamic_cast<ValEntry *>(currentEntry);
263 if ( valEntry->GetVR()!=vr )
266 // if currentEntry doesn't correspond to the requested valEntry
269 if ( !RemoveEntry(currentEntry) )
271 gdcmWarningMacro( "Removal of previous DocEntry failed.");
278 // Create a new valEntry if necessary
281 valEntry = NewValEntry( group, elem, vr );
283 if ( !AddEntry(valEntry) )
285 gdcmWarningMacro("AddEntry failed although this is a creation.");
292 // Set the binEntry value
293 SetValEntry(value, valEntry); // The std::string value
298 * \brief Modifies the value of a given Header Entry (Dicom Element)
299 * when it exists. Create it with the given value when unexistant.
300 * A copy of the binArea is made to be kept in the Document.
301 * @param binArea (binary) value to be set
302 * @param lgth length of the Bin Area we want to set
303 * @param group Group number of the Entry
304 * @param elem Element number of the Entry
305 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
306 * \return pointer to the modified/created Header Entry (NULL when creation
309 BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth,
310 uint16_t group, uint16_t elem,
313 BinEntry *binEntry = 0;
314 DocEntry *currentEntry = GetDocEntry( group, elem );
316 // Verify the currentEntry
319 binEntry = dynamic_cast<BinEntry *>(currentEntry);
323 if ( binEntry->GetVR()!=vr )
326 // if currentEntry doesn't correspond to the requested valEntry
329 if ( !RemoveEntry(currentEntry) )
331 gdcmWarningMacro( "Removal of previous DocEntry failed.");
338 // Create a new binEntry if necessary
341 binEntry = NewBinEntry(group, elem, vr);
343 if ( !AddEntry(binEntry) )
345 gdcmWarningMacro( "AddEntry failed although this is a creation.");
352 // Set the binEntry value
354 if ( lgth>0 && binArea )
356 tmpArea = new uint8_t[lgth];
357 memcpy(tmpArea,binArea,lgth);
363 if ( !SetBinEntry(tmpArea,lgth,binEntry) )
375 * \brief Modifies the value of a given Doc Entry (Dicom Element)
376 * when it exists. Creates it when unexistant.
377 * @param group Group number of the Entry
378 * @param elem Element number of the Entry
379 * \return pointer to the modified/created SeqEntry (NULL when creation
382 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
384 SeqEntry *seqEntry = 0;
385 DocEntry *currentEntry = GetDocEntry( group, elem );
387 // Verify the currentEntry
390 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
396 // if currentEntry doesn't correspond to the requested seqEntry
399 if (!RemoveEntry(currentEntry))
401 gdcmWarningMacro( "Removal of previous DocEntry failed.");
407 // Create a new seqEntry if necessary
410 seqEntry = NewSeqEntry(group, elem);
412 if ( !AddEntry(seqEntry) )
414 gdcmWarningMacro( "AddEntry failed although this is a creation.");
421 // TODO : Find a trick to insert a SequenceDelimitationItem
422 // in the SeqEntry, at the end.
427 * \brief Checks if a given Dicom Element exists within the H table
428 * @param group Group number of the searched Dicom Element
429 * @param elem Element number of the searched Dicom Element
430 * @return true is found
432 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
434 return GetDocEntry(group,elem)!=NULL;
438 * \brief Build a new Val Entry from all the low level arguments.
439 * Check for existence of dictionary entry, and build
440 * a default one when absent.
441 * @param group Group number of the new Entry
442 * @param elem Element number of the new Entry
443 * @param vr V(alue) R(epresentation) of the new Entry
445 ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
448 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
449 gdcmAssertMacro(dictEntry);
451 ValEntry *newEntry = new ValEntry(dictEntry);
454 gdcmWarningMacro( "Failed to allocate ValEntry");
462 * \brief Build a new Bin Entry from all the low level arguments.
463 * Check for existence of dictionary entry, and build
464 * a default one when absent.
465 * @param group Group number of the new Entry
466 * @param elem Element number of the new Entry
467 * @param vr V(alue) R(epresentation) of the new Entry
469 BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
472 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
473 gdcmAssertMacro(dictEntry);
475 BinEntry *newEntry = new BinEntry(dictEntry);
478 gdcmWarningMacro( "Failed to allocate BinEntry");
485 * \brief Build a new Seq Entry from all the low level arguments.
486 * Check for existence of dictionary entry, and build
487 * a default one when absent.
488 * @param group Group number of the new Entry
489 * @param elem Element number of the new Entry
491 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
493 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
494 gdcmAssertMacro(dictEntry);
496 SeqEntry *newEntry = new SeqEntry( dictEntry );
499 gdcmWarningMacro( "Failed to allocate SeqEntry");
506 * \brief Request a new virtual dict entry to the dict set
507 * @param group Group number of the underlying DictEntry
508 * @param elem Element number of the underlying DictEntry
509 * @param vr V(alue) R(epresentation) of the underlying DictEntry
510 * @param vm V(alue) M(ultiplicity) of the underlying DictEntry
511 * @param name english name
513 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
516 TagName const &name )
518 return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
521 //-----------------------------------------------------------------------------
524 * \brief Searches [both] the public [and the shadow dictionary (when they
525 * exist)] for the presence of the DictEntry with given
526 * group and element. The public dictionary has precedence on the
527 * shadow one(s), if any.
528 * @param group Group number of the searched DictEntry
529 * @param elem Element number of the searched DictEntry
530 * @return Corresponding DictEntry when it exists, NULL otherwise.
532 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
534 DictEntry *found = 0;
535 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
538 gdcmWarningMacro( "We SHOULD have a default dictionary");
542 found = pubDict->GetEntry(group, elem);
548 * \brief Searches [both] the public [and the shadow dictionary (when they
549 * exist)] for the presence of the DictEntry with given
550 * group and element, and create a new virtual DictEntry if necessary
551 * @param group group number of the searched DictEntry
552 * @param elem element number of the searched DictEntry
553 * @param vr V(alue) R(epresentation) to use, if necessary
554 * @return Corresponding DictEntry when it exists, NULL otherwise.
556 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
559 DictEntry *dictEntry = GetDictEntry(group,elem);
560 DictEntry *goodEntry = dictEntry;
561 std::string goodVR = vr;
563 if (elem == 0x0000) goodVR="UL";
567 if ( goodVR != goodEntry->GetVR()
568 && goodVR != GDCM_UNKNOWN )
574 // Create a new virtual DictEntry if necessary
579 goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME",
580 dictEntry->GetName() );
584 goodEntry = NewVirtualDictEntry(group, elem, goodVR);
590 //-----------------------------------------------------------------------------
593 //-----------------------------------------------------------------------------
596 //-----------------------------------------------------------------------------
597 } // end namespace gdcm