From: frog Date: Sat, 19 Jun 2004 23:51:03 +0000 (+0000) Subject: * In order to fix memory leaks: X-Git-Tag: Version0.5.bp~131 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=61e1a3e0ce5480990a0d0b844cf0e86d1775306d;p=gdcm.git * In order to fix memory leaks: - Test/TestWriteSimple.cxx: added cleaning of free store through some delete calls. - src/gdcmBinEntry.cxx: fix to avoid SegFault. - src/gdcmDicomDir.[cxx|h]: fixed initialisation in constructor gdcmDicomDir::gdcmDicomDir(bool) [either the constructor itself (through the call to ::AddDicomDirMeta()) or the destructor would crash when deleting uninitialized ::metaElems]. - src/gdcmDictEntry.cxx: annotation of ununderstood memory leak. - src/gdcmDocument.cxx: -- ::~gdcmDocument() destructor now cleans up all dictionary entries from dynamic stores. -- ::ParseDES() misplaced deletion of temporary NewDocEntry was causing memory leaks. - src/gdcmSQItem.cxx: -- ::~gdcmSQItem() dummy code cleaned (learned that deletion is cleanly handled with polymophism: sorry but my milage is low). -- ::SetEntryByNumber(string, guint16, guint16) now cleanly allocates a gdcmValENtry, and makes no assumption on type (gdcmDocEntry, gdcmSeqEntry vs gdcmValEntry) of existing entry (when present). This avoids SegFaulting. - src/gdcmSQItem.h: coding style. * Conclusion: - Test/TestWriteSimple still severely sucks. The output image content (when $(GDCMDATA_HOME)/012345.002.050.dcm in input) is brain damaged when displayed with vtkgdcmViewer. - on memory leaks: TestWriteSimple leaks really less (see entry of 2004-06-18 in Changelog file for the call to valgrind). - on segfaults: ctest now passes all the tests but one (no more segfaults). --- diff --git a/ChangeLog b/ChangeLog index adc27f6f..f5c22113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2004-06-20 Eric Boix + * In order to fix memory leaks: + - Test/TestWriteSimple.cxx: added cleaning of free store through + some delete calls. + - src/gdcmBinEntry.cxx: fix to avoid SegFault. + - src/gdcmDicomDir.[cxx|h]: fixed initialisation in constructor + gdcmDicomDir::gdcmDicomDir(bool) [either the constructor itself + (through the call to ::AddDicomDirMeta()) or the destructor + would crash when deleting uninitialized ::metaElems]. + - src/gdcmDictEntry.cxx: annotation of ununderstood memory leak. + - src/gdcmDocument.cxx: + -- ::~gdcmDocument() destructor now cleans up all dictionary entries + from dynamic stores. + -- ::ParseDES() misplaced deletion of temporary NewDocEntry + was causing memory leaks. + - src/gdcmSQItem.cxx: + -- ::~gdcmSQItem() dummy code cleaned (learned that deletion is + cleanly handled with polymophism: sorry but my milage is low). + -- ::SetEntryByNumber(string, guint16, guint16) now cleanly allocates + a gdcmValENtry, and makes no assumption on type (gdcmDocEntry, + gdcmSeqEntry vs gdcmValEntry) of existing entry (when present). + This avoids SegFaulting. + - src/gdcmSQItem.h: coding style. + * Conclusion: + - Test/TestWriteSimple still severely sucks. The output image content + (when $(GDCMDATA_HOME)/012345.002.050.dcm in input) is brain + damaged when displayed with vtkgdcmViewer. + - on memory leaks: TestWriteSimple leaks really less (see entry + of 2004-06-18 in Changelog file for the call to valgrind). + - on segfaults: ctest now passes all the tests but one (no more + segfaults). + 2004-06-18 Eric Boix * In order to fix writing of dicom files: - Test/TestWriteSimple.cxx: a simpler example of writing. diff --git a/Testing/TestWriteSimple.cxx b/Testing/TestWriteSimple.cxx index 33294911..8451cbd5 100644 --- a/Testing/TestWriteSimple.cxx +++ b/Testing/TestWriteSimple.cxx @@ -16,11 +16,12 @@ int TestWriteSimple(int argc, char* argv[]) const char *header = argv[1]; const char *output = argv[2]; - dbg.SetDebug(4); gdcmHeader *f1 = new gdcmHeader( header ); gdcmFile *f2 = new gdcmFile( f1 ); - f2->GetImageData(); //EXTREMELY IMPORTANT + // If the following call is important, then the API sucks. Why is it + // required to allocate PixelData when we are not using it !? + void* PixelData = f2->GetImageData(); //EXTREMELY IMPORTANT //Otherwise ReadPixel == -1 -> the dicom writing fails completely int dataSize = f2->GetImageDataSize(); @@ -33,6 +34,9 @@ int TestWriteSimple(int argc, char* argv[]) f2->WriteDcmExplVR( output ); delete[] imageData; + delete f1; + delete f2; + delete PixelData; return 0; } diff --git a/src/gdcmBinEntry.cxx b/src/gdcmBinEntry.cxx index c9b15621..b24d5c38 100644 --- a/src/gdcmBinEntry.cxx +++ b/src/gdcmBinEntry.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmBinEntry.cxx,v $ Language: C++ - Date: $Date: 2004/06/18 12:26:54 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/06/19 23:51:03 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -27,7 +27,7 @@ * \brief Constructor from a given gdcmBinEntry */ gdcmBinEntry::gdcmBinEntry(gdcmDictEntry* e) : gdcmValEntry(e) { - + this->voidArea = NULL; } /** @@ -49,7 +49,8 @@ gdcmBinEntry::gdcmBinEntry(gdcmDocEntry* e) : gdcmValEntry(e->GetDictEntry()){ * \brief Canonical destructor. */ gdcmBinEntry::~gdcmBinEntry(){ - free (voidArea); + if (voidArea) + free (voidArea); } diff --git a/src/gdcmDicomDir.cxx b/src/gdcmDicomDir.cxx index bbd9374a..a542b0b4 100644 --- a/src/gdcmDicomDir.cxx +++ b/src/gdcmDicomDir.cxx @@ -1,5 +1,21 @@ -// gdcmDicomDir.cxx -//----------------------------------------------------------------------------- +/*========================================================================= + + Program: gdcm + Module: $RCSfile: gdcmDicomDir.cxx,v $ + Language: C++ + Date: $Date: 2004/06/19 23:51:03 $ + Version: $Revision: 1.48 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + #include #include #include @@ -28,9 +44,26 @@ // For full DICOMDIR description, see: // PS 3.3-2003, pages 731-750 //----------------------------------------------------------------------------- +// Constructor / Destructor +void gdcmDicomDir::Initialize(void) +{ + startMethod = NULL; + progressMethod = NULL; + endMethod = NULL; + startMethodArgDelete = NULL; + progressMethodArgDelete = NULL; + endMethodArgDelete = NULL; + startArg = NULL; + progressArg = NULL; + endArg = NULL; + + progress = 0.0; + abort = false; + + metaElems = (gdcmDicomDirMeta *)0; +} -// Constructor / Destructor /** * \brief Constructor Parses recursively the directory and creates the DicomDir @@ -49,24 +82,10 @@ gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir, bool exception_on_error): gdcmDocument(FileName,exception_on_error,true) // true : enable SeQuences { - // que l'on ai passe un root directory ou un DICOMDIR - // et quelle que soit la valeur de parseDir, - // on a lance gdcmDocument - - startMethod= NULL; - progressMethod= NULL; - endMethod= NULL; - startMethodArgDelete= NULL; - progressMethodArgDelete=NULL; - endMethodArgDelete= NULL; - startArg= NULL; - progressArg= NULL; - endArg= NULL; - - progress=0.0; - abort=false; - - metaElems=NULL; + // que l'on ai passe un root directory ou un DICOMDIR + // et quelle que soit la valeur de parseDir, + // on a lance gdcmDocument + Initialize(); // gdcmDocument already executed // if user passed a root directory, sure we didn't get anything @@ -114,25 +133,13 @@ gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir, gdcmDicomDir::gdcmDicomDir(bool exception_on_error): gdcmDocument(exception_on_error) { - startMethod= NULL; - progressMethod= NULL; - endMethod= NULL; - startMethodArgDelete= NULL; - progressMethodArgDelete=NULL; - endMethodArgDelete= NULL; - startArg= NULL; - progressArg= NULL; - endArg= NULL; - progress=0.0; - abort=false; + Initialize(); std::string pathBidon = "Bidon"; // Sorry, NULL not allowed ... SetElement(pathBidon, GDCM_DICOMDIR_META, NULL); // Set the META elements AddDicomDirMeta(); } - /** - * \ingroup gdcmDicomDir * \brief Canonical destructor */ gdcmDicomDir::~gdcmDicomDir() @@ -144,7 +151,9 @@ gdcmDicomDir::~gdcmDicomDir() if(metaElems) delete metaElems; - for(ListDicomDirPatient::iterator cc=patients.begin();cc!=patients.end();++cc) + for(ListDicomDirPatient::iterator cc = patients.begin(); + cc!= patients.end(); + ++cc) { delete *cc; } @@ -153,7 +162,6 @@ gdcmDicomDir::~gdcmDicomDir() //----------------------------------------------------------------------------- // Print /** - * \ingroup gdcmDicomDir * \brief Canonical Printer */ void gdcmDicomDir::Print(std::ostream &os) @@ -163,7 +171,9 @@ void gdcmDicomDir::Print(std::ostream &os) metaElems->SetPrintLevel(printLevel); metaElems->Print(os); } - for(ListDicomDirPatient::iterator cc=patients.begin();cc!=patients.end();++cc) + for(ListDicomDirPatient::iterator cc = patients.begin(); + cc != patients.end(); + ++cc) { (*cc)->SetPrintLevel(printLevel); (*cc)->Print(os); @@ -173,7 +183,6 @@ void gdcmDicomDir::Print(std::ostream &os) //----------------------------------------------------------------------------- // Public /** - * \ingroup gdcmDicomDir * \brief This predicate, based on hopefully reasonable heuristics, * decides whether or not the current header was properly parsed * and contains the mandatory information for being considered as diff --git a/src/gdcmDicomDir.h b/src/gdcmDicomDir.h index fdb03622..98ee8ac4 100644 --- a/src/gdcmDicomDir.h +++ b/src/gdcmDicomDir.h @@ -1,9 +1,24 @@ -// gdcmDicomDir.h -//----------------------------------------------------------------------------- +/*========================================================================= + + Program: gdcm + Module: $RCSfile: gdcmDicomDir.h,v $ + Language: C++ + Date: $Date: 2004/06/19 23:51:03 $ + Version: $Revision: 1.22 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + #ifndef GDCMDICOMDIR_H #define GDCMDICOMDIR_H -//#include "gdcmHeader.h" #include "gdcmCommon.h" #include "gdcmDocument.h" #include "gdcmDicomDirPatient.h" @@ -111,6 +126,7 @@ protected: void CallEndMethod(void); private: + void Initialize(void); void CreateDicomDir(void); // void AddObjectToEnd(gdcmDicomDirType type, gdcmSQItem *s); void AddDicomDirMeta (); diff --git a/src/gdcmDictEntry.cxx b/src/gdcmDictEntry.cxx index da623a2e..598a083c 100644 --- a/src/gdcmDictEntry.cxx +++ b/src/gdcmDictEntry.cxx @@ -8,7 +8,6 @@ //----------------------------------------------------------------------------- // Constructor / Destructor /** - * \ingroup gdcmDictEntry * \brief Constructor * @param InGroup DICOM-Group Number * @param InElement DICOM-Element Number @@ -20,13 +19,14 @@ gdcmDictEntry::gdcmDictEntry(guint16 InGroup, guint16 InElement, std::string InVr, std::string InFourth, - std::string InName) { - group = InGroup; - element = InElement; - vr = InVr; - fourth = InFourth; - name = InName; - key = TranslateToKey(group, element); + std::string InName) +{ + group = InGroup; + element = InElement; + vr = InVr; + fourth = InFourth; + name = InName; + key = TranslateToKey(group, element); /// \todo Frog MEMORY LEAK. } //----------------------------------------------------------------------------- @@ -35,15 +35,14 @@ gdcmDictEntry::gdcmDictEntry(guint16 InGroup, guint16 InElement, //----------------------------------------------------------------------------- // Public /** - * \ingroup gdcmDictEntry * \brief concatenates 2 guint16 (supposed to be a Dicom group number * and a Dicom element number) * @param group the Dicom group number used to build the tag * @param element the Dicom element number used to build the tag * @return the built tag */ - -TagKey gdcmDictEntry::TranslateToKey(guint16 group, guint16 element) { +TagKey gdcmDictEntry::TranslateToKey(guint16 group, guint16 element) +{ char trash[10]; TagKey key; // CLEANME: better call the iostream<< with the hex manipulator on. @@ -55,7 +54,6 @@ TagKey gdcmDictEntry::TranslateToKey(guint16 group, guint16 element) { } /** - * \ingroup gdcmDictEntry * \brief If-and only if-the V(alue) R(epresentation) * \ is unset then overwrite it. * @param NewVr New V(alue) R(epresentation) to be set. diff --git a/src/gdcmDocEntrySet.h b/src/gdcmDocEntrySet.h index ba2a142a..48e183d0 100644 --- a/src/gdcmDocEntrySet.h +++ b/src/gdcmDocEntrySet.h @@ -18,36 +18,29 @@ public: /// \brief adds any type of entry to the entry set (pure vitual) virtual bool AddEntry(gdcmDocEntry *Entry) = 0; // pure virtual - //FIXME bool CheckEntryVR(gdcmDocEntry *Entry, std::string vr); /// \brief prints any type of entry to the entry set (pure vitual) virtual void Print (std::ostream & os = std::cout) = 0;// pure virtual - /// \brief Gets the depth level of a Dicom Header Entry embedded in a SeQuence - inline int GetDepthLevel(void) - {return(SQDepthLevel);} + /// \brief Gets the depth level of a Dicom Header Entry embedded in a + /// SeQuence + inline int GetDepthLevel(void) {return(SQDepthLevel);} - /// \brief Sets the depth level of a Dicom Header Entry embedded in a SeQuence - inline void SetDepthLevel(int depth) - {SQDepthLevel = depth;} + /// \brief Sets the depth level of a Dicom Header Entry embedded in a + /// SeQuence + inline void SetDepthLevel(int depth) {SQDepthLevel = depth;} protected: - -// void gdcmDocEntrySet::FindDocEntryLength (gdcmDocEntry *Entry); - - // DocEntry related utilities - - /// \brief Build a new Element Value from all the low level arguments. - /// Check for existence of dictionary entry, and build - /// a default one when absent (pure virtual) + /// \brief Build a new Element Value from all the low level arguments. + /// Check for existence of dictionary entry, and build + /// a default one when absent (pure virtual) virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element)=0; // pure virtual - /// \brief Build a new Element Value from all the low level arguments. - /// Check for existence of dictionary entry, and build - /// a default one when absent (pure virtual) - virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0;// pure virtual - + /// \brief Build a new Element Value from all the low level arguments. + /// Check for existence of dictionary entry, and build + /// a default one when absent (pure virtual) + virtual gdcmDocEntry *NewDocEntryByName (std::string Name)=0;// pure virtual /// Gives the depth level of the element set inside SeQuences int SQDepthLevel; diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 9dd23bbc..3e3c3ac1 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -160,16 +160,7 @@ gdcmDocument::~gdcmDocument (void) { // Recursive clean up of sequences for (TagDocEntryHT::iterator it = tagHT.begin(); it != tagHT.end(); ++it ) { - gdcmDocEntry * entry = it->second; - if ( gdcmSeqEntry* SeqEntry = dynamic_cast(entry) ) - { - delete SeqEntry; - RemoveEntry(SeqEntry); - } - else - { - RemoveEntry(entry); - } + delete (it->second); } tagHT.clear(); } @@ -626,13 +617,12 @@ gdcmValEntry * gdcmDocument::ReplaceOrCreateByNumber( * \return pointer to the modified/created Header Entry (NULL when creation * failed). */ - - gdcmBinEntry * gdcmDocument::ReplaceOrCreateByNumber( void *voidArea, int lgth, guint16 Group, - guint16 Elem ){ + guint16 Elem) +{ gdcmDocEntry* a; gdcmBinEntry* b; a = GetDocEntryByNumber( Group, Elem); @@ -1376,7 +1366,7 @@ guint16 gdcmDocument::UnswapShort(guint16 a) { long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool delim_mode) { gdcmDocEntry *NewDocEntry = (gdcmDocEntry *)0; - gdcmValEntry *vl; + gdcmValEntry *NewValEntry = (gdcmValEntry *)0; gdcmBinEntry *bn; gdcmSeqEntry *sq; VRKey vr; @@ -1394,17 +1384,18 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool break; vr = NewDocEntry->GetVR(); - if (vr!="SQ") { + if (vr!="SQ") + { if ( gdcmGlobal::GetVR()->IsVROfGdcmStringRepresentable(vr) ) { /////// ValEntry - vl= new gdcmValEntry(NewDocEntry->GetDictEntry()); - vl->Copy(NewDocEntry); - vl->SetDepthLevel(depth); - set->AddEntry(vl); - LoadDocEntry(vl); - if (/*!delim_mode && */vl->isItemDelimitor()) + NewValEntry = new gdcmValEntry(NewDocEntry->GetDictEntry()); + NewValEntry->Copy(NewDocEntry); + NewValEntry->SetDepthLevel(depth); + set->AddEntry(NewValEntry); + LoadDocEntry(NewValEntry); + if (/*!delim_mode && */NewValEntry->isItemDelimitor()) break; if ( !delim_mode && ftell(fp)-offset >= l_max) { @@ -1441,7 +1432,9 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool SkipToNextDocEntry(NewDocEntry); l = NewDocEntry->GetFullLength(); } - } else { // VR = "SQ" + } + else + { // VR = "SQ" l=NewDocEntry->GetReadLength(); if (l != 0) // don't mess the delim_mode for zero-length sequence @@ -1469,8 +1462,8 @@ long gdcmDocument::ParseDES(gdcmDocEntrySet *set, long offset, long l_max, bool break; } } + delete NewDocEntry; } - delete NewDocEntry; return l; // ?? } @@ -1530,7 +1523,8 @@ long gdcmDocument::ParseSQ(gdcmSeqEntry *set, * the value specified with gdcmDocument::SetMaxSizeLoadEntry() * @param Entry Header Entry (Dicom Element) to be dealt with */ -void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) { +void gdcmDocument::LoadDocEntry(gdcmDocEntry *Entry) +{ size_t item_read; guint16 group = Entry->GetGroup(); std::string vr= Entry->GetVR(); @@ -2505,15 +2499,6 @@ gdcmDocEntry *gdcmDocument::ReadNextDocEntry(void) { // header parsing has to be considered as finished. return (gdcmDocEntry *)0; -// Pb : how to propagate the element length (used in SkipDocEntry) -// direct call to SkipBytes ? - -// if (ignoreShadow == 1 && g%2 ==1) - // if user wants to skip shadow groups - // and current element *is* a shadow element - // we don't create anything -// return (gdcmDocEntry *)1; // to tell caller it's NOT finished - NewEntry = NewDocEntryByNumber(g, n); FindDocEntryVR(NewEntry); FindDocEntryLength(NewEntry); @@ -2572,7 +2557,7 @@ gdcmDictEntry *gdcmDocument::NewVirtualDictEntry(guint16 group, guint16 element, * @param Group group number of the underlying DictEntry * @param Elem element number of the underlying DictEntry */ -gdcmDocEntry *gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) +gdcmDocEntry* gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) { // Find out if the tag we encountered is in the dictionaries: gdcmDictEntry *DictEntry = GetDictEntryByNumber(Group, Elem); @@ -2584,7 +2569,7 @@ gdcmDocEntry *gdcmDocument::NewDocEntryByNumber(guint16 Group, guint16 Elem) { dbg.Verbose(1, "gdcmDocument::NewDocEntryByNumber", "failed to allocate gdcmDocEntry"); - return NULL; + return (gdcmDocEntry*)0; } return NewEntry; } diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index e98a3446..b9d59ac0 100644 --- a/src/gdcmElementSet.cxx +++ b/src/gdcmElementSet.cxx @@ -91,7 +91,7 @@ bool gdcmElementSet::RemoveEntry( gdcmDocEntry *EntryToRemove) if(tagHT.count(key) == 1) { tagHT.erase(key); - dbg.Verbose(1, "gdcmElementSet::RemoveEntry: one element erased."); + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: one element erased."); return true; } diff --git a/src/gdcmSQItem.cxx b/src/gdcmSQItem.cxx index 2dd62176..02ac489c 100644 --- a/src/gdcmSQItem.cxx +++ b/src/gdcmSQItem.cxx @@ -1,12 +1,28 @@ -// gdcmSQItem.cxx -//----------------------------------------------------------------------------- -// +/*========================================================================= + + Program: gdcm + Module: $RCSfile: gdcmSQItem.cxx,v $ + Language: C++ + Date: $Date: 2004/06/19 23:51:04 $ + Version: $Revision: 1.10 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + #include "gdcmSQItem.h" #include "gdcmSeqEntry.h" +#include "gdcmValEntry.h" +#include "gdcmBinEntry.h" #include "gdcmGlobal.h" #include "gdcmUtil.h" -#include "gdcmValEntry.h" - +#include "gdcmDebug.h" //----------------------------------------------------------------------------- // Constructor / Destructor @@ -28,24 +44,14 @@ gdcmSQItem::~gdcmSQItem() cc != docEntries.end(); ++cc) { - gdcmDocEntry* DocEntry = *cc; - if ( gdcmSeqEntry* SeqEntry = dynamic_cast(DocEntry) ) - { - delete SeqEntry; - } - else - { - delete DocEntry; - } + delete (*cc); } docEntries.clear(); } - //----------------------------------------------------------------------------- // Print /* - * \ingroup gdcmSQItem * \brief canonical Printer */ void gdcmSQItem::Print(std::ostream & os) { @@ -72,13 +78,13 @@ gdcmSQItem::~gdcmSQItem() /** * \brief adds any Entry (Dicom Element) to the Sequence Item */ -bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) { +bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) +{ docEntries.push_back(entry); //TODO : check if it worked return true; } - /** * \brief Sets Entry (Dicom Element) value of an element, * specified by it's tag (Group, Number) @@ -91,49 +97,63 @@ bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) { * @param element Element of the searched tag. * @return true if element was found or created successfully */ - bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, - guint16 element) { - - for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) { +bool gdcmSQItem::SetEntryByNumber(std::string val,guint16 group, + guint16 element) +{ + for(ListDocEntry::iterator i=docEntries.begin();i!=docEntries.end();++i) + { if ( (*i)->GetGroup() == 0xfffe && (*i)->GetElement() == 0xe000 ) continue; - if ( group < (*i)->GetGroup() || - (group == (*i)->GetGroup() && element < (*i)->GetElement()) ){ - // instead of ReplaceOrCreateByNumber - // that is a method of gdcmDocument :-( - gdcmDocEntry *Entry; + if ( ( group < (*i)->GetGroup() ) + ||( group == (*i)->GetGroup() && element < (*i)->GetElement()) ) + { + // instead of ReplaceOrCreateByNumber + // that is a method of gdcmDocument :-( + gdcmValEntry* Entry = (gdcmValEntry*)0; TagKey key = gdcmDictEntry::TranslateToKey(group, element); - if ( ! ptagHT->count(key)) { - // we assume a Public Dictionnary *is* loaded - gdcmDict *PubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict(); - // if the invoked (group,elem) doesn't exist inside the Dictionary - // we create a VirtualDictEntry - gdcmDictEntry *DictEntry = PubDict->GetDictEntryByNumber(group, element); - if (DictEntry == NULL) { - DictEntry=gdcmGlobal::GetDicts()->NewVirtualDictEntry(group,element,"UN","??","??"); - } - // we assume the constructor didn't fail - Entry = new gdcmDocEntry(DictEntry); - /// \todo - /// ---- - /// better we don't assume too much ! - /// gdcmSQItem is now used to describe any DICOMDIR related object - /// + if ( ! ptagHT->count(key)) + { + // we assume a Public Dictionnary *is* loaded + gdcmDict *PubDict = gdcmGlobal::GetDicts()->GetDefaultPubDict(); + // if the invoked (group,elem) doesn't exist inside the Dictionary + // we create a VirtualDictEntry + gdcmDictEntry *DictEntry = PubDict->GetDictEntryByNumber(group, + element); + if (DictEntry == NULL) + { + DictEntry=gdcmGlobal::GetDicts()->NewVirtualDictEntry(group, + element, + "UN", + "??","??"); + } + // we assume the constructor didn't fail + Entry = new gdcmValEntry(DictEntry); + /// \todo + /// ---- + /// better we don't assume too much ! + /// gdcmSQItem is now used to describe any DICOMDIR related object } else { - Entry = ptagHT->find(key)->second; + gdcmDocEntry* FoundEntry = ptagHT->find(key)->second; + Entry = dynamic_cast(FoundEntry); + if (!Entry) + dbg.Verbose(0, "gdcmSQItem::SetEntryByNumber: docEntries" + " contains non gdcmValEntry occurences"); } - ((gdcmValEntry*)Entry)->SetValue(val); + if (Entry) + Entry->SetValue(val); Entry->SetLength(val.length()); docEntries.insert(i,Entry); - return true; - } - if (group == (*i)->GetGroup() && element == (*i)->GetElement() ) { - ((gdcmValEntry*)(*i))->SetValue(val); + return true; + } + if (group == (*i)->GetGroup() && element == (*i)->GetElement() ) + { + if ( gdcmValEntry* Entry = dynamic_cast(*i) ) + Entry->SetValue(val); (*i)->SetLength(val.length()); return true; - } - } -} + } + } +} //----------------------------------------------------------------------------- // Protected @@ -145,7 +165,7 @@ bool gdcmSQItem::AddEntry(gdcmDocEntry *entry) { /// \brief to be written if really usefull gdcmDocEntry *gdcmSQItem::NewDocEntryByNumber(guint16 group, guint16 element) { -// TODO +/// \todo TODO gdcmDocEntry *a; std::cout << " gdcmSQItem::NewDocEntryByNumber : TODO" < - #include "gdcmDocEntry.h" #include "gdcmDocEntrySet.h" #include "gdcmDocument.h" + //----------------------------------------------------------------------------- typedef std::list ListDocEntry; //----------------------------------------------------------------------------- @@ -19,34 +34,29 @@ public: virtual void Print(std::ostream &os = std::cout); - /// \brief returns the DocEntry chained List for this SQ Item. - inline ListDocEntry &GetDocEntries() - {return docEntries;}; + /// \brief returns the DocEntry chained List for this SQ Item. + inline ListDocEntry &GetDocEntries() {return docEntries;}; - /// \brief adds the passed DocEntry to the DocEntry chained List for this SQ Item. - inline void AddDocEntry(gdcmDocEntry *e) - {docEntries.push_back(e);}; + /// \brief adds the passed DocEntry to the DocEntry chained List for + /// this SQ Item. + inline void AddDocEntry(gdcmDocEntry *e) {docEntries.push_back(e);}; virtual bool AddEntry(gdcmDocEntry *Entry); // add to the List - gdcmDocEntry *GetDocEntryByNumber(guint16 group, - guint16 element); + gdcmDocEntry *GetDocEntryByNumber(guint16 group, guint16 element); gdcmDocEntry *GetDocEntryByName (std::string Name); - bool SetEntryByNumber(std::string val,guint16 group, - guint16 element); + bool SetEntryByNumber(std::string val,guint16 group, guint16 element); std::string GetEntryByNumber(guint16 group, guint16 element); std::string GetEntryByName(TagName name); - inline int GetSQItemNumber() - { return SQItemNumber;}; + inline int GetSQItemNumber() { return SQItemNumber;}; - inline void SetSQItemNumber(int itemNumber) - { SQItemNumber=itemNumber;}; + inline void SetSQItemNumber(int itemNumber) { SQItemNumber=itemNumber;}; protected: - // DocEntry related utilities +// DocEntry related utilities virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element); // TODO @@ -54,23 +64,20 @@ protected: // Variables -/// \brief chained list of (Elementary) Doc Entries - ListDocEntry docEntries; + /// \brief chained list of (Elementary) Doc Entries + ListDocEntry docEntries; -/// \brief SQ Item ordinal number - int SQItemNumber; + /// \brief SQ Item ordinal number + int SQItemNumber; - -///\brief pointer to the HTable of the gdcmDocument, -/// (because we don't know it within any gdcmObject nor any gdcmSQItem) - TagDocEntryHT *ptagHT; + ///\brief pointer to the HTable of the gdcmDocument, + /// (because we don't know it within any gdcmObject nor any gdcmSQItem) + TagDocEntryHT *ptagHT; private: }; - //----------------------------------------------------------------------------- #endif -