1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/10/18 08:35:49 $
7 Version: $Revision: 1.60 $
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"
27 #include "gdcmDataEntry.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::GetEntryString(uint16_t group, uint16_t elem)
49 DataEntry *entry = dynamic_cast<DataEntry *>(GetDocEntry(group,elem));
52 if( entry->IsNotLoaded() )
53 return GDCM_NOTLOADED;
54 if( entry->IsUnfound() )
56 if( entry->IsUnread() )
58 return entry->GetString();
64 * \brief Gets (from Header) a 'non string' element value
65 * @param group group number of the Entry
66 * @param elem element number of the Entry
67 * @return Pointer to the 'non string' area
69 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem)
71 DataEntry *entry = GetDataEntry(group, elem);
73 return entry->GetBinArea();
78 * \brief Return the value of the DataEntry if it's "std::string representable"
79 * @param group Group number of the searched tag.
80 * @param elem Element number of the searched tag.
81 * @return Corresponding element value when it's "std::string representable"
82 * and the string GDCM_NOTASCII otherwise.
84 std::string DocEntrySet::GetEntryForcedAsciiValue(uint16_t group, uint16_t elem)
86 DocEntry *d = GetDocEntry(group,elem);
90 DataEntry *de = dynamic_cast<DataEntry *>(d);
93 if( de->IsNotLoaded() )
94 return GDCM_NOTLOADED;
101 if( Global::GetVR()->IsVROfStringRepresentable( de->GetVR() ) )
102 return de->GetString();
105 uint8_t *a = de->GetBinArea();
106 if( Util::IsCleanArea(a, de->GetLength()) )
107 return Util::CreateCleanString(a, de->GetLength());
109 return GDCM_NOTASCII;
113 * \brief Searches within Header Entries (Dicom Elements) parsed with
114 * the public and private dictionaries
115 * for the value length of a given tag..
116 * @param group Group number of the searched tag.
117 * @param elem Element number of the searched tag.
118 * @return Corresponding element length; -2 if not found
120 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
122 DocEntry *entry = GetDocEntry(group, elem);
124 return entry->GetLength();
129 * \brief Searches within Header Entries (Dicom Elements) parsed with
130 * the public [and private dictionaries]
131 * for the element value representation of a given tag..
132 * Obtaining the VR (Value Representation) might be needed by caller
133 * to convert the string typed content to caller's native type
134 * (think of C++ vs Python). The VR is actually of a higher level
135 * of semantics than just the native C++ type.
136 * @param group Group number of the searched tag.
137 * @param elem Element number of the searched tag.
138 * @return Corresponding element value representation when it exists,
139 * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
141 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
143 DocEntry *entry = GetDocEntry(group, elem);
145 return entry->GetVR();
150 * \brief Same as \ref Document::GetDocEntry except it only
151 * returns a result when the corresponding entry is of type
153 * @param group Group number of the searched Dicom Element
154 * @param elem Element number of the searched Dicom Element
155 * @return When present, the corresponding DataEntry.
157 DataEntry *DocEntrySet::GetDataEntry(uint16_t group, uint16_t elem)
159 DocEntry *currentEntry = GetDocEntry(group, elem);
163 return dynamic_cast<DataEntry*>(currentEntry);
167 * \brief Same as \ref Document::GetDocEntry except it only
168 * returns a result when the corresponding entry is of type
170 * @param group Group number of the searched Dicom Element
171 * @param elem Element number of the searched Dicom Element
172 * @return When present, the corresponding SeqEntry.
174 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
176 DocEntry *currentEntry = GetDocEntry(group, elem);
179 gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
184 return dynamic_cast<SeqEntry*>(currentEntry);
188 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
189 * through it's (group, element) and modifies it's content with
191 * @param content new value (string) to substitute with
192 * @param group group number of the Dicom Element to modify
193 * @param elem element number of the Dicom Element to modify
195 bool DocEntrySet::SetEntryString(std::string const &content,
196 uint16_t group, uint16_t elem)
198 DataEntry *entry = GetDataEntry(group, elem);
201 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
202 "," << elem << " element (try promotion first).");
205 return SetEntryString(content,entry);
209 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
210 * through it's (group, element) and modifies it's content with
212 * @param content new value (void* -> uint8_t*) to substitute with
213 * @param lgth new value length
214 * @param group group number of the Dicom Element to modify
215 * @param elem element number of the Dicom Element to modify
217 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth,
218 uint16_t group, uint16_t elem)
220 DataEntry *entry = GetDataEntry(group, elem);
223 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
224 "," << elem << " element (try promotion first).");
228 return SetEntryBinArea(content,lgth,entry);
232 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
233 * and modifies it's content with the given value.
234 * @param content new value (string) to substitute with
235 * @param entry Entry to be modified
237 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
241 entry->SetString(content);
248 * \brief Accesses an existing DataEntry (i.e. a Dicom Element)
249 * and modifies it's content with the given value.
250 * @param content new value (void* -> uint8_t*) to substitute with
251 * @param entry Entry to be modified
252 * @param lgth new value length
254 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
258 entry->SetLength(lgth);
259 entry->SetBinArea(content);
266 * \brief Modifies the value of a given Doc Entry (Dicom Element)
267 * when it exists. Create it with the given value when unexistant.
268 * @param value (string) Value to be set
269 * @param group Group number of the Entry
270 * @param elem Element number of the Entry
271 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
272 * \return pointer to the modified/created Header Entry (NULL when creation
275 DataEntry *DocEntrySet::InsertEntryString(std::string const &value,
276 uint16_t group, uint16_t elem,
279 DataEntry *dataEntry = 0;
280 DocEntry *currentEntry = GetDocEntry( group, elem );
284 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
288 if ( dataEntry->GetVR()!=vr )
291 // if currentEntry doesn't correspond to the requested dataEntry
294 if ( !RemoveEntry(currentEntry) )
296 gdcmWarningMacro( "Removal of previous DocEntry failed.");
302 // Create a new dataEntry if necessary
305 dataEntry = NewDataEntry( group, elem, vr );
307 if ( !AddEntry(dataEntry) )
309 gdcmWarningMacro("AddEntry failed although this is a creation.");
316 // Set the dataEntry value
317 SetEntryString(value, dataEntry); // The std::string value
322 * \brief Modifies the value of a given Header Entry (Dicom Element)
323 * when it exists. Create it with the given value when unexistant.
324 * A copy of the binArea is made to be kept in the Document.
325 * @param binArea (binary) value to be set
326 * @param lgth length of the Bin Area we want to set
327 * @param group Group number of the Entry
328 * @param elem Element number of the Entry
329 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
330 * \return pointer to the modified/created Header Entry (NULL when creation
333 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
334 uint16_t group, uint16_t elem,
337 DataEntry *dataEntry = 0;
338 DocEntry *currentEntry = GetDocEntry( group, elem );
340 // Verify the currentEntry
343 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
347 if ( dataEntry->GetVR()!=vr )
350 // if currentEntry doesn't correspond to the requested dataEntry
353 if ( !RemoveEntry(currentEntry) )
355 gdcmWarningMacro( "Removal of previous DocEntry failed.");
361 // Create a new dataEntry if necessary
364 dataEntry = NewDataEntry(group, elem, vr);
366 if ( !AddEntry(dataEntry) )
368 gdcmWarningMacro( "AddEntry failed although this is a creation.");
375 // Set the dataEntry value
377 if ( lgth>0 && binArea )
379 tmpArea = new uint8_t[lgth];
380 memcpy(tmpArea,binArea,lgth);
386 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
398 * \brief Modifies the value of a given Doc Entry (Dicom Element)
399 * when it exists. Creates it when unexistant.
400 * @param group Group number of the Entry
401 * @param elem Element number of the Entry
402 * \return pointer to the modified/created SeqEntry (NULL when creation
405 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
407 SeqEntry *seqEntry = 0;
408 DocEntry *currentEntry = GetDocEntry( group, elem );
410 // Verify the currentEntry
413 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
419 // if currentEntry doesn't correspond to the requested seqEntry
422 if (!RemoveEntry(currentEntry))
424 gdcmWarningMacro( "Removal of previous DocEntry failed.");
430 // Create a new seqEntry if necessary
433 seqEntry = NewSeqEntry(group, elem);
435 if ( !AddEntry(seqEntry) )
437 gdcmWarningMacro( "AddEntry failed although this is a creation.");
444 // TODO : Find a trick to insert a SequenceDelimitationItem
445 // in the SeqEntry, at the end.
450 * \brief Checks if a given Dicom Element exists within the H table
451 * @param group Group number of the searched Dicom Element
452 * @param elem Element number of the searched Dicom Element
453 * @return true is found
455 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
457 return GetDocEntry(group,elem)!=NULL;
461 * \brief Build a new Val Entry from all the low level arguments.
462 * Check for existence of dictionary entry, and build
463 * a default one when absent.
464 * @param group Group number of the new Entry
465 * @param elem Element number of the new Entry
466 * @param vr V(alue) R(epresentation) of the new Entry
468 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
471 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
472 gdcmAssertMacro(dictEntry);
474 DataEntry *newEntry = new DataEntry(dictEntry);
477 gdcmWarningMacro( "Failed to allocate DataEntry");
484 * \brief Build a new Seq Entry from all the low level arguments.
485 * Check for existence of dictionary entry, and build
486 * a default one when absent.
487 * @param group Group number of the new Entry
488 * @param elem Element number of the new Entry
490 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
492 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
493 gdcmAssertMacro(dictEntry);
495 SeqEntry *newEntry = new SeqEntry( dictEntry );
498 gdcmWarningMacro( "Failed to allocate SeqEntry");
505 * \brief Request a new virtual dict entry to the dict set
506 * @param group Group number of the underlying DictEntry
507 * @param elem Element number of the underlying DictEntry
508 * @param vr V(alue) R(epresentation) of the underlying DictEntry
509 * @param vm V(alue) M(ultiplicity) of the underlying DictEntry
510 * @param name english name
512 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
515 TagName const &name )
517 return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
520 //-----------------------------------------------------------------------------
523 * \brief Searches [both] the public [and the shadow dictionary (when they
524 * exist)] for the presence of the DictEntry with given
525 * group and element. The public dictionary has precedence on the
526 * shadow one(s), if any.
527 * @param group Group number of the searched DictEntry
528 * @param elem Element number of the searched DictEntry
529 * @return Corresponding DictEntry when it exists, NULL otherwise.
531 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
533 DictEntry *found = 0;
534 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
537 gdcmWarningMacro( "We SHOULD have a default dictionary");
541 found = pubDict->GetEntry(group, elem);
547 * \brief Searches [both] the public [and the shadow dictionary (when they
548 * exist)] for the presence of the DictEntry with given
549 * group and element, and create a new virtual DictEntry if necessary
550 * @param group group number of the searched DictEntry
551 * @param elem element number of the searched DictEntry
552 * @param vr V(alue) R(epresentation) to use, if necessary
553 * @return Corresponding DictEntry when it exists, NULL otherwise.
555 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
558 DictEntry *dictEntry = GetDictEntry(group,elem);
559 DictEntry *goodEntry = dictEntry;
560 std::string goodVR = vr;
562 if (elem == 0x0000) goodVR="UL";
566 if ( goodVR != goodEntry->GetVR()
567 && goodVR != GDCM_UNKNOWN )
573 // Create a new virtual DictEntry if necessary
578 goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME",
579 dictEntry->GetName() );
583 goodEntry = NewVirtualDictEntry(group, elem, goodVR);
589 //-----------------------------------------------------------------------------
592 //-----------------------------------------------------------------------------
595 //-----------------------------------------------------------------------------
596 } // end namespace gdcm