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