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