]> Creatis software - gdcm.git/blob - src/gdcmDocEntrySet.cxx
Typo, comments, doxygenation
[gdcm.git] / src / gdcmDocEntrySet.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntrySet.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/02/11 15:22:18 $
7   Version:   $Revision: 1.55 $
8                                                                                 
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.
12                                                                                 
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.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmDocEntrySet.h"
19
20 #include "gdcmDebug.h"
21 #include "gdcmCommon.h"
22 #include "gdcmDictSet.h"
23 #include "gdcmGlobal.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmSeqEntry.h"
26 #include "gdcmValEntry.h"
27 #include "gdcmBinEntry.h"
28
29 namespace gdcm 
30 {
31 //-----------------------------------------------------------------------------
32 // Constructor / Destructor
33
34 //-----------------------------------------------------------------------------
35 // Public
36 /**
37  * \brief   Get the "std::string representable" value of the Dicom entry
38  * @param   group  Group number of the searched tag.
39  * @param   elem Element number of the searched tag.
40  * @return  Corresponding element value when it exists,
41  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
42  */
43 std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
44 {
45    ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
46    if( entry )
47       return entry->GetValue();
48    return GDCM_UNFOUND;
49 }
50
51 /**
52  * \brief   Gets (from Header) a 'non string' element value 
53  * @param group   group number of the Entry 
54  * @param elem  element number of the Entry
55  * @return Pointer to the 'non string' area
56  */
57 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem) 
58 {
59    BinEntry *entry = GetBinEntry(group, elem);
60    if( entry )
61       return entry->GetBinArea();
62    return 0;
63 }
64
65 /**
66  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
67  *          the public and private dictionaries 
68  *          for the value length of a given tag..
69  * @param   group  Group number of the searched tag.
70  * @param   elem Element number of the searched tag.
71  * @return  Corresponding element length; -2 if not found
72  */
73 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
74 {
75    DocEntry *entry = GetDocEntry(group, elem);
76    if( entry )
77       return entry->GetLength();
78    return -1;
79 }
80
81 /**
82  * \brief   Searches within Header Entries (Dicom Elements) parsed with 
83  *          the public [and private dictionaries] 
84  *          for the element value representation of a given tag..
85  *          Obtaining the VR (Value Representation) might be needed by caller
86  *          to convert the string typed content to caller's native type 
87  *          (think of C++ vs Python). The VR is actually of a higher level
88  *          of semantics than just the native C++ type.
89  * @param   group  Group number of the searched tag.
90  * @param   elem Element number of the searched tag.
91  * @return  Corresponding element value representation when it exists,
92  *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
93  */
94 std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
95 {
96    DocEntry *entry = GetDocEntry(group, elem);
97    if( entry )
98       return entry->GetVR();
99    return GDCM_UNFOUND;
100 }
101
102 /**
103  * \brief  Same as \ref Document::GetDocEntry except it only
104  *         returns a result when the corresponding entry is of type
105  *         ValEntry.
106  * @param   group  Group number of the searched Dicom Element 
107  * @param   elem Element number of the searched Dicom Element  
108  * @return When present, the corresponding ValEntry. 
109  */
110 ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
111 {
112    DocEntry *currentEntry = GetDocEntry(group, elem);
113    if ( !currentEntry )
114       return NULL;
115
116    return dynamic_cast<ValEntry*>(currentEntry);
117 }
118
119 /**
120  * \brief  Same as \ref Document::GetDocEntry except it only
121  *         returns a result when the corresponding entry is of type
122  *         BinEntry.
123  * @param   group  Group number of the searched Dicom Element
124  * @param   elem Element number of the searched Dicom Element
125  * @return When present, the corresponding BinEntry. 
126  */
127 BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
128 {
129    DocEntry *currentEntry = GetDocEntry(group, elem);
130    if ( !currentEntry )
131    {
132       gdcmWarningMacro( "No corresponding BinEntry " << std::hex << group <<
133                          "," << elem);
134       return NULL;
135    }
136
137    return dynamic_cast<BinEntry*>(currentEntry);
138 }
139
140 /**
141  * \brief  Same as \ref Document::GetDocEntry except it only
142  *         returns a result when the corresponding entry is of type
143  *         SeqEntry.
144  * @param   group  Group number of the searched Dicom Element 
145  * @param   elem Element number of the searched Dicom Element  
146  * @return When present, the corresponding SeqEntry. 
147  */
148 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
149 {
150    DocEntry *currentEntry = GetDocEntry(group, elem);
151    if ( !currentEntry )
152    {
153       gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
154                         "," << elem);
155       return NULL;
156    }
157
158    return dynamic_cast<SeqEntry*>(currentEntry);
159 }
160
161 /**
162  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
163  *          through it's (group, element) and modifies it's content with
164  *          the given value.
165  * @param   content new value (string) to substitute with
166  * @param   group  group number of the Dicom Element to modify
167  * @param   elem element number of the Dicom Element to modify
168  */
169 bool DocEntrySet::SetValEntry(std::string const &content, 
170                               uint16_t group, uint16_t elem) 
171 {
172    ValEntry *entry = GetValEntry(group, elem);
173    if (!entry )
174    {
175       gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
176                          "," << elem << " element (try promotion first).");
177       return false;
178    }
179    return SetValEntry(content,entry);
180 }
181
182 /**
183  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
184  *          through it's (group, element) and modifies it's content with
185  *          the given value.
186  * @param   content new value (void*  -> uint8_t*) to substitute with
187  * @param   lgth new value length
188  * @param   group  group number of the Dicom Element to modify
189  * @param   elem element number of the Dicom Element to modify
190  */
191 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, 
192                               uint16_t group, uint16_t elem) 
193 {
194    BinEntry *entry = GetBinEntry(group, elem);
195    if (!entry )
196    {
197       gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
198                         "," << elem << " element (try promotion first).");
199       return false;
200    }
201
202    return SetBinEntry(content,lgth,entry);
203
204
205 /**
206  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
207  *          and modifies it's content with the given value.
208  * @param  content new value (string) to substitute with
209  * @param  entry Entry to be modified
210  */
211 bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
212 {
213    if(entry)
214    {
215       entry->SetValue(content);
216       return true;
217    }
218    return false;
219 }
220
221 /**
222  * \brief   Accesses an existing BinEntry (i.e. a Dicom Element)
223  *          and modifies it's content with the given value.
224  * @param   content new value (void*  -> uint8_t*) to substitute with
225  * @param  entry Entry to be modified 
226  * @param  lgth new value length
227  */
228 bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
229 {
230    if(entry)
231    {
232       entry->SetBinArea(content);  
233       entry->SetLength(lgth);
234       entry->SetValue(GDCM_BINLOADED);
235       return true;
236    }
237    return false;
238 }
239
240 /**
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
248  *          failed).
249  */ 
250 ValEntry *DocEntrySet::InsertValEntry(std::string const &value, 
251                                       uint16_t group, uint16_t elem,
252                                       TagName const &vr )
253 {
254    ValEntry *valEntry = 0;
255    DocEntry *currentEntry = GetDocEntry( group, elem );
256    
257    if (currentEntry)
258    {
259       valEntry = dynamic_cast<ValEntry *>(currentEntry);
260
261       // Verify the VR
262       if( valEntry )
263          if( valEntry->GetVR()!=vr )
264             valEntry = NULL;
265
266       // if currentEntry doesn't correspond to the requested valEntry
267       if( !valEntry)
268       {
269          if( !RemoveEntry(currentEntry) )
270          {
271             gdcmWarningMacro( "Removal of previous DocEntry failed.");
272
273             return NULL;
274          }
275       }
276    }
277
278    // Create a new valEntry if necessary
279    if( !valEntry )
280    {
281       valEntry = NewValEntry( group, elem, vr );
282
283       if ( !AddEntry(valEntry) )
284       {
285          gdcmWarningMacro("AddEntry failed although this is a creation.");
286
287          delete valEntry;
288          return NULL;
289       }
290    }
291
292    // Set the binEntry value
293    SetValEntry(value, valEntry); // The std::string value
294    return valEntry;
295 }
296
297 /**
298  * \brief   Modifies the value of a given Header Entry (Dicom Element)
299  *          when it exists. Create it with the given value when unexistant.
300  *          A copy of the binArea is made to be kept in the Document.
301  * @param   binArea (binary) value to be set
302  * @param   lgth length of the Bin Area we want to set
303  * @param   group   Group number of the Entry 
304  * @param   elem  Element number of the Entry
305  * @param   vr  V(alue) R(epresentation) of the Entry -if private Entry-
306  * \return  pointer to the modified/created Header Entry (NULL when creation
307  *          failed).
308  */
309 BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth, 
310                                       uint16_t group, uint16_t elem,
311                                       TagName const &vr )
312 {
313    BinEntry *binEntry = 0;
314    DocEntry *currentEntry = GetDocEntry( group, elem );
315
316    // Verify the currentEntry
317    if (currentEntry)
318    {
319       binEntry = dynamic_cast<BinEntry *>(currentEntry);
320
321       // Verify the VR
322       if( binEntry )
323          if( binEntry->GetVR()!=vr )
324             binEntry = NULL;
325
326       // if currentEntry doesn't correspond to the requested valEntry
327       if( !binEntry)
328       {
329          if( !RemoveEntry(currentEntry) )
330          {
331             gdcmWarningMacro( "Removal of previous DocEntry failed.");
332
333             return NULL;
334          }
335       }
336    }
337
338    // Create a new binEntry if necessary
339    if( !binEntry)
340    {
341       binEntry = NewBinEntry(group, elem, vr);
342
343       if ( !AddEntry(binEntry) )
344       {
345          gdcmWarningMacro( "AddEntry failed allthough this is a creation.");
346
347          delete binEntry;
348          return NULL;
349       }
350    }
351
352    // Set the binEntry value
353    uint8_t *tmpArea;
354    if( lgth>0 && binArea )
355    {
356       tmpArea = new uint8_t[lgth];
357       memcpy(tmpArea,binArea,lgth);
358    }
359    else
360    {
361       tmpArea = 0;
362    }
363    if( !SetBinEntry(tmpArea,lgth,binEntry) )
364    {
365       if( tmpArea )
366       {
367          delete[] tmpArea;
368       }
369    }
370
371    return binEntry;
372 }  
373
374 /**
375  * \brief   Modifies the value of a given Doc Entry (Dicom Element)
376  *          when it exists. Creates it when unexistant.
377  * @param   group   Group number of the Entry 
378  * @param   elem  Element number of the Entry
379  * \return  pointer to the modified/created SeqEntry (NULL when creation
380  *          failed).
381  */
382 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
383 {
384    SeqEntry *seqEntry = 0;
385    DocEntry *currentEntry = GetDocEntry( group, elem );
386
387    // Verify the currentEntry
388    if( currentEntry )
389    {
390       seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
391
392       // Verify the VR
393       if( seqEntry )
394          seqEntry = NULL;
395
396       // if currentEntry doesn't correspond to the requested seqEntry
397       if( !seqEntry )
398       {
399          if (!RemoveEntry(currentEntry))
400          {
401             gdcmWarningMacro( "Removal of previous DocEntry failed.");
402
403             return NULL;
404          }
405       }
406    }
407    // Create a new seqEntry if necessary
408    if( !seqEntry )
409    {
410       seqEntry = NewSeqEntry(group, elem);
411
412       if( !AddEntry(seqEntry) )
413       {
414          gdcmWarningMacro( "AddEntry failed allthough this is a creation.");
415
416          delete seqEntry;
417          return NULL;
418       }
419    }
420
421    // TODO : Find a trick to insert a SequenceDelimitationItem 
422    //       in the SeqEntry, at the end.
423    return seqEntry;
424
425
426
427  
428 /**
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
433  */
434 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
435 {
436    return GetDocEntry(group,elem)!=NULL;
437 }
438
439 /**
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     VR of the new Entry 
446  */
447 ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
448                                    TagName const &vr) 
449 {
450    DictEntry *dictEntry = GetDictEntry(group, elem, vr);
451    gdcmAssertMacro(dictEntry);
452
453    ValEntry *newEntry = new ValEntry(dictEntry);
454    if (!newEntry) 
455    {
456       gdcmWarningMacro( "Failed to allocate ValEntry");
457       return 0;
458    }
459    return newEntry;
460 }
461
462
463 /**
464  * \brief   Build a new Bin 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  * @param   vr     VR of the new Entry 
470  */
471 BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
472                                    TagName const &vr) 
473 {
474    DictEntry *dictEntry = GetDictEntry(group, elem, vr);
475    gdcmAssertMacro(dictEntry);
476
477    BinEntry *newEntry = new BinEntry(dictEntry);
478    if (!newEntry) 
479    {
480       gdcmWarningMacro( "Failed to allocate BinEntry");
481       return 0;
482    }
483    return newEntry;
484 }
485
486 /**
487  * \brief   Build a new Seq Entry from all the low level arguments. 
488  *          Check for existence of dictionary entry, and build
489  *          a default one when absent.
490  * @param   group group   number of the new Entry
491  * @param   elem  element number of the new Entry
492  */
493 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem) 
494 {
495    DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
496    gdcmAssertMacro(dictEntry);
497
498    SeqEntry *newEntry = new SeqEntry( dictEntry );
499    if (!newEntry)
500    {
501       gdcmWarningMacro( "Failed to allocate SeqEntry");
502       return 0;
503    }
504    return newEntry;
505 }
506
507 /**
508  * \brief   Request a new virtual dict entry to the dict set
509  * @param   group group  number of the underlying DictEntry
510  * @param   elem  element number of the underlying DictEntry
511  * @param   vr    VR (Value Representation) of the underlying DictEntry
512  * @param   vm    VM (Value Multiplicity)   of the underlying DictEntry
513  * @param   name   english name
514  */
515 DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
516                                              TagName const &vr,
517                                              TagName const &vm,
518                                              TagName const &name )
519 {
520    return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
521 }
522
523 //-----------------------------------------------------------------------------
524 // Protected
525 /**
526  * \brief   Searches [both] the public [and the shadow dictionary (when they
527  *          exist)] for the presence of the DictEntry with given
528  *          group and element. The public dictionary has precedence on the
529  *          shadow one.
530  * @param   group  group number of the searched DictEntry
531  * @param   elem element number of the searched DictEntry
532  * @return  Corresponding DictEntry when it exists, NULL otherwise.
533  */
534 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem) 
535 {
536    DictEntry *found = 0;
537    Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
538    if (!pubDict) 
539    {
540       gdcmWarningMacro( "We SHOULD have a default dictionary");
541    }
542    else
543    {
544       found = pubDict->GetEntry(group, elem);  
545    }
546    return found;
547 }
548
549 /**
550  * \brief   Searches [both] the public [and the shadow dictionary (when they
551  *          exist)] for the presence of the DictEntry with given
552  *          group and element, and create a new virtual DictEntry if necessary
553  * @param   group  group number of the searched DictEntry
554  * @param   elem element number of the searched DictEntry
555  * @param   vr Value Representation to use, if necessary 
556  * @return  Corresponding DictEntry when it exists, NULL otherwise.
557  */
558 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
559                                      TagName const &vr)
560 {
561    DictEntry *dictEntry = GetDictEntry(group,elem);
562    DictEntry *goodEntry = dictEntry;
563    std::string goodVR = vr;
564
565    if (elem == 0x0000) goodVR="UL";
566
567    if ( goodEntry )
568    {
569       if ( goodVR != goodEntry->GetVR()
570         && goodVR != GDCM_UNKNOWN )
571       {
572          goodEntry = NULL;
573       }
574    }
575
576    // Create a new virtual DictEntry if necessary
577    if (!goodEntry)
578    {
579       if (dictEntry)
580       {
581          goodEntry = NewVirtualDictEntry(group, elem, goodVR, "FIXME", 
582                                          dictEntry->GetName() );
583       }
584       else
585       {
586          goodEntry = NewVirtualDictEntry(group, elem, goodVR);
587       }
588    }
589    return goodEntry;
590 }
591
592 //-----------------------------------------------------------------------------
593 // Private
594
595 //-----------------------------------------------------------------------------
596 // Print
597
598 //-----------------------------------------------------------------------------
599 } // end namespace gdcm