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