1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2005/10/27 09:13:18 $
7 Version: $Revision: 1.67 $
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);
159 return dynamic_cast<SeqEntry*>(currentEntry);
163 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
164 * through it's (group, element) and modifies it's content with
166 * @param content new value (string) to substitute with
167 * @param group group number of the Dicom Element to modify
168 * @param elem element number of the Dicom Element to modify
170 bool DocEntrySet::SetEntryString(std::string const &content,
171 uint16_t group, uint16_t elem)
173 DataEntry *entry = GetDataEntry(group, elem);
176 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
177 "," << elem << " element (try promotion first).");
180 return SetEntryString(content,entry);
184 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
185 * through it's (group, element) and modifies it's content with
187 * @param content new value (void* -> uint8_t*) to substitute with
188 * @param lgth new value length
189 * @param group group number of the Dicom Element to modify
190 * @param elem element number of the Dicom Element to modify
192 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth,
193 uint16_t group, uint16_t elem)
195 DataEntry *entry = GetDataEntry(group, elem);
198 gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
199 "," << elem << " element (try promotion first).");
203 return SetEntryBinArea(content,lgth,entry);
207 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
208 * and modifies it's content with the given value.
209 * @param content new value (string) to substitute with
210 * @param entry Entry to be modified
212 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
216 entry->SetString(content);
223 * \brief Accesses an existing DataEntry (i.e. a Dicom Element)
224 * and modifies it's content with the given value.
225 * @param content new value (void* -> uint8_t*) to substitute with
226 * @param entry Entry to be modified
227 * @param lgth new value length
229 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
233 entry->SetLength(lgth);
234 entry->SetBinArea(content);
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 DataEntry *DocEntrySet::InsertEntryString(std::string const &value,
251 uint16_t group, uint16_t elem,
254 DataEntry *dataEntry = 0;
255 DocEntry *currentEntry = GetDocEntry( group, elem );
259 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
263 if ( dataEntry->GetVR()!=vr )
266 // if currentEntry doesn't correspond to the requested dataEntry
269 if ( !RemoveEntry(currentEntry) )
271 gdcmWarningMacro( "Removal of previous DocEntry failed.");
277 // Create a new dataEntry if necessary
280 dataEntry = NewDataEntry( group, elem, vr );
282 if ( !AddEntry(dataEntry) )
284 gdcmWarningMacro("AddEntry failed although this is a creation.");
291 // Set the dataEntry value
292 SetEntryString(value, dataEntry); // The std::string value
297 * \brief Modifies the value of a given Header Entry (Dicom Element)
298 * when it exists. Create it with the given value when unexistant.
299 * A copy of the binArea is made to be kept in the Document.
300 * @param binArea (binary) value to be set
301 * @param lgth length of the Bin Area we want to set
302 * @param group Group number of the Entry
303 * @param elem Element number of the Entry
304 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
305 * \return pointer to the modified/created Header Entry (NULL when creation
308 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
309 uint16_t group, uint16_t elem,
312 DataEntry *dataEntry = 0;
313 DocEntry *currentEntry = GetDocEntry( group, elem );
315 // Verify the currentEntry
318 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
322 if ( dataEntry->GetVR()!=vr )
325 // if currentEntry doesn't correspond to the requested dataEntry
328 if ( !RemoveEntry(currentEntry) )
330 gdcmWarningMacro( "Removal of previous DocEntry failed.");
336 // Create a new dataEntry if necessary
339 dataEntry = NewDataEntry(group, elem, vr);
341 if ( !AddEntry(dataEntry) )
343 gdcmWarningMacro( "AddEntry failed although this is a creation.");
350 // Set the dataEntry value
352 if ( lgth>0 && binArea )
354 tmpArea = new uint8_t[lgth];
355 memcpy(tmpArea,binArea,lgth);
361 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
373 * \brief Modifies the value of a given Doc Entry (Dicom Element)
374 * when it exists. Creates it when unexistant.
375 * @param group Group number of the Entry
376 * @param elem Element number of the Entry
377 * \return pointer to the modified/created SeqEntry (NULL when creation
380 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
382 SeqEntry *seqEntry = 0;
383 DocEntry *currentEntry = GetDocEntry( group, elem );
385 // Verify the currentEntry
388 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
394 // if currentEntry doesn't correspond to the requested seqEntry
397 if (!RemoveEntry(currentEntry))
399 gdcmWarningMacro( "Removal of previous DocEntry failed.");
405 // Create a new seqEntry if necessary
408 seqEntry = NewSeqEntry(group, elem);
410 if ( !AddEntry(seqEntry) )
412 gdcmWarningMacro( "AddEntry failed although this is a creation.");
419 // TODO : Find a trick to insert a SequenceDelimitationItem
420 // in the SeqEntry, at the end.
425 * \brief Checks if a given Dicom Element exists within the H table
426 * @param group Group number of the searched Dicom Element
427 * @param elem Element number of the searched Dicom Element
428 * @return true is found
430 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
432 return GetDocEntry(group,elem)!=NULL;
436 * \brief Build a new Val Entry from all the low level arguments.
437 * Check for existence of dictionary entry, and build
438 * a default one when absent.
439 * @param group Group number of the new Entry
440 * @param elem Element number of the new Entry
441 * @param vr V(alue) R(epresentation) of the new Entry
442 * \remarks The user of this method must destroy the DataEntry when unused
444 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
447 DictEntry *dictEntry = GetDictEntry(group, elem, vr);
449 DataEntry *newEntry = DataEntry::New(dictEntry);
450 dictEntry->Unregister(); // GetDictEntry register it
453 gdcmWarningMacro( "Failed to allocate DataEntry");
460 * \brief Build a new Seq Entry from all the low level arguments.
461 * Check for existence of dictionary entry, and build
462 * a default one when absent.
463 * @param group Group number of the new Entry
464 * @param elem Element number of the new Entry
465 * \remarks The user of this method must destroy the SeqEntry when unused
467 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
469 DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
471 SeqEntry *newEntry = SeqEntry::New( dictEntry );
472 dictEntry->Unregister(); // GetDictEntry register it
475 gdcmWarningMacro( "Failed to allocate SeqEntry");
481 //-----------------------------------------------------------------------------
484 * \brief Searches [both] the public [and the shadow dictionary (when they
485 * exist)] for the presence of the DictEntry with given
486 * group and element. The public dictionary has precedence on the
487 * shadow one(s), if any.
488 * @param group Group number of the searched DictEntry
489 * @param elem Element number of the searched DictEntry
490 * @return Corresponding DictEntry when it exists, NULL otherwise.
491 * \remarks The returned DictEntry is registered when existing
493 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
495 DictEntry *found = 0;
496 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
499 gdcmWarningMacro( "We SHOULD have a default dictionary");
503 found = pubDict->GetEntry(group, elem);
511 * \brief Searches [both] the public [and the shadow dictionary (when they
512 * exist)] for the presence of the DictEntry with given
513 * group and element, and create a new virtual DictEntry if necessary
514 * @param group group number of the searched DictEntry
515 * @param elem element number of the searched DictEntry
516 * @param vr V(alue) R(epresentation) to use, if necessary
517 * @return Corresponding DictEntry when it exists, NULL otherwise.
518 * \remarks The returned DictEntry is registered
520 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
523 DictEntry *dictEntry = GetDictEntry(group,elem);
524 DictEntry *goodEntry = dictEntry;
532 if ( goodVR != goodEntry->GetVR()
533 && goodVR != GDCM_VRUNKNOWN )
537 dictEntry->Unregister();
540 // Create a new virtual DictEntry if necessary
545 goodEntry = DictEntry::New(group, elem, goodVR, "FIXME",
546 dictEntry->GetName() );
550 goodEntry = DictEntry::New(group, elem, goodVR);
555 goodEntry->Register();
560 //-----------------------------------------------------------------------------
563 //-----------------------------------------------------------------------------
566 //-----------------------------------------------------------------------------
567 } // end namespace gdcm