1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/10/25 09:22:15 $
7 Version: $Revision: 1.66 $
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 Same as \ref Document::GetDocEntry except it only
130 * returns a result when the corresponding entry is of type
132 * @param group Group number of the searched Dicom Element
133 * @param elem Element number of the searched Dicom Element
134 * @return When present, the corresponding DataEntry.
136 DataEntry *DocEntrySet::GetDataEntry(uint16_t group, uint16_t elem)
138 DocEntry *currentEntry = GetDocEntry(group, elem);
142 return dynamic_cast<DataEntry*>(currentEntry);
146 * \brief Same as \ref Document::GetDocEntry except it only
147 * returns a result when the corresponding entry is of type
149 * @param group Group number of the searched Dicom Element
150 * @param elem Element number of the searched Dicom Element
151 * @return When present, the corresponding SeqEntry.
153 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
155 DocEntry *currentEntry = GetDocEntry(group, elem);
158 gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
163 return dynamic_cast<SeqEntry*>(currentEntry);
167 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
168 * through it's (group, element) and modifies it's content with
170 * @param content new value (string) to substitute with
171 * @param group group number of the Dicom Element to modify
172 * @param elem element number of the Dicom Element to modify
174 bool DocEntrySet::SetEntryString(std::string const &content,
175 uint16_t group, uint16_t elem)
177 DataEntry *entry = GetDataEntry(group, elem);
180 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
181 "," << elem << " element (try promotion first).");
184 return SetEntryString(content,entry);
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 (void* -> uint8_t*) to substitute with
192 * @param lgth new value length
193 * @param group group number of the Dicom Element to modify
194 * @param elem element number of the Dicom Element to modify
196 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth,
197 uint16_t group, uint16_t elem)
199 DataEntry *entry = GetDataEntry(group, elem);
202 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
203 "," << elem << " element (try promotion first).");
207 return SetEntryBinArea(content,lgth,entry);
211 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
212 * and modifies it's content with the given value.
213 * @param content new value (string) to substitute with
214 * @param entry Entry to be modified
216 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
220 entry->SetString(content);
227 * \brief Accesses an existing DataEntry (i.e. a Dicom Element)
228 * and modifies it's content with the given value.
229 * @param content new value (void* -> uint8_t*) to substitute with
230 * @param entry Entry to be modified
231 * @param lgth new value length
233 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
237 entry->SetLength(lgth);
238 entry->SetBinArea(content);
245 * \brief Modifies the value of a given Doc Entry (Dicom Element)
246 * when it exists. Create it with the given value when unexistant.
247 * @param value (string) Value to be set
248 * @param group Group number of the Entry
249 * @param elem Element number of the Entry
250 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
251 * \return pointer to the modified/created Header Entry (NULL when creation
254 DataEntry *DocEntrySet::InsertEntryString(std::string const &value,
255 uint16_t group, uint16_t elem,
258 DataEntry *dataEntry = 0;
259 DocEntry *currentEntry = GetDocEntry( group, elem );
263 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
267 if ( dataEntry->GetVR()!=vr )
270 // if currentEntry doesn't correspond to the requested dataEntry
273 if ( !RemoveEntry(currentEntry) )
275 gdcmWarningMacro( "Removal of previous DocEntry failed.");
281 // Create a new dataEntry if necessary
284 dataEntry = NewDataEntry( group, elem, vr );
286 if ( !AddEntry(dataEntry) )
288 gdcmWarningMacro("AddEntry failed although this is a creation.");
295 // Set the dataEntry value
296 SetEntryString(value, dataEntry); // 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 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
313 uint16_t group, uint16_t elem,
316 DataEntry *dataEntry = 0;
317 DocEntry *currentEntry = GetDocEntry( group, elem );
319 // Verify the currentEntry
322 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
326 if ( dataEntry->GetVR()!=vr )
329 // if currentEntry doesn't correspond to the requested dataEntry
332 if ( !RemoveEntry(currentEntry) )
334 gdcmWarningMacro( "Removal of previous DocEntry failed.");
340 // Create a new dataEntry if necessary
343 dataEntry = NewDataEntry(group, elem, vr);
345 if ( !AddEntry(dataEntry) )
347 gdcmWarningMacro( "AddEntry failed although this is a creation.");
354 // Set the dataEntry value
356 if ( lgth>0 && binArea )
358 tmpArea = new uint8_t[lgth];
359 memcpy(tmpArea,binArea,lgth);
365 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
377 * \brief Modifies the value of a given Doc Entry (Dicom Element)
378 * when it exists. Creates it when unexistant.
379 * @param group Group number of the Entry
380 * @param elem Element number of the Entry
381 * \return pointer to the modified/created SeqEntry (NULL when creation
384 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
386 SeqEntry *seqEntry = 0;
387 DocEntry *currentEntry = GetDocEntry( group, elem );
389 // Verify the currentEntry
392 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
398 // if currentEntry doesn't correspond to the requested seqEntry
401 if (!RemoveEntry(currentEntry))
403 gdcmWarningMacro( "Removal of previous DocEntry failed.");
409 // Create a new seqEntry if necessary
412 seqEntry = NewSeqEntry(group, elem);
414 if ( !AddEntry(seqEntry) )
416 gdcmWarningMacro( "AddEntry failed although this is a creation.");
423 // TODO : Find a trick to insert a SequenceDelimitationItem
424 // in the SeqEntry, at the end.
429 * \brief Checks if a given Dicom Element exists within the H table
430 * @param group Group number of the searched Dicom Element
431 * @param elem Element number of the searched Dicom Element
432 * @return true is found
434 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
436 return GetDocEntry(group,elem)!=NULL;
440 * \brief Build a new Val Entry from all the low level arguments.
441 * Check for existence of dictionary entry, and build
442 * a default one when absent.
443 * @param group Group number of the new Entry
444 * @param elem Element number of the new Entry
445 * @param vr V(alue) R(epresentation) of the new Entry
446 * \remarks The user of this method must destroy the DataEntry when unused
448 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
451 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
453 DataEntry *newEntry = DataEntry::New(dictEntry);
454 dictEntry->Unregister(); // GetDictEntry register it
457 gdcmWarningMacro( "Failed to allocate DataEntry");
464 * \brief Build a new Seq Entry from all the low level arguments.
465 * Check for existence of dictionary entry, and build
466 * a default one when absent.
467 * @param group Group number of the new Entry
468 * @param elem Element number of the new Entry
469 * \remarks The user of this method must destroy the SeqEntry when unused
471 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
473 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
475 SeqEntry *newEntry = SeqEntry::New( dictEntry );
476 dictEntry->Unregister(); // GetDictEntry register it
479 gdcmWarningMacro( "Failed to allocate SeqEntry");
485 //-----------------------------------------------------------------------------
488 * \brief Searches [both] the public [and the shadow dictionary (when they
489 * exist)] for the presence of the DictEntry with given
490 * group and element. The public dictionary has precedence on the
491 * shadow one(s), if any.
492 * @param group Group number of the searched DictEntry
493 * @param elem Element number of the searched DictEntry
494 * @return Corresponding DictEntry when it exists, NULL otherwise.
495 * \remarks The returned DictEntry is registered when existing
497 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
499 DictEntry *found = 0;
500 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
503 gdcmWarningMacro( "We SHOULD have a default dictionary");
507 found = pubDict->GetEntry(group, elem);
515 * \brief Searches [both] the public [and the shadow dictionary (when they
516 * exist)] for the presence of the DictEntry with given
517 * group and element, and create a new virtual DictEntry if necessary
518 * @param group group number of the searched DictEntry
519 * @param elem element number of the searched DictEntry
520 * @param vr V(alue) R(epresentation) to use, if necessary
521 * @return Corresponding DictEntry when it exists, NULL otherwise.
522 * \remarks The returned DictEntry is registered
524 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
527 DictEntry *dictEntry = GetDictEntry(group,elem);
528 DictEntry *goodEntry = dictEntry;
536 if ( goodVR != goodEntry->GetVR()
537 && goodVR != GDCM_VRUNKNOWN )
541 dictEntry->Unregister();
544 // Create a new virtual DictEntry if necessary
549 goodEntry = DictEntry::New(group, elem, goodVR, "FIXME",
550 dictEntry->GetName() );
554 goodEntry = DictEntry::New(group, elem, goodVR);
559 goodEntry->Register();
564 //-----------------------------------------------------------------------------
567 //-----------------------------------------------------------------------------
570 //-----------------------------------------------------------------------------
571 } // end namespace gdcm