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