]> Creatis software - gdcm.git/blob - src/gdcmDocEntrySet.cxx
Remove useless warning message
[gdcm.git] / src / gdcmDocEntrySet.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDocEntrySet.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/10/27 09:13:18 $
7   Version:   $Revision: 1.67 $
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 "gdcmUtil.h"
27 #include "gdcmDataEntry.h"
28 #include "gdcmVR.h"
29
30 namespace gdcm 
31 {
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 DocEntrySet::DocEntrySet() 
35
36    PreviousDocEntry = 0;
37 }
38 //-----------------------------------------------------------------------------
39 // Public
40 /**
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.
46  */
47 std::string DocEntrySet::GetEntryString(uint16_t group, uint16_t elem)
48 {
49    DataEntry *entry = dynamic_cast<DataEntry *>(GetDocEntry(group,elem));
50    if ( entry )
51    {
52       if( entry->IsNotLoaded() )
53          return GDCM_NOTLOADED;
54       if( entry->IsUnfound() )
55          return GDCM_UNFOUND;
56       if( entry->IsUnread() )
57          return GDCM_UNREAD;
58       return entry->GetString();
59    }
60    return GDCM_UNFOUND;
61 }
62
63 /**
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
68  */
69 void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem) 
70 {
71    DataEntry *entry = GetDataEntry(group, elem);
72    if ( entry )
73       return entry->GetBinArea();
74    return 0;
75 }
76
77 /**
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.
83  */
84 std::string DocEntrySet::GetEntryForcedAsciiValue(uint16_t group, uint16_t elem)
85 {
86    DocEntry *d = GetDocEntry(group,elem);
87    if ( !d )
88       return GDCM_UNFOUND;
89
90    DataEntry *de = dynamic_cast<DataEntry *>(d);
91    if ( de )
92    {
93       if( de->IsNotLoaded() )
94          return GDCM_NOTLOADED;
95       if( de->IsUnfound() )
96          return GDCM_UNFOUND;
97       if( de->IsUnread() )
98          return GDCM_UNREAD;
99    }
100
101    if( Global::GetVR()->IsVROfStringRepresentable( de->GetVR() ) )
102       return de->GetString();
103    else
104    {
105       uint8_t *a = de->GetBinArea();
106       if( Util::IsCleanArea(a, de->GetLength()) )
107          return  Util::CreateCleanString(a, de->GetLength());
108    }
109    return GDCM_NOTASCII;
110 }
111
112 /**
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
119  */
120 int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
121 {
122    DocEntry *entry = GetDocEntry(group, elem);
123    if ( entry )
124       return entry->GetLength();
125    return -1;
126 }
127
128 /**
129  * \brief  Same as \ref Document::GetDocEntry except it only
130  *         returns a result when the corresponding entry is of type
131  *         DataEntry.
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. 
135  */
136 DataEntry *DocEntrySet::GetDataEntry(uint16_t group, uint16_t elem)
137 {
138    DocEntry *currentEntry = GetDocEntry(group, elem);
139    if ( !currentEntry )
140       return NULL;
141
142    return dynamic_cast<DataEntry*>(currentEntry);
143 }
144
145 /**
146  * \brief  Same as \ref Document::GetDocEntry except it only
147  *         returns a result when the corresponding entry is of type
148  *         SeqEntry.
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. 
152  */
153 SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
154 {
155    DocEntry *currentEntry = GetDocEntry(group, elem);
156    if ( !currentEntry )
157       return NULL;
158       
159    return dynamic_cast<SeqEntry*>(currentEntry);
160 }
161
162 /**
163  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
164  *          through it's (group, element) and modifies it's content with
165  *          the given value.
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
169  */
170 bool DocEntrySet::SetEntryString(std::string const &content, 
171                                  uint16_t group, uint16_t elem) 
172 {
173    DataEntry *entry = GetDataEntry(group, elem);
174    if (!entry )
175    {
176       gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
177                          "," << elem << " element (try promotion first).");
178       return false;
179    }
180    return SetEntryString(content,entry);
181 }
182
183 /**
184  * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
185  *          through it's (group, element) and modifies it's content with
186  *          the given value.
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
191  */
192 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, 
193                                   uint16_t group, uint16_t elem) 
194 {
195    DataEntry *entry = GetDataEntry(group, elem);
196    if (!entry )
197    {
198       gdcmWarningMacro( "No corresponding DataEntry " << std::hex << group <<
199                         "," << elem << " element (try promotion first).");
200       return false;
201    }
202
203    return SetEntryBinArea(content,lgth,entry);
204
205
206 /**
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
211  */
212 bool DocEntrySet::SetEntryString(std::string const &content, DataEntry *entry)
213 {
214    if (entry)
215    {
216       entry->SetString(content);
217       return true;
218    }
219    return false;
220 }
221
222 /**
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
228  */
229 bool DocEntrySet::SetEntryBinArea(uint8_t *content, int lgth, DataEntry *entry)
230 {
231    if (entry)
232    {
233       entry->SetLength(lgth);
234       entry->SetBinArea(content);  
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 DataEntry *DocEntrySet::InsertEntryString(std::string const &value, 
251                                              uint16_t group, uint16_t elem,
252                                              VRKey const &vr )
253 {
254    DataEntry *dataEntry = 0;
255    DocEntry *currentEntry = GetDocEntry( group, elem );
256    
257    if (currentEntry)
258    {
259       dataEntry = dynamic_cast<DataEntry *>(currentEntry);
260
261       // Verify the VR
262       if ( dataEntry )
263          if ( dataEntry->GetVR()!=vr )
264             dataEntry = NULL;
265
266       // if currentEntry doesn't correspond to the requested dataEntry
267       if ( !dataEntry)
268       {
269          if ( !RemoveEntry(currentEntry) )
270          {
271             gdcmWarningMacro( "Removal of previous DocEntry failed.");
272             return NULL;
273          }
274       }
275    }
276
277    // Create a new dataEntry if necessary
278    if ( !dataEntry )
279    {
280       dataEntry = NewDataEntry( group, elem, vr );
281
282       if ( !AddEntry(dataEntry) )
283       {
284          gdcmWarningMacro("AddEntry failed although this is a creation.");
285          dataEntry->Delete();
286          return NULL;
287       }
288       dataEntry->Delete();
289    }
290
291    // Set the dataEntry value
292    SetEntryString(value, dataEntry); // The std::string value
293    return dataEntry;
294 }
295
296 /**
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
306  *          failed).
307  */
308 DataEntry *DocEntrySet::InsertEntryBinArea(uint8_t *binArea, int lgth, 
309                                               uint16_t group, uint16_t elem,
310                                               VRKey const &vr )
311 {
312    DataEntry *dataEntry = 0;
313    DocEntry *currentEntry = GetDocEntry( group, elem );
314
315    // Verify the currentEntry
316    if (currentEntry)
317    {
318       dataEntry = dynamic_cast<DataEntry *>(currentEntry);
319
320       // Verify the VR
321       if ( dataEntry )
322          if ( dataEntry->GetVR()!=vr )
323             dataEntry = NULL;
324
325       // if currentEntry doesn't correspond to the requested dataEntry
326       if ( !dataEntry)
327       {
328          if ( !RemoveEntry(currentEntry) )
329          {
330             gdcmWarningMacro( "Removal of previous DocEntry failed.");
331             return NULL;
332          }
333       }
334    }
335
336    // Create a new dataEntry if necessary
337    if ( !dataEntry)
338    {
339       dataEntry = NewDataEntry(group, elem, vr);
340
341       if ( !AddEntry(dataEntry) )
342       {
343          gdcmWarningMacro( "AddEntry failed although this is a creation.");
344          dataEntry->Delete();
345          return NULL;
346       }
347       dataEntry->Delete();
348    }
349
350    // Set the dataEntry value
351    uint8_t *tmpArea;
352    if ( lgth>0 && binArea )
353    {
354       tmpArea = new uint8_t[lgth];
355       memcpy(tmpArea,binArea,lgth);
356    }
357    else
358    {
359       tmpArea = 0;
360    }
361    if ( !SetEntryBinArea(tmpArea,lgth,dataEntry) )
362    {
363       if ( tmpArea )
364       {
365          delete[] tmpArea;
366       }
367    }
368
369    return dataEntry;
370 }  
371
372 /**
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
378  *          failed).
379  */
380 SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
381 {
382    SeqEntry *seqEntry = 0;
383    DocEntry *currentEntry = GetDocEntry( group, elem );
384
385    // Verify the currentEntry
386    if ( currentEntry )
387    {
388       seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
389
390       // Verify the VR
391       if ( seqEntry )
392          seqEntry = NULL;
393
394       // if currentEntry doesn't correspond to the requested seqEntry
395       if ( !seqEntry )
396       {
397          if (!RemoveEntry(currentEntry))
398          {
399             gdcmWarningMacro( "Removal of previous DocEntry failed.");
400
401             return NULL;
402          }
403       }
404    }
405    // Create a new seqEntry if necessary
406    if ( !seqEntry )
407    {
408       seqEntry = NewSeqEntry(group, elem);
409
410       if ( !AddEntry(seqEntry) )
411       {
412          gdcmWarningMacro( "AddEntry failed although this is a creation.");
413          seqEntry->Delete();
414          return NULL;
415       }
416       seqEntry->Delete();
417    }
418
419    // TODO : Find a trick to insert a SequenceDelimitationItem 
420    //       in the SeqEntry, at the end.
421    return seqEntry;
422
423  
424 /**
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
429  */
430 bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
431 {
432    return GetDocEntry(group,elem)!=NULL;
433 }
434
435 /**
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
443  */
444 DataEntry *DocEntrySet::NewDataEntry(uint16_t group,uint16_t elem,
445                                      VRKey const &vr) 
446 {
447    DictEntry *dictEntry = GetDictEntry(group, elem, vr);
448
449    DataEntry *newEntry = DataEntry::New(dictEntry);
450    dictEntry->Unregister(); // GetDictEntry register it
451    if (!newEntry) 
452    {
453       gdcmWarningMacro( "Failed to allocate DataEntry");
454       return 0;
455    }
456    return newEntry;
457 }
458
459 /**
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
466  */
467 SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem) 
468 {
469    DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
470
471    SeqEntry *newEntry = SeqEntry::New( dictEntry );
472    dictEntry->Unregister(); // GetDictEntry register it
473    if (!newEntry)
474    {
475       gdcmWarningMacro( "Failed to allocate SeqEntry");
476       return 0;
477    }
478    return newEntry;
479 }
480
481 //-----------------------------------------------------------------------------
482 // Protected
483 /**
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
492  */
493 DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem) 
494 {
495    DictEntry *found = 0;
496    Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
497    if (!pubDict) 
498    {
499       gdcmWarningMacro( "We SHOULD have a default dictionary");
500    }
501    else
502    {
503       found = pubDict->GetEntry(group, elem);
504       if( found )
505          found->Register();
506    }
507    return found;
508 }
509
510 /**
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
519  */
520 DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
521                                      VRKey const &vr)
522 {
523    DictEntry *dictEntry = GetDictEntry(group,elem);
524    DictEntry *goodEntry = dictEntry;
525    VRKey goodVR = vr;
526
527    if (elem == 0x0000) 
528       goodVR="UL";
529
530    if ( goodEntry )
531    {
532       if ( goodVR != goodEntry->GetVR()
533         && goodVR != GDCM_VRUNKNOWN )
534       {
535          goodEntry = NULL;
536       }
537       dictEntry->Unregister();
538    }
539
540    // Create a new virtual DictEntry if necessary
541    if (!goodEntry)
542    {
543       if (dictEntry)
544       {
545          goodEntry = DictEntry::New(group, elem, goodVR, "FIXME", 
546                                     dictEntry->GetName() );
547       }
548       else
549       {
550          goodEntry = DictEntry::New(group, elem, goodVR);
551       }
552    }
553    else
554    {
555       goodEntry->Register();
556    }
557    return goodEntry;
558 }
559
560 //-----------------------------------------------------------------------------
561 // Private
562
563 //-----------------------------------------------------------------------------
564 // Print
565
566 //-----------------------------------------------------------------------------
567 } // end namespace gdcm