1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2006/03/22 13:19:25 $
7 Version: $Revision: 1.71 $
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"
30 #if defined(__BORLANDC__)
31 #include <mem.h> // for memset
36 //-----------------------------------------------------------------------------
37 // Constructor / Destructor
38 DocEntrySet::DocEntrySet()
42 //-----------------------------------------------------------------------------
45 * \brief Get the "std::string representable" value of the Dicom entry
46 * @param group Group number of the searched tag.
47 * @param elem Element number of the searched tag.
48 * @return Corresponding element value when it exists,
49 * and the string GDCM_UNFOUND otherwise.
51 std::string DocEntrySet::GetEntryString(uint16_t group, uint16_t elem)
53 DataEntry *entry = dynamic_cast<DataEntry *>(GetDocEntry(group,elem));
56 if( entry->IsNotLoaded() )
57 return GDCM_NOTLOADED;
58 if( entry->IsUnfound() )
60 if( entry->IsUnread() )
62 return entry->GetString();
68 * \brief Gets (from Header) a 'non string' element value
69 * @param group group number of the Entry
70 * @param elem element number of the Entry
71 * @return Pointer to the 'non string' area
73 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem)
75 DataEntry *entry = GetDataEntry(group, elem);
77 return entry->GetBinArea();
82 * \brief Searches within the DocEntrySet
83 * for the value length of a given tag..
84 * @param group Group number of the searched tag.
85 * @param elem Element number of the searched tag.
86 * @return Corresponding element length; -1 if not found
88 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
90 DocEntry *entry = GetDocEntry(group, elem);
92 return entry->GetLength();
97 * \brief Same as \ref Document::GetDocEntry except it returns a result
98 * only when the corresponding entry is of type DataEntry.
99 * @param group Group number of the searched Dicom Element
100 * @param elem Element number of the searched Dicom Element
101 * @return When present, the corresponding DataEntry.
103 DataEntry *DocEntrySet::GetDataEntry(uint16_t group, uint16_t elem)
105 DocEntry *currentEntry = GetDocEntry(group, elem);
109 return dynamic_cast<DataEntry*>(currentEntry);
113 * \brief Same as \ref Document::GetDocEntry except it returns a result
114 * only when the corresponding entry is of type SeqEntry.
115 * @param group Group number of the searched Dicom Element
116 * @param elem Element number of the searched Dicom Element
117 * @return When present, the corresponding SeqEntry.
119 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
121 DocEntry *currentEntry = GetDocEntry(group, elem);
125 return dynamic_cast<SeqEntry*>(currentEntry);
129 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
130 * through it's (group, element) and modifies it's content with
132 * @param content new value (string) to substitute with
133 * @param group group number of the Dicom Element to modify
134 * @param elem element number of the Dicom Element to modify
136 bool DocEntrySet::SetEntryString(std::string const &content,
137 uint16_t group, uint16_t elem)
139 DataEntry *entry = GetDataEntry(group, elem);
142 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
143 "," << elem << " element (try promotion first).");
146 return SetEntryString(content,entry);
150 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
151 * through it's (group, element) and modifies it's content with
153 * @param content new value (void* -> uint8_t*) to substitute with
154 * @param lgth new value length
155 * @param group group number of the Dicom Element to modify
156 * @param elem element number of the Dicom Element to modify
158 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth,
159 uint16_t group, uint16_t elem)
161 DataEntry *entry = GetDataEntry(group, elem);
164 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
165 "," << elem << " element (try promotion first).");
169 return SetEntryBinArea(content,lgth,entry);
173 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
174 * and modifies it's content with the given value.
175 * @param content new value (string) to substitute with
176 * @param entry Entry to be modified
178 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
182 entry->SetString(content);
189 * \brief Accesses an existing DataEntry (i.e. a Dicom Element)
190 * and modifies it's content with the given value.
191 * @param content new value (void* -> uint8_t*) to substitute with
192 * @param entry Entry to be modified
193 * @param lgth new value length
195 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
199 entry->SetLength(lgth);
200 entry->SetBinArea(content);
207 * \brief Modifies the value of a given Doc Entry (Dicom Element)
208 * when it exists. Create it with the given value when unexistant.
209 * @param value (string) Value to be set
210 * @param group Group number of the Entry
211 * @param elem Element number of the Entry
212 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
213 * \return pointer to the modified/created Header Entry (NULL when creation
216 DataEntry *DocEntrySet::InsertEntryString(std::string const &value,
217 uint16_t group, uint16_t elem,
220 DataEntry *dataEntry = 0;
221 DocEntry *currentEntry = GetDocEntry( group, elem );
225 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
229 if ( dataEntry->GetVR()!=vr )
232 // if currentEntry doesn't correspond to the requested dataEntry
235 if ( !RemoveEntry(currentEntry) )
237 gdcmWarningMacro( "Removal of previous DocEntry failed.");
243 // Create a new dataEntry if necessary
246 dataEntry = NewDataEntry( group, elem, vr );
248 if ( !AddEntry(dataEntry) )
250 gdcmWarningMacro("AddEntry failed although this is a creation.");
257 // Set the dataEntry value
258 SetEntryString(value, dataEntry); // The std::string value
263 * \brief Modifies the value of a given Header Entry (Dicom Element)
264 * when it exists. Create it with the given value when unexistant.
265 * A copy of the binArea is made to be kept in the Document.
266 * @param binArea (binary) value to be set
267 * @param lgth length of the Bin Area we want to set
268 * @param group Group number of the Entry
269 * @param elem Element number of the Entry
270 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
271 * \return pointer to the modified/created Header Entry (NULL when creation
274 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
275 uint16_t group, uint16_t elem,
278 DataEntry *dataEntry = 0;
279 DocEntry *currentEntry = GetDocEntry( group, elem );
281 // Verify the currentEntry
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
318 if ( lgth>0 && binArea )
320 tmpArea = new uint8_t[lgth];
321 memcpy(tmpArea,binArea,lgth);
327 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
338 * \brief Creates a new gdcm::SeqEntry and adds it to the current DocEntrySet.
339 * (remove any existing entry with same group,elem)
340 * @param group Group number of the Entry
341 * @param elem Element number of the Entry
342 * \return pointer to the created SeqEntry (NULL when creation
345 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
347 SeqEntry *seqEntry = 0;
348 DocEntry *currentEntry = GetDocEntry( group, elem );
350 // Verify the currentEntry
353 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
359 // if currentEntry doesn't correspond to the requested seqEntry
362 if (!RemoveEntry(currentEntry))
364 gdcmWarningMacro( "Removal of previous DocEntry failed for ("
365 <<std::hex << group << "|" << elem <<")" );
370 // Create a new seqEntry if necessary
373 seqEntry = NewSeqEntry(group, elem);
375 if ( !AddEntry(seqEntry) )
377 gdcmWarningMacro( "AddEntry failed although this is a creation for ("
378 <<std::hex << group << "|" << elem <<")" );
385 // SequenceDelimitationItem will be added at the end of the SeqEntry,
391 * \brief Checks if a given Dicom Element exists within the DocEntrySet
392 * @param group Group number of the searched Dicom Element
393 * @param elem Element number of the searched Dicom Element
394 * @return true is found
396 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
398 return GetDocEntry(group,elem)!=NULL;
402 * \brief Build a new DataEntry from all the low level arguments.
403 * Check for existence of dictionary entry, and build
404 * a default one when absent.
405 * @param group Group number of the new Entry
406 * @param elem Element number of the new Entry
407 * @param vr V(alue) R(epresentation) of the new Entry
408 * \remarks The user of this method must destroy the DataEntry when unused
410 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
413 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
415 DataEntry *newEntry = DataEntry::New(dictEntry);
416 dictEntry->Unregister(); // GetDictEntry register it
419 gdcmWarningMacro( "Failed to allocate DataEntry for ("
420 <<std::hex << group << "|" << elem <<")" );
427 * \brief Build a new SeqEntry from all the low level arguments.
428 * Check for existence of dictionary entry, and build
429 * a default one when absent.
430 * @param group Group number of the new Entry
431 * @param elem Element number of the new Entry
432 * \remarks The user of this method must destroy the SeqEntry when unused
434 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
436 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
438 SeqEntry *newEntry = SeqEntry::New( dictEntry );
439 dictEntry->Unregister(); // GetDictEntry register it
442 gdcmWarningMacro( "Failed to allocate SeqEntry for ("
443 <<std::hex << group << "|" << elem <<")" );
449 //-----------------------------------------------------------------------------
452 * \brief Searches [both] the public [and the shadow dictionary (when they
453 * exist)] for the presence of the DictEntry with given
454 * group and element. The public dictionary has precedence on the
455 * shadow one(s), if any.
456 * @param group Group number of the searched DictEntry
457 * @param elem Element number of the searched DictEntry
458 * @return Corresponding DictEntry when it exists, NULL otherwise.
459 * \remarks The returned DictEntry is registered when existing
461 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
463 DictEntry *found = 0;
464 /// \todo store the DefaultPubDict somwhere, in order not to access the HTable
466 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
469 gdcmWarningMacro( "We SHOULD have a default dictionary");
473 found = pubDict->GetEntry(group, elem);
481 * \brief Searches [both] the public [and the shadow dictionary (when they
482 * exist)] for the presence of the DictEntry with given
483 * group and element, and creates a new virtual DictEntry if necessary
484 * @param group group number of the searched DictEntry
485 * @param elem element number of the searched DictEntry
486 * @param vr V(alue) R(epresentation) to use, if necessary
487 * @return Corresponding DictEntry when it exists, NULL otherwise.
488 * \remarks The returned DictEntry is registered
490 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
493 DictEntry *dictEntry = GetDictEntry(group,elem);
494 DictEntry *goodEntry = dictEntry;
502 if ( goodVR != goodEntry->GetVR()
503 && goodVR != GDCM_VRUNKNOWN )
505 gdcmWarningMacro("For (" << std::hex << group << "|"
506 << elem << "), found VR : [" << vr << "]"
507 << " expected: [" << goodEntry->GetVR() << "]" ) ;
508 // avoid confusing further validator with "FIXME" VM
510 vm = dictEntry->GetVM();
513 dictEntry->Unregister();
519 // Create a new virtual DictEntry if necessary
525 goodEntry = DictEntry::New(group, elem, goodVR, vm,
526 dictEntry->GetName() );
530 goodEntry = DictEntry::New(group, elem, goodVR);
535 goodEntry->Register();
540 //-----------------------------------------------------------------------------
543 //-----------------------------------------------------------------------------
546 //-----------------------------------------------------------------------------
547 } // end namespace gdcm