]> Creatis software - gdcm.git/blob - src/gdcmDict.cxx
* src/gdcmUtil.[cxx|h] split in two. Additional file gdcmDebug.[cxx|h]
[gdcm.git] / src / gdcmDict.cxx
1 // gdcmDict.cxx
2 //-----------------------------------------------------------------------------
3 #include "gdcmDict.h"
4 #include "gdcmUtil.h"
5 #include "gdcmDebug.h"
6
7 #include <fstream>
8 #include <iostream>
9 #include <iomanip>
10
11 #ifdef GDCM_NO_ANSI_STRING_STREAM
12 #  include <strstream>
13 #  define  ostringstream ostrstream
14 # else
15 #  include <sstream>
16 #endif
17
18 //-----------------------------------------------------------------------------
19 // Constructor / Destructor
20 /**
21  * \ingroup gdcmDict
22  * \brief   Construtor
23  * @param   FileName from which to build the dictionary.
24  */
25 gdcmDict::gdcmDict(std::string & FileName) {
26    guint16 group, element;
27    char buff[1024];
28    TagName vr;
29    TagName fourth;
30    TagName name;
31
32    std::ifstream from(FileName.c_str());
33    dbg.Error(!from, "gdcmDict::gdcmDict: can't open dictionary",
34                     FileName.c_str());
35
36    while (!from.eof()) {
37       from >> std::hex >> group >> element;
38       eatwhite(from);
39       from.getline(buff, 256, ' ');
40       vr = buff;
41       eatwhite(from);
42       from.getline(buff, 256, ' ');
43       fourth = buff;
44       from.getline(buff, 256, '\n');
45       name = buff;
46
47       gdcmDictEntry * newEntry = new gdcmDictEntry(group, element,
48                                                    vr, fourth, name);
49       AddNewEntry(newEntry);
50    }
51    from.close();
52
53    filename=FileName;
54 }
55
56 /**
57  * \ingroup gdcmDict
58  * \brief  Destructor 
59  */
60 gdcmDict::~gdcmDict() {
61    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag) {
62       gdcmDictEntry* EntryToDelete = tag->second;
63       if ( EntryToDelete )
64          delete EntryToDelete;
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 entry to add 
134  * @return  false if Dicom Element already exists
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 new entry (overwrites any previous one with same tag)
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 number
202  * @param   group   Dicom group number of the Dicom Element
203  * @param   element Dicom element number of the Dicom Element
204  * @return  false if Dicom Dictionary Entry doesn't exist
205  */
206 bool gdcmDict::RemoveEntry (guint16 group, guint16 element) {
207         return( RemoveEntry(gdcmDictEntry::TranslateToKey(group, element)) );
208 }
209
210 /**
211  * \ingroup gdcmDict
212  * \brief   Get the dictionnary entry identified by it's name.
213  * @param   name element of the ElVal to modify
214  * \warning : NEVER use it !
215  *            the 'name' IS NOT an identifier within the Dicom Dicom Dictionary
216  *            the name MAY CHANGE between two versions !
217  * @return  the corresponding dictionnary entry when existing, NULL otherwise
218  */
219 gdcmDictEntry *gdcmDict::GetDictEntryByName(TagName name) {
220    if ( ! NameHt.count(name))
221       return NULL; 
222    return NameHt.find(name)->second;
223 }
224
225 /**
226  * \ingroup gdcmDict
227  * \brief   Get the dictionnary entry identified by a given tag (group,element)
228  * @param   group   group of the entry to be found
229  * @param   element element of the entry to be found
230  * @return  the corresponding dictionnary entry when existing, NULL otherwise
231  */
232 gdcmDictEntry *gdcmDict::GetDictEntryByNumber(guint16 group, guint16 element) {
233    TagKey key = gdcmDictEntry::TranslateToKey(group, element);
234    if ( ! KeyHt.count(key))
235       return NULL; 
236    return KeyHt.find(key)->second;
237 }
238
239 /** 
240  * \ingroup gdcmDict
241  * \brief   Consider all the entries of the public dicom dictionnary. 
242  *          Build all list of all the tag names of all those entries.
243  * \sa      gdcmDictSet::GetPubDictTagNamesByCategory
244  * @return  A list of all entries of the public dicom dictionnary.
245  */
246 std::list<std::string> *gdcmDict::GetDictEntryNames(void) 
247 {
248    std::list<std::string> *Result = new std::list<std::string>;
249    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
250    {
251       Result->push_back( tag->second->GetName() );
252    }
253    return Result;
254 }
255
256 /** 
257  * \ingroup gdcmDict
258  * \brief   Consider all the entries of the public dicom dictionnary.
259  *          Build an hashtable whose keys are the names of the groups
260  *          (fourth field in each line of dictionary) and whose corresponding
261  *          values are lists of all the dictionnary entries among that
262  *          group. Note that apparently the Dicom standard doesn't explicitely
263  *          define a name (as a string) for each group.
264  *          A typical usage of this method would be to enable a dynamic
265  *          configuration of a Dicom file browser: the admin/user can
266  *          select in the interface which Dicom tags should be displayed.
267  * \warning Dicom *doesn't* define any name for any 'categorie'
268  *          (the dictionnary fourth field was formerly NIH defined
269  *           - and no longer he is-
270  *           and will be removed when Dicom provides us a text file
271  *           with the 'official' Dictionnary, that would be more friendly
272  *           than asking us to perform a line by line check of the dictionnary
273  *           at the beginning of each year to -try to- guess the changes)
274  *           Therefore : please NEVER use that fourth field :-(
275  *
276  * @return  An hashtable: whose keys are the names of the groups and whose
277  *          corresponding values are lists of all the dictionnary entries
278  *          among that group.
279  */
280 std::map<std::string, std::list<std::string> > *gdcmDict::GetDictEntryNamesByCategory(void) 
281 {
282    std::map<std::string, std::list<std::string> > *Result = new std::map<std::string, std::list<std::string> >;
283
284    for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
285    {
286       (*Result)[tag->second->GetFourth()].push_back(tag->second->GetName());
287    }
288    return Result;
289 }
290
291 //-----------------------------------------------------------------------------
292 // Protected
293
294 //-----------------------------------------------------------------------------
295 // Private
296
297 //-----------------------------------------------------------------------------