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