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