From 0457e1e8fc68df6d9e2d1a0fcd0053ecee3c5ad7 Mon Sep 17 00:00:00 2001 From: frog Date: Wed, 16 Apr 2003 08:03:26 +0000 Subject: [PATCH] * More memmory link related corrections and documentation fixes. --- ChangeLog | 6 +++- Testing/.cvsignore | 4 +++ src/gdcmDict.cxx | 37 +++++++++++++++++++----- src/gdcmDict.h | 11 ++++++-- src/gdcmDictEntry.cxx | 3 +- src/gdcmDictSet.cxx | 37 ++++++++++-------------- src/gdcmDictSet.h | 16 +++++------ src/gdcmElValSet.cxx | 13 +++++++++ src/gdcmElValSet.h | 3 +- src/gdcmHeader.cxx | 10 +++++-- src/gdcmHeader.h | 2 +- src/gdcmUtil.cxx | 16 +++++++++-- src/gdcmUtil.h | 5 +++- src/gdcmVR.cxx | 65 +++++++++++++++++++------------------------ src/gdcmVR.h | 13 ++++----- 15 files changed, 146 insertions(+), 95 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f957e19..c3da4560 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ +2003-04-16 Eric Boix with JPR + * More memmory link related corrections and documentation fixes. + 2003-04-15 Eric Boix with JPR - * Memory link hunt (by using valgrind --leak-check=yes PrintHeader). + * Memory link hunt (by using valgrind through the command + valgrind --show-reachable=yes --leak-check=yes PrintHeader). - added src/gdcmVR.cxx gdcmVR.h that objectify the previous gdcmHeader::_dicom_vr. - gdcmHeader::InitVRDict transfered as gdcmVR::gdcmVR(). diff --git a/Testing/.cvsignore b/Testing/.cvsignore index 0622317e..27d52172 100644 --- a/Testing/.cvsignore +++ b/Testing/.cvsignore @@ -12,3 +12,7 @@ testChangeEntete bug1 image.dcm image.raw +test2.acr.dcm +test2.acr.raw +test3.acr.dcm +test3.acr.raw diff --git a/src/gdcmDict.cxx b/src/gdcmDict.cxx index 724225bd..d115e0a0 100644 --- a/src/gdcmDict.cxx +++ b/src/gdcmDict.cxx @@ -4,9 +4,15 @@ #include "gdcmDict.h" #include "gdcmUtil.h" -gdcmDict::gdcmDict(const char* FileName) { - std::ifstream from(FileName); - dbg.Error(!from, "gdcmDict::gdcmDict: can't open dictionary", FileName); +/** + * \ingroup gdcmDict + * \brief Construtor + * @param FileName from which to build the dictionary. + */ +gdcmDict::gdcmDict(string & FileName) { + std::ifstream from(FileName.c_str()); + dbg.Error(!from, "gdcmDict::gdcmDict: can't open dictionary", + FileName.c_str()); guint16 group, element; // CLEANME : use defines for all those constants char buff[1024]; @@ -26,18 +32,32 @@ gdcmDict::gdcmDict(const char* FileName) { name = buff; gdcmDictEntry * newEntry = new gdcmDictEntry(group, element, vr, fourth, name); + // FIXME: use AddNewEntry NameHt[name] = newEntry; KeyHt[gdcmDictEntry::TranslateToKey(group, element)] = newEntry; } from.close(); } +gdcmDict::~gdcmDict() { + for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag) { + gdcmDictEntry* EntryToDelete = tag->second; + if ( EntryToDelete ) + delete EntryToDelete; + } + KeyHt.clear(); + // Since AddNewEntry adds symetrical in both KeyHt and NameHT we can + // assume all the pointed gdcmDictEntries are allready cleaned-up when + // we cleaned KeyHt. + NameHt.clear(); +} + void gdcmDict::Print(ostream& os) { PrintByKey(os); } /** - * \ingroup gdcmHeader + * \ingroup gdcmDict * \brief Print all the dictionary entries contained in this dictionary. * Entries will be sorted by tag i.e. the couple (group, element). * @param os The output stream to be written to. @@ -54,7 +74,7 @@ void gdcmDict::PrintByKey(ostream& os) { } /** - * \ingroup gdcmHeader + * \ingroup gdcmDict * \brief Print all the dictionary entries contained in this dictionary. * Entries will be sorted by the name of the dictionary entries. * @param os The output stream to be written to. @@ -71,7 +91,7 @@ void gdcmDict::PrintByName(ostream& os) { } /** - * \ingroup gdcmHeader + * \ingroup gdcmDict * \brief Get the dictionnary entry identified by a given tag (group,element) * @param group group of the entry to be found * @param element element of the entry to be found @@ -85,7 +105,7 @@ gdcmDictEntry * gdcmDict::GetTagByNumber(guint16 group, guint16 element) { } /** - * \ingroup gdcmHeader + * \ingroup gdcmDict * \brief Get the dictionnary entry identified by it's name. * @param name element of the ElVal to modify * @return the corresponding dictionnary entry when existing, NULL otherwise @@ -121,6 +141,9 @@ int gdcmDict::AddNewEntry(gdcmDictEntry* NewEntry) { int gdcmDict::RemoveEntry(TagKey key) { if(KeyHt.count(key) == 1) { + gdcmDictEntry* EntryToDelete = KeyHt.find(key)->second; + if ( EntryToDelete ) + delete EntryToDelete; KeyHt.erase(key); return (1); } else { diff --git a/src/gdcmDict.h b/src/gdcmDict.h index 04975882..5e56f335 100644 --- a/src/gdcmDict.h +++ b/src/gdcmDict.h @@ -14,13 +14,18 @@ typedef map TagKeyHT; typedef map TagNameHT; +/// Build a memory representation of a dicom dictionary by parsing +/// an ascii file class GDCM_EXPORT gdcmDict { string name; string filename; - TagKeyHT KeyHt; // Both accesses with a TagKey or with a - TagNameHT NameHt; // TagName are required. + /// Access through TagKey (see alternate access with NameHt) + TagKeyHT KeyHt; + /// Access through TagName (see alternate access with KeyHt) + TagNameHT NameHt; public: - gdcmDict(const char* FileName); // Reads Dict from ascii file + gdcmDict(string & FileName); + ~gdcmDict(); int AddNewEntry (gdcmDictEntry* NewEntry); int ReplaceEntry(gdcmDictEntry* NewEntry); int RemoveEntry (TagKey key); diff --git a/src/gdcmDictEntry.cxx b/src/gdcmDictEntry.cxx index 482a05d0..8823ac73 100644 --- a/src/gdcmDictEntry.cxx +++ b/src/gdcmDictEntry.cxx @@ -6,7 +6,8 @@ gdcmDictEntry::gdcmDictEntry(guint16 InGroup, guint16 InElement, - string InVr, string InFourth, string InName) { + string InVr, string InFourth, + string InName) { group = InGroup; element = InElement; vr = InVr; diff --git a/src/gdcmDictSet.cxx b/src/gdcmDictSet.cxx index ace75222..9a8bea4c 100644 --- a/src/gdcmDictSet.cxx +++ b/src/gdcmDictSet.cxx @@ -11,9 +11,6 @@ #endif #define PUB_DICT_FILENAME "dicomV3.dic" -string gdcmDictSet::DictPath = gdcmDictSet::BuildDictPath(); -gdcmDict* gdcmDictSet::DefaultPubDict = gdcmDictSet::LoadDefaultPubDict(); - /** * \ingroup gdcmDictSet * \brief Consider all the entries of the public dicom dictionnary. @@ -23,7 +20,7 @@ gdcmDict* gdcmDictSet::DefaultPubDict = gdcmDictSet::LoadDefaultPubDict(); */ list * gdcmDictSet::GetPubDictTagNames(void) { list * Result = new list; - TagKeyHT entries = gdcmDictSet::DefaultPubDict->GetEntries(); + TagKeyHT entries = GetDefaultPubDict()->GetEntries(); for (TagKeyHT::iterator tag = entries.begin(); tag != entries.end(); ++tag){ Result->push_back( tag->second->GetName() ); @@ -48,7 +45,7 @@ list * gdcmDictSet::GetPubDictTagNames(void) { */ map > * gdcmDictSet::GetPubDictTagNamesByCategory(void) { map > * Result = new map >; - TagKeyHT entries = gdcmDictSet::DefaultPubDict->GetEntries(); + TagKeyHT entries = GetDefaultPubDict()->GetEntries(); for (TagKeyHT::iterator tag = entries.begin(); tag != entries.end(); ++tag){ (*Result)[tag->second->GetFourth()].push_back(tag->second->GetName()); @@ -78,28 +75,24 @@ string gdcmDictSet::BuildDictPath(void) { return ResultPath; } -/** - * \ingroup gdcmDictSet - * \brief Loads the default public DICOM V3 dictionary as a gdcmDict. - * \return The newly build reference public dictionary. - */ -gdcmDict* gdcmDictSet::LoadDefaultPubDict(void) { - string PubDictFile = gdcmDictSet::DictPath + PUB_DICT_FILENAME; - return new gdcmDict(PubDictFile.c_str()); -} - /** * \ingroup gdcmDictSet * \brief The Dictionnary Set obtained with this constructor simply * contains the Default Public dictionnary. */ gdcmDictSet::gdcmDictSet(void) { - dicts[PUB_DICT_NAME] = DefaultPubDict; + DictPath = BuildDictPath(); + string PubDictFile = DictPath + PUB_DICT_FILENAME; + Dicts[PUB_DICT_NAME] = new gdcmDict(PubDictFile); } gdcmDictSet::~gdcmDictSet() { - //FIXME : first destroy pointed dictionaries before trashing hash table. - dicts.clear(); + for (DictSetHT::iterator tag = Dicts.begin(); tag != Dicts.end(); ++tag) { + gdcmDict* EntryToDelete = tag->second; + if ( EntryToDelete ) + delete EntryToDelete; + } + Dicts.clear(); } /** @@ -112,8 +105,8 @@ gdcmDictSet::~gdcmDictSet() { * created dictionary. */ void gdcmDictSet::LoadDictFromFile(string FileName, DictKey Name) { - gdcmDict *NewDict = new gdcmDict(FileName.c_str()); - dicts[Name] = NewDict; + gdcmDict *NewDict = new gdcmDict(FileName); + Dicts[Name] = NewDict; } /** @@ -123,7 +116,7 @@ void gdcmDictSet::LoadDictFromFile(string FileName, DictKey Name) { * @param os Output stream used for printing. */ void gdcmDictSet::Print(ostream& os) { - for (DictSetHT::iterator dict = dicts.begin(); dict != dicts.end(); ++dict){ + for (DictSetHT::iterator dict = Dicts.begin(); dict != Dicts.end(); ++dict){ os << "Printing dictionary " << dict->first << " \n"; dict->second->Print(os); } @@ -137,7 +130,7 @@ void gdcmDictSet::Print(ostream& os) { * \result The retrieved dictionary. */ gdcmDict * gdcmDictSet::GetDict(DictKey DictName) { - DictSetHT::iterator dict = dicts.find(DictName); + DictSetHT::iterator dict = Dicts.find(DictName); return dict->second; } diff --git a/src/gdcmDictSet.h b/src/gdcmDictSet.h index c57ae166..751be5f8 100644 --- a/src/gdcmDictSet.h +++ b/src/gdcmDictSet.h @@ -20,18 +20,16 @@ typedef map DictSetHT; */ class GDCM_EXPORT gdcmDictSet { private: - DictSetHT dicts; + /// Hash table of all dictionaries contained in this gdcmDictSet + DictSetHT Dicts; + /// Directory path to dictionaries + string DictPath; int AppendDict(gdcmDict* NewDict); void LoadDictFromFile(string filename, DictKey); -private: - /// Directory path to dictionaries - static string DictPath; - static string BuildDictPath(void); - static gdcmDict* DefaultPubDict; + string BuildDictPath(void); public: - static list * GetPubDictTagNames(void); - static map >* GetPubDictTagNamesByCategory(void); - static gdcmDict* LoadDefaultPubDict(void); + list * GetPubDictTagNames(void); + map >* GetPubDictTagNamesByCategory(void); // TODO Swig int LoadDictFromFile(string filename); // QUESTION: the following function might not be thread safe !? Maybe diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index ed07d4f1..d0f02984 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -4,6 +4,18 @@ #include "gdcmUtil.h" #include "gdcmElValSet.h" +gdcmElValSet::~gdcmElValSet() { + for (TagElValueHT::iterator tag = tagHt.begin(); tag != tagHt.end(); ++tag) { + gdcmElValue* EntryToDelete = tag->second; + if ( EntryToDelete ) + delete EntryToDelete; + } + tagHt.clear(); + // Since Add() adds symetrical in both tagHt and NameHt we can + // assume all the pointed gdcmElValues are allready cleaned-up when + // we cleaned tagHt. + NameHt.clear(); +} TagElValueHT & gdcmElValSet::GetTagHt(void) { return tagHt; @@ -267,6 +279,7 @@ void gdcmElValSet::WriteElements(FileType type, FILE * _fp) { } continue; } + tokens.clear(); // Les pixels ne sont pas chargés dans l'element ! if ((gr == 0x7fe0) && (el == 0x0010) ) break; diff --git a/src/gdcmElValSet.h b/src/gdcmElValSet.h index c5b59ed5..ae30bc55 100644 --- a/src/gdcmElValSet.h +++ b/src/gdcmElValSet.h @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.10 2003/04/09 14:04:53 jpr Exp $ +// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.11 2003/04/16 08:03:27 frog Exp $ #ifndef GDCMELVALSET_H #define GDCMELVALSET_H @@ -21,6 +21,7 @@ class GDCM_EXPORT gdcmElValSet { typedef map GroupHT; public: + ~gdcmElValSet(); void Add(gdcmElValue*); void Print(ostream &); diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index 66b97ce2..82c31a0f 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -19,11 +19,13 @@ #define _MaxSizeLoadElementValue_ 1024 gdcmVR * gdcmHeader::dicom_vr = (gdcmVR*)0; +gdcmDictSet * gdcmHeader::Dicts = (gdcmDictSet*)0; void gdcmHeader::Initialise(void) { if (!gdcmHeader::dicom_vr) gdcmHeader::dicom_vr = gdcmGlobal::GetVR(); - Dicts = new gdcmDictSet(); + if (!gdcmHeader::Dicts) + gdcmHeader::Dicts = gdcmGlobal::GetDicts(); RefPubDict = Dicts->GetDefaultPubDict(); RefShaDict = (gdcmDict*)0; } @@ -61,8 +63,10 @@ bool gdcmHeader::CloseFile(void) { } gdcmHeader::~gdcmHeader (void) { - delete Dicts; - //FIXME obviously there is much to be done here ! + dicom_vr = (gdcmVR*)0; + Dicts = (gdcmDictSet*)0; + RefPubDict = (gdcmDict*)0; + RefShaDict = (gdcmDict*)0; return; } diff --git a/src/gdcmHeader.h b/src/gdcmHeader.h index 1834dfdb..2741b3ed 100644 --- a/src/gdcmHeader.h +++ b/src/gdcmHeader.h @@ -40,7 +40,7 @@ private: static gdcmVR *dicom_vr; /// Global dictionary container - gdcmDictSet* Dicts; + static gdcmDictSet* Dicts; /// Public dictionary used to parse this header gdcmDict* RefPubDict; /// Optional "shadow dictionary" (private elements) used to parse this diff --git a/src/gdcmUtil.cxx b/src/gdcmUtil.cxx index 9b93e96c..207b66f1 100644 --- a/src/gdcmUtil.cxx +++ b/src/gdcmUtil.cxx @@ -5,7 +5,6 @@ // Library globals. gdcmDebug dbg; -gdcmVR * gdcmGlobal::VR = new gdcmVR(); gdcmDebug::gdcmDebug(int level) { DebugLevel = level; @@ -48,17 +47,30 @@ void gdcmDebug::Exit(int a) { } /////////////////////////////////////////////////////////////////////////// +gdcmVR * gdcmGlobal::VR = (gdcmVR*)0; +gdcmDictSet * gdcmGlobal::Dicts = (gdcmDictSet*)0; +gdcmGlobal gdcmGlob; + gdcmGlobal::gdcmGlobal(void) { + if (VR || Dicts) + dbg.Verbose(0, "gdcmGlobal::gdcmGlobal: VR or Dicts allready allocated"); + VR = new gdcmVR(); + Dicts = new gdcmDictSet(); } -gdcmGlobal::~gdcmGlobal(void) { +gdcmGlobal::~gdcmGlobal() { delete VR; + delete Dicts; } gdcmVR * gdcmGlobal::GetVR(void) { return VR; } +gdcmDictSet * gdcmGlobal::GetDicts(void) { + return Dicts; +} + /////////////////////////////////////////////////////////////////////////// // Because is not yet available in g++2.96 istream& eatwhite(istream& is) { diff --git a/src/gdcmUtil.h b/src/gdcmUtil.h index 325bde91..cb9dcbd3 100644 --- a/src/gdcmUtil.h +++ b/src/gdcmUtil.h @@ -7,6 +7,7 @@ #include #include #include "gdcmVR.h" +#include "gdcmDictSet.h" using namespace std; class gdcmDebug { @@ -24,10 +25,12 @@ public: class gdcmGlobal { private: static gdcmVR *VR; + static gdcmDictSet *Dicts; public: gdcmGlobal(void); - ~gdcmGlobal(void); + ~gdcmGlobal(); static gdcmVR * GetVR(void); + static gdcmDictSet * GetDicts(void); }; istream & eatwhite(istream & is); diff --git a/src/gdcmVR.cxx b/src/gdcmVR.cxx index 802557d1..c20aa4a2 100644 --- a/src/gdcmVR.cxx +++ b/src/gdcmVR.cxx @@ -1,47 +1,40 @@ // gdcmVR.cxx #include "gdcmVR.h" -#include "gdcmUtil.h" -gdcmVR::gdcmVR () { - // NOTE: making the affectation directely to dicom_vr instead of passing - // through an apparently unncessary local variable vr, crashes with - // gcc... Beware. - VRHT *vr = new VRHT; - (*vr)["AE"] = "Application Entity"; // At most 16 bytes - (*vr)["AS"] = "Age String"; // Exactly 4 bytes - (*vr)["AT"] = "Attribute Tag"; // 2 16-bit unsigned short integers - (*vr)["CS"] = "Code String"; // At most 16 bytes - (*vr)["DA"] = "Date"; // Exactly 8 bytes - (*vr)["DS"] = "Decimal String"; // At most 16 bytes - (*vr)["DT"] = "Date Time"; // At most 26 bytes - (*vr)["FL"] = "Floating Point Single"; // 32-bit IEEE 754:1985 float - (*vr)["FD"] = "Floating Point Double"; // 64-bit IEEE 754:1985 double - (*vr)["IS"] = "Integer String"; // At most 12 bytes - (*vr)["LO"] = "Long String"; // At most 64 chars - (*vr)["LT"] = "Long Text"; // At most 10240 chars - (*vr)["OB"] = "Other Byte String"; // String of bytes (vr independant) - (*vr)["OW"] = "Other Word String"; // String of 16-bit words (vr dep) - (*vr)["PN"] = "Person Name"; // At most 64 chars - (*vr)["SH"] = "Short String"; // At most 16 chars - (*vr)["SL"] = "Signed Long"; // Exactly 4 bytes - (*vr)["SQ"] = "Sequence of Items"; // Not Applicable - (*vr)["SS"] = "Signed Short"; // Exactly 2 bytes - (*vr)["ST"] = "Short Text"; // At most 1024 chars - (*vr)["TM"] = "Time"; // At most 16 bytes - (*vr)["UI"] = "Unique Identifier"; // At most 64 bytes - (*vr)["UL"] = "Unsigned Long "; // Exactly 4 bytes - (*vr)["UN"] = "Unknown"; // Any length of bytes - (*vr)["US"] = "Unsigned Short "; // Exactly 2 bytes - (*vr)["UT"] = "Unlimited Text"; // At most 2^32 -1 chars - dicom_vr = vr; +gdcmVR::gdcmVR(void) { + vr["AE"] = "Application Entity"; // At most 16 bytes + vr["AS"] = "Age String"; // Exactly 4 bytes + vr["AT"] = "Attribute Tag"; // 2 16-bit unsigned short integers + vr["CS"] = "Code String"; // At most 16 bytes + vr["DA"] = "Date"; // Exactly 8 bytes + vr["DS"] = "Decimal String"; // At most 16 bytes + vr["DT"] = "Date Time"; // At most 26 bytes + vr["FL"] = "Floating Point Single"; // 32-bit IEEE 754:1985 float + vr["FD"] = "Floating Point Double"; // 64-bit IEEE 754:1985 double + vr["IS"] = "Integer String"; // At most 12 bytes + vr["LO"] = "Long String"; // At most 64 chars + vr["LT"] = "Long Text"; // At most 10240 chars + vr["OB"] = "Other Byte String"; // String of bytes (vr independant) + vr["OW"] = "Other Word String"; // String of 16-bit words (vr dep) + vr["PN"] = "Person Name"; // At most 64 chars + vr["SH"] = "Short String"; // At most 16 chars + vr["SL"] = "Signed Long"; // Exactly 4 bytes + vr["SQ"] = "Sequence of Items"; // Not Applicable + vr["SS"] = "Signed Short"; // Exactly 2 bytes + vr["ST"] = "Short Text"; // At most 1024 chars + vr["TM"] = "Time"; // At most 16 bytes + vr["UI"] = "Unique Identifier"; // At most 64 bytes + vr["UL"] = "Unsigned Long "; // Exactly 4 bytes + vr["UN"] = "Unknown"; // Any length of bytes + vr["US"] = "Unsigned Short "; // Exactly 2 bytes + vr["UT"] = "Unlimited Text"; // At most 2^32 -1 chars } gdcmVR::~gdcmVR() { - dicom_vr->clear(); - delete dicom_vr; + vr.clear(); } int gdcmVR::Count(VRKey key) { - return dicom_vr->count(key); + return vr.count(key); } diff --git a/src/gdcmVR.h b/src/gdcmVR.h index 3be7fa4c..db5869a0 100644 --- a/src/gdcmVR.h +++ b/src/gdcmVR.h @@ -11,18 +11,15 @@ typedef string VRKey; typedef string VRAtr; typedef map VRHT; // Value Representation Hash Table -/* - * \defgroup gdcmVR - * \brief Container for dicom Value Representation Hash Table - * \note This is a singleton - */ +/// Container for dicom Value Representation Hash Table +/// \note This is a singleton class GDCM_EXPORT gdcmVR { private: - VRHT *dicom_vr; + VRHT vr; public: - gdcmVR(); + gdcmVR(void); ~gdcmVR(); - int Count(VRKey); + int Count(VRKey key); }; #endif -- 2.45.1