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