]> Creatis software - gdcm.git/blob - src/gdcmDict.cxx
Doxygenation
[gdcm.git] / src / gdcmDict.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDict.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/01/06 17:08:06 $
7   Version:   $Revision: 1.53 $
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
19 #include "gdcmDict.h"
20 #include "gdcmUtil.h"
21 #include "gdcmDebug.h"
22
23 #include <fstream>
24 #include <iostream>
25 #include <iomanip>
26
27 namespace gdcm 
28 {
29 void FillDefaultDataDict(Dict *d);
30 //-----------------------------------------------------------------------------
31 // Constructor / Destructor
32 /**
33  * \brief   Constructor
34  * @param   filename from which to build the dictionary.
35  */
36 Dict::Dict(std::string const &filename)
37 {
38    uint16_t group;
39    uint16_t element;
40    TagName vr;
41    TagName fourth;
42    TagName name;
43
44    std::ifstream from( filename.c_str() );
45    if( !from )
46    {
47       dbg.Verbose(2,"Dict::Dict: can't open dictionary", filename.c_str());
48       // Using default embeded one:
49       FillDefaultDataDict( this );
50    }
51    else
52    {
53       while (!from.eof())
54       {
55          from >> std::hex;
56          from >> group;
57          from >> element;
58          from >> vr;
59          from >> fourth;
60          from >> std::ws;  //remove white space
61          std::getline(from, name);
62    
63          const DictEntry newEntry(group, element, vr, fourth, name);
64          AddNewEntry(newEntry);
65       }
66
67       Filename = filename;
68    }
69    from.close();
70 }
71
72 /**
73  * \brief  Destructor 
74  */
75 Dict::~Dict()
76 {
77    // Since AddNewEntry adds symetrical in both KeyHt and NameHT we can
78    // assume all the pointed DictEntries are already cleaned-up when
79    // we cleaned KeyHt.
80    KeyHt.clear();
81    NameHt.clear();
82 }
83
84 //-----------------------------------------------------------------------------
85 // Print
86 /**
87  * \brief   Print all the dictionary entries contained in this dictionary.
88  *          Entries will be sorted by tag i.e. the couple (group, element).
89  * @param   os The output stream to be written to.
90  */
91 void Dict::Print(std::ostream &os)
92 {
93    os << "Dict file name : " << Filename << std::endl;
94    PrintByKey(os);
95 }
96
97 /**
98  * \brief   Print all the dictionary entries contained in this dictionary.
99  *          Entries will be sorted by tag i.e. the couple (group, element).
100  * @param   os The output stream to be written to.
101  */
102 void Dict::PrintByKey(std::ostream &os)
103 {
104    std::ostringstream s;
105
106    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
107    {
108       s << "Entry : ";
109       s << "(" << std::hex << std::setw(4) << tag->second.GetGroup() << ',';
110       s << std::hex << std::setw(4) << tag->second.GetElement() << ") = "
111         << std::dec;
112       s << tag->second.GetVR() << ", ";
113       s << tag->second.GetFourth() << ", ";
114       s << tag->second.GetName() << "."  << std::endl;
115    }
116    os << s.str();
117 }
118
119 /**
120  * \brief   Print all the dictionary entries contained in this dictionary.
121  *          Entries will be sorted by the name of the dictionary entries.
122  * \warning AVOID USING IT : the name IS NOT an identifier; 
123  *                           unpredictable result
124  * @param   os The output stream to be written to.
125  */
126 void Dict::PrintByName(std::ostream &os)
127 {
128    std::ostringstream s;
129
130    for (TagNameHT::iterator tag = NameHt.begin(); tag != NameHt.end(); ++tag)
131    {
132       s << "Entry : ";
133       s << tag->second.GetName() << ",";
134       s << tag->second.GetVR() << ", ";
135       s << tag->second.GetFourth() << ", ";
136       s << "(" << std::hex << std::setw(4) << tag->second.GetGroup() << ',';
137       s << std::hex << std::setw(4) << tag->second.GetElement() << ") = ";
138       s << std::dec << std::endl;
139    }
140    os << s.str();
141 }
142
143 //-----------------------------------------------------------------------------
144 // Public
145 /**
146  * \ingroup Dict
147  * \brief  adds a new Dicom Dictionary Entry 
148  * @param   newEntry entry to add 
149  * @return  false if Dicom Element already exists
150  */
151 bool Dict::AddNewEntry(DictEntry const &newEntry) 
152 {
153    const TagKey &key = newEntry.GetKey();
154
155    if(KeyHt.count(key) == 1)
156    {
157       dbg.Verbose(1, "Dict::AddNewEntry already present", key.c_str());
158       return false;
159    } 
160    else 
161    {
162       KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
163       NameHt.insert( TagNameHT::value_type(newEntry.GetName(), newEntry ));
164       return true;
165    }
166 }
167
168 /**
169  * \ingroup Dict
170  * \brief  replaces an already existing Dicom Element by a new one
171  * @param   newEntry new entry (overwrites any previous one with same tag)
172  * @return  false if Dicom Element doesn't exist
173  */
174 bool Dict::ReplaceEntry(DictEntry const &newEntry)
175 {
176    if ( RemoveEntry(newEntry.GetKey()) )
177    {
178        KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
179        NameHt.insert( TagNameHT::value_type(newEntry.GetName(), newEntry ));
180        return true;
181    } 
182    return false;
183 }
184
185 /**
186  * \ingroup Dict
187  * \brief  removes an already existing Dicom Dictionary Entry,
188  *         identified by its Tag
189  * @param   key (group|element)
190  * @return  false if Dicom Dictionary Entry doesn't exist
191  */
192 bool Dict::RemoveEntry (TagKey const &key) 
193 {
194    TagKeyHT::const_iterator it = KeyHt.find(key);
195    if(it != KeyHt.end()) 
196    {
197       const DictEntry& entryToDelete = it->second;
198       NameHt.erase(entryToDelete.GetName());
199       KeyHt.erase(key);
200
201       return true;
202    } 
203    else 
204    {
205       dbg.Verbose(1, "Dict::RemoveEntry unfound entry", key.c_str());
206       return false;
207   }
208 }
209
210 /**
211  * \brief  removes an already existing Dicom Dictionary Entry, 
212  *          identified by its group,element number
213  * @param   group   Dicom group number of the Dicom Element
214  * @param   element Dicom element number of the Dicom Element
215  * @return  false if Dicom Dictionary Entry doesn't exist
216  */
217 bool Dict::RemoveEntry (uint16_t group, uint16_t element)
218 {
219    return RemoveEntry(DictEntry::TranslateToKey(group, element));
220 }
221
222 /**
223  * \brief   Get the dictionnary entry identified by it's name.
224  * @param   name element of the ElVal to modify
225  * \warning : NEVER use it !
226  *            the 'name' IS NOT an identifier within the Dicom Dictionary
227  *            the name MAY CHANGE between two versions !
228  * @return  the corresponding dictionnary entry when existing, NULL otherwise
229  */
230 DictEntry *Dict::GetDictEntryByName(TagName const &name)
231 {
232    TagNameHT::iterator it = NameHt.find(name);
233    if ( it == NameHt.end() )
234    {
235       return 0;
236    }
237    return &(it->second);
238 }
239
240 /**
241  * \brief   Get the dictionnary entry identified by a given tag (group,element)
242  * @param   group   group of the entry to be found
243  * @param   element element of the entry to be found
244  * @return  the corresponding dictionnary entry when existing, NULL otherwise
245  */
246 DictEntry *Dict::GetDictEntryByNumber(uint16_t group, uint16_t element)
247 {
248    TagKey key = DictEntry::TranslateToKey(group, element);
249    TagKeyHT::iterator it = KeyHt.find(key);
250    if ( it == KeyHt.end() )
251    {
252       return 0;
253    }
254    return &(it->second);
255 }
256
257 /** 
258  * \brief   Consider all the entries of the public dicom dictionnary. 
259  *          Build all list of all the tag names of all those entries.
260  * \sa      DictSet::GetPubDictTagNamesByCategory
261  * @return  A list of all entries of the public dicom dictionnary.
262  */
263 EntryNamesList *Dict::GetDictEntryNames() 
264 {
265    EntryNamesList *result = new EntryNamesList;
266    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
267    {
268       result->push_back( tag->second.GetName() );
269    }
270    return result;
271 }
272
273 /** 
274  * \ingroup Dict
275  * \brief   Consider all the entries of the public dicom dictionnary.
276  *          Build an hashtable whose keys are the names of the groups
277  *          (fourth field in each line of dictionary) and whose corresponding
278  *          values are lists of all the dictionnary entries among that
279  *          group. Note that apparently the Dicom standard doesn't explicitely
280  *          define a name (as a string) for each group.
281  *          A typical usage of this method would be to enable a dynamic
282  *          configuration of a Dicom file browser: the admin/user can
283  *          select in the interface which Dicom tags should be displayed.
284  * \warning Dicom *doesn't* define any name for any 'categorie'
285  *          (the dictionnary fourth field was formerly NIH defined
286  *           - and no longer he is-
287  *           and will be removed when Dicom provides us a text file
288  *           with the 'official' Dictionnary, that would be more friendly
289  *           than asking us to perform a line by line check of the dictionnary
290  *           at the beginning of each year to -try to- guess the changes)
291  *           Therefore : please NEVER use that fourth field :-(
292  *
293  * @return  An hashtable: whose keys are the names of the groups and whose
294  *          corresponding values are lists of all the dictionnary entries
295  *          among that group.
296  */
297 EntryNamesByCatMap *Dict::GetDictEntryNamesByCategory() 
298 {
299    EntryNamesByCatMap *result = new EntryNamesByCatMap;
300
301    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
302    {
303       (*result)[tag->second.GetFourth()].push_back(tag->second.GetName());
304    }
305
306    return result;
307 }
308
309 //-----------------------------------------------------------------------------
310 // Protected
311
312 //-----------------------------------------------------------------------------
313 // Private
314
315 //-----------------------------------------------------------------------------
316
317 } // end namespace gdcm