1 /*=========================================================================
4 Module: $RCSfile: gdcmDocEntrySet.cxx,v $
6 Date: $Date: 2007/09/17 12:16:02 $
7 Version: $Revision: 1.76 $
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
34 namespace GDCM_NAME_SPACE
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 DocEntrySet::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 DocEntrySet::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 its (group, element) and modifies its 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 its (group, element) and modifies its 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 its 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 its 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. Creates 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 else // the 'currentEntry' was not found
245 if ( vr == GDCM_VRUNKNOWN ) // user didn't specify a VR.
246 // Probabely he trusts the Dicom Dict !
249 Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, elem);
252 localVR = e->GetVR();
253 e->Register(); // ?? JPRx
258 // Create a new dataEntry if necessary
261 dataEntry = NewDataEntry( group, elem, localVR );
263 if ( !AddEntry(dataEntry) )
265 gdcmWarningMacro("AddEntry " << dataEntry->GetKey()
266 << " failed although this is a creation.");
270 dataEntry->Delete(); // ?!? JPRx
273 // Set the dataEntry value
274 SetEntryString(value, dataEntry); // The std::string value
279 * \brief Modifies the value of a given Header Entry (Dicom Element)
280 * when it exists. Create it with the given value when unexistant.
281 * A copy of the binArea is made to be kept in the Document.
282 * @param binArea (binary) value to be set
283 * @param lgth length of the Bin Area we want to set
284 * @param group Group number of the Entry
285 * @param elem Element number of the Entry
286 * @param vr V(alue) R(epresentation) of the Entry -if private Entry-
287 * \return pointer to the modified/created Header Entry (NULL when creation
290 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth,
291 uint16_t group, uint16_t elem,
294 DataEntry *dataEntry = 0;
295 DocEntry *currentEntry = GetDocEntry( group, elem );
297 // Verify the currentEntry
300 dataEntry = dynamic_cast<DataEntry *>(currentEntry);
304 if ( dataEntry->GetVR()!=vr )
307 // if currentEntry doesn't correspond to the requested dataEntry
310 if ( !RemoveEntry(currentEntry) )
312 gdcmWarningMacro( "Removal of previous DocEntry failed.");
318 // Create a new dataEntry if necessary
321 dataEntry = NewDataEntry(group, elem, vr);
323 if ( !AddEntry(dataEntry) )
325 gdcmWarningMacro( "AddEntry failed although this is a creation.");
332 // Set the dataEntry value
334 if ( lgth>0 && binArea )
336 tmpArea = new uint8_t[lgth];
337 memcpy(tmpArea,binArea,lgth);
343 if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
354 * \brief Creates a new gdcm::SeqEntry and adds it to the current DocEntrySet.
355 * (remove any existing entry with same group,elem)
356 * @param group Group number of the Entry
357 * @param elem Element number of the Entry
358 * \return pointer to the created SeqEntry (NULL when creation
361 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
363 SeqEntry *seqEntry = 0;
364 DocEntry *currentEntry = GetDocEntry( group, elem );
366 // Verify the currentEntry
369 seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
375 // if currentEntry doesn't correspond to the requested seqEntry
378 if (!RemoveEntry(currentEntry))
380 gdcmWarningMacro( "Removal of previous DocEntry failed for ("
381 <<std::hex << group << "|" << elem <<")" );
386 // Create a new seqEntry if necessary
389 seqEntry = NewSeqEntry(group, elem);
391 if ( !AddEntry(seqEntry) )
393 gdcmWarningMacro( "AddEntry failed although this is a creation for ("
394 <<std::hex << group << "|" << elem <<")" );
401 // SequenceDelimitationItem will be added at the end of the SeqEntry,
407 * \brief Checks if a given Dicom Element exists within the DocEntrySet
408 * @param group Group number of the searched Dicom Element
409 * @param elem Element number of the searched Dicom Element
410 * @return true is found
412 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
414 return GetDocEntry(group,elem)!=NULL;
419 * \brief Build a new DataEntry from all the low level arguments.
420 * @param group Group number of the new Entry
421 * @param elem Element number of the new Entry
422 * @param vr V(alue) R(epresentation) of the new Entry
423 * \remarks The user of this method must destroy the DataEntry when unused
425 DataEntry *DocEntrySet::NewDataEntry(uint16_t group, uint16_t elem,
429 DataEntry *newEntry = DataEntry::New(group, elem, vr);
432 gdcmWarningMacro( "Failed to allocate DataEntry for ("
433 <<std::hex << group << "|" << elem <<")" );
440 * \brief Build a new SeqEntry from all the low level arguments.
441 * @param group Group number of the new Entry
442 * @param elem Element number of the new Entry
443 * \remarks The user of this method must destroy the SeqEntry when unused
445 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem)
447 //DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
449 //SeqEntry *newEntry = SeqEntry::New( dictEntry );
450 SeqEntry *newEntry = SeqEntry::New( group, elem );
451 //dictEntry->Unregister(); // GetDictEntry register it
454 gdcmWarningMacro( "Failed to allocate SeqEntry for ("
455 <<std::hex << group << "|" << elem <<")" );
461 //-----------------------------------------------------------------------------
464 * \brief Searches [both] the public [and the shadow dictionary (when they
465 * exist)] for the presence of the DictEntry with given
466 * group and element. The public dictionary has precedence on the
467 * shadow one(s), if any.
468 * @param group Group number of the searched DictEntry
469 * @param elem Element number of the searched DictEntry
470 * @return Corresponding DictEntry when it exists, NULL otherwise.
471 * \remarks The returned DictEntry is registered when existing
473 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem)
475 DictEntry *found = 0;
476 /// \todo store the DefaultPubDict somwhere, in order not to access the HTable
477 /// every time ! --> Done!
478 Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
481 gdcmWarningMacro( "We SHOULD have a default dictionary");
485 found = pubDict->GetEntry(group, elem);
492 //-----------------------------------------------------------------------------
495 //-----------------------------------------------------------------------------
498 //-----------------------------------------------------------------------------
499 } // end namespace gdcm