1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/11/21 09:41:46 $
7 Version: $Revision: 1.68 $
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 Searches within the DocEntrySet
79 * for the value length of a given tag..
80 * @param group Group number of the searched tag.
81 * @param elem Element number of the searched tag.
82 * @return Corresponding element length; -1 if not found
84 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
86 DocEntry *entry = GetDocEntry(group, elem);
88 return entry->GetLength();
93 * \brief Same as \ref Document::GetDocEntry except it returns a result
94 * only when the corresponding entry is of type DataEntry.
95 * @param group Group number of the searched Dicom Element
96 * @param elem Element number of the searched Dicom Element
97 * @return When present, the corresponding DataEntry.
99 DataEntry *DocEntrySet::GetDataEntry(uint16_t group, uint16_t elem)
101 DocEntry *currentEntry = GetDocEntry(group, elem);
105 return dynamic_cast<DataEntry*>(currentEntry);
109 * \brief Same as \ref Document::GetDocEntry except it returns a result
110 * only when the corresponding entry is of type SeqEntry.
111 * @param group Group number of the searched Dicom Element
112 * @param elem Element number of the searched Dicom Element
113 * @return When present, the corresponding SeqEntry.
115 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
117 DocEntry *currentEntry = GetDocEntry(group, elem);
121 return dynamic_cast<SeqEntry*>(currentEntry);
125 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
126 * through it's (group, element) and modifies it's content with
128 * @param content new value (string) to substitute with
129 * @param group group number of the Dicom Element to modify
130 * @param elem element number of the Dicom Element to modify
132 bool DocEntrySet::SetEntryString(std::string const &content,
133 uint16_t group, uint16_t elem)
135 DataEntry *entry = GetDataEntry(group, elem);
138 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
139 "," << elem << " element (try promotion first).");
142 return SetEntryString(content,entry);
146 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
147 * through it's (group, element) and modifies it's content with
149 * @param content new value (void* -> uint8_t*) to substitute with
150 * @param lgth new value length
151 * @param group group number of the Dicom Element to modify
152 * @param elem element number of the Dicom Element to modify
154 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth,
155 uint16_t group, uint16_t elem)
157 DataEntry *entry = GetDataEntry(group, elem);
160 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
161 "," << elem << " element (try promotion first).");
165 return SetEntryBinArea(content,lgth,entry);
169 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
170 * and modifies it's content with the given value.
171 * @param content new value (string) to substitute with
172 * @param entry Entry to be modified
174 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
178 entry->SetString(content);
185 * \brief Accesses an existing DataEntry (i.e. a Dicom Element)
186 * and modifies it's content with the given value.
187 * @param content new value (void* -> uint8_t*) to substitute with
188 * @param entry Entry to be modified
189 * @param lgth new value length
191 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
195 entry->SetLength(lgth);
196 entry->SetBinArea(content);
203 * \brief Modifies the value of a given Doc Entry (Dicom Element)
204 * when it exists. Create it with the given value when unexistant.
205 * @param value (string) Value to be set
206 * @param group Group number of the Entry
207 * @param elem Element number of the Entry
208 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
209 * \return pointer to the modified/created Header Entry (NULL when creation
212 DataEntry *DocEntrySet::InsertEntryString(std::string const &value,
213 uint16_t group, uint16_t elem,
216 DataEntry *dataEntry = 0;
217 DocEntry *currentEntry = GetDocEntry( group, elem );
221 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
225 if ( dataEntry->GetVR()!=vr )
228 // if currentEntry doesn't correspond to the requested dataEntry
231 if ( !RemoveEntry(currentEntry) )
233 gdcmWarningMacro( "Removal of previous DocEntry failed.");
239 // Create a new dataEntry if necessary
242 dataEntry = NewDataEntry( group, elem, vr );
244 if ( !AddEntry(dataEntry) )
246 gdcmWarningMacro("AddEntry failed although this is a creation.");
253 // Set the dataEntry value
254 SetEntryString(value, dataEntry); // The std::string value
259 * \brief Modifies the value of a given Header Entry (Dicom Element)
260 * when it exists. Create it with the given value when unexistant.
261 * A copy of the binArea is made to be kept in the Document.
262 * @param binArea (binary) value to be set
263 * @param lgth length of the Bin Area we want to set
264 * @param group Group number of the Entry
265 * @param elem Element number of the Entry
266 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
267 * \return pointer to the modified/created Header Entry (NULL when creation
270 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
271 uint16_t group, uint16_t elem,
274 DataEntry *dataEntry = 0;
275 DocEntry *currentEntry = GetDocEntry( group, elem );
277 // Verify the currentEntry
280 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
284 if ( dataEntry->GetVR()!=vr )
287 // if currentEntry doesn't correspond to the requested dataEntry
290 if ( !RemoveEntry(currentEntry) )
292 gdcmWarningMacro( "Removal of previous DocEntry failed.");
298 // Create a new dataEntry if necessary
301 dataEntry = NewDataEntry(group, elem, vr);
303 if ( !AddEntry(dataEntry) )
305 gdcmWarningMacro( "AddEntry failed although this is a creation.");
312 // Set the dataEntry value
314 if ( lgth>0 && binArea )
316 tmpArea = new uint8_t[lgth];
317 memcpy(tmpArea,binArea,lgth);
323 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
334 * \brief Creates a new gdcm::SeqEntry and adds it to the current DocEntrySet.
335 * (remove any existing entry with same group,elem)
336 * @param group Group number of the Entry
337 * @param elem Element number of the Entry
338 * \return pointer to the created SeqEntry (NULL when creation
341 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
343 SeqEntry *seqEntry = 0;
344 DocEntry *currentEntry = GetDocEntry( group, elem );
346 // Verify the currentEntry
349 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
355 // if currentEntry doesn't correspond to the requested seqEntry
358 if (!RemoveEntry(currentEntry))
360 gdcmWarningMacro( "Removal of previous DocEntry failed for ("
361 <<std::hex << group << "|" << elem <<")" );
366 // Create a new seqEntry if necessary
369 seqEntry = NewSeqEntry(group, elem);
371 if ( !AddEntry(seqEntry) )
373 gdcmWarningMacro( "AddEntry failed although this is a creation for ("
374 <<std::hex << group << "|" << elem <<")" );
381 // SequenceDelimitationItem will be added at the end of the SeqEntry,
387 * \brief Checks if a given Dicom Element exists within the DocEntrySet
388 * @param group Group number of the searched Dicom Element
389 * @param elem Element number of the searched Dicom Element
390 * @return true is found
392 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
394 return GetDocEntry(group,elem)!=NULL;
398 * \brief Build a new DataEntry from all the low level arguments.
399 * Check for existence of dictionary entry, and build
400 * a default one when absent.
401 * @param group Group number of the new Entry
402 * @param elem Element number of the new Entry
403 * @param vr V(alue) R(epresentation) of the new Entry
404 * \remarks The user of this method must destroy the DataEntry when unused
406 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
409 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
411 DataEntry *newEntry = DataEntry::New(dictEntry);
412 dictEntry->Unregister(); // GetDictEntry register it
415 gdcmWarningMacro( "Failed to allocate DataEntry for ("
416 <<std::hex << group << "|" << elem <<")" );
423 * \brief Build a new SeqEntry from all the low level arguments.
424 * Check for existence of dictionary entry, and build
425 * a default one when absent.
426 * @param group Group number of the new Entry
427 * @param elem Element number of the new Entry
428 * \remarks The user of this method must destroy the SeqEntry when unused
430 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
432 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
434 SeqEntry *newEntry = SeqEntry::New( dictEntry );
435 dictEntry->Unregister(); // GetDictEntry register it
438 gdcmWarningMacro( "Failed to allocate SeqEntry for ("
439 <<std::hex << group << "|" << elem <<")" );
445 //-----------------------------------------------------------------------------
448 * \brief Searches [both] the public [and the shadow dictionary (when they
449 * exist)] for the presence of the DictEntry with given
450 * group and element. The public dictionary has precedence on the
451 * shadow one(s), if any.
452 * @param group Group number of the searched DictEntry
453 * @param elem Element number of the searched DictEntry
454 * @return Corresponding DictEntry when it exists, NULL otherwise.
455 * \remarks The returned DictEntry is registered when existing
457 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
459 DictEntry *found = 0;
460 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
463 gdcmWarningMacro( "We SHOULD have a default dictionary");
467 found = pubDict->GetEntry(group, elem);
475 * \brief Searches [both] the public [and the shadow dictionary (when they
476 * exist)] for the presence of the DictEntry with given
477 * group and element, and create a new virtual DictEntry if necessary
478 * @param group group number of the searched DictEntry
479 * @param elem element number of the searched DictEntry
480 * @param vr V(alue) R(epresentation) to use, if necessary
481 * @return Corresponding DictEntry when it exists, NULL otherwise.
482 * \remarks The returned DictEntry is registered
484 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
487 DictEntry *dictEntry = GetDictEntry(group,elem);
488 DictEntry *goodEntry = dictEntry;
496 if ( goodVR != goodEntry->GetVR()
497 && goodVR != GDCM_VRUNKNOWN )
499 gdcmWarningMacro("For (" << std::hex << group << "|"
500 << elem << "), found VR : [" << vr << "]"
501 << " expected: [" << goodEntry->GetVR() << "]" ) ;
502 // avoid confusing further validator with "FIXME" VM
504 vm = dictEntry->GetVM();
507 dictEntry->Unregister();
513 // Create a new virtual DictEntry if necessary
519 goodEntry = DictEntry::New(group, elem, goodVR, vm,//"FIXME",
520 dictEntry->GetName() );
524 goodEntry = DictEntry::New(group, elem, goodVR);
529 goodEntry->Register();
534 //-----------------------------------------------------------------------------
537 //-----------------------------------------------------------------------------
540 //-----------------------------------------------------------------------------
541 } // end namespace gdcm