X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=ab150ec1196e13b5ab4c52f2f0e2dae1c8305131;hb=refs%2Ftags%2FVersion0.6.bp;hp=f78a25a5ed32abe26517073ae95a481aefda0c5f;hpb=80f7a0ffbc39a8a7c47c2a8c6c9a272515d55d6f;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index f78a25a5..ab150ec1 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2004/10/22 13:56:45 $ - Version: $Revision: 1.110 $ + Date: $Date: 2004/11/05 21:23:46 $ + Version: $Revision: 1.118 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -84,8 +84,7 @@ const unsigned int Document::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff; * \brief constructor * @param filename file to be opened for parsing */ -Document::Document( std::string const & filename ) - : ElementSet(-1) +Document::Document( std::string const & filename ) : ElementSet(-1) { SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE); Filename = filename; @@ -180,8 +179,7 @@ Document::Document( std::string const & filename ) * \brief This default constructor doesn't parse the file. You should * then invoke \ref Document::SetFileName and then the parsing. */ -Document::Document() - :ElementSet(-1) +Document::Document() : ElementSet(-1) { SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE); Initialise(); @@ -203,6 +201,8 @@ Document::~Document () //delete it->second; //temp remove } TagHT.clear(); + delete RLEInfo; + delete JPEGInfo; } //----------------------------------------------------------------------------- @@ -478,7 +478,8 @@ void Document::Write(std::ofstream* fp, FileType filetype) if (filetype == ImplicitVR) { - std::string ts = TransferSyntaxStrings[ImplicitVRLittleEndian]; + std::string ts = + Util::DicomString( TransferSyntaxStrings[ImplicitVRLittleEndian] ); ReplaceOrCreateByNumber(ts, 0x0002, 0x0010); /// \todo Refer to standards on page 21, chapter 6.2 @@ -491,8 +492,9 @@ void Document::Write(std::ofstream* fp, FileType filetype) if (filetype == ExplicitVR) { - std::string ts = TransferSyntaxStrings[ExplicitVRLittleEndian]; - ReplaceOrCreateByNumber(ts, 0x0002, 0x0010); + std::string ts = + Util::DicomString( TransferSyntaxStrings[ExplicitVRLittleEndian] ); + ReplaceOrCreateByNumber(ts, 0x0002, 0x0010); //LEAK /// \todo Refer to standards on page 21, chapter 6.2 /// "Value representation": values with a VR of UI shall be @@ -532,7 +534,7 @@ ValEntry* Document::ReplaceOrCreateByNumber( std::string const & value, uint16_t group, uint16_t elem, - std::string const & VR ) + TagName const & vr ) { ValEntry* valEntry = 0; DocEntry* currentEntry = GetDocEntryByNumber( group, elem); @@ -548,7 +550,7 @@ ValEntry* Document::ReplaceOrCreateByNumber( DictEntry* dictEntry = pubDict->GetDictEntryByNumber(group, elem); if (!dictEntry) { - currentEntry = NewDocEntryByNumber(group, elem,VR); + currentEntry = NewDocEntryByNumber(group, elem, vr); } else { @@ -564,9 +566,13 @@ ValEntry* Document::ReplaceOrCreateByNumber( valEntry = new ValEntry(currentEntry); if ( !AddEntry(valEntry)) { + delete valEntry; dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: AddEntry" " failed allthough this is a creation."); } + // This is the reason why NewDocEntryByNumber are a real + // bad habit !!! FIXME + delete currentEntry; } else { @@ -579,12 +585,14 @@ ValEntry* Document::ReplaceOrCreateByNumber( valEntry = new ValEntry(currentEntry); if (!RemoveEntry(currentEntry)) { + delete valEntry; dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: removal" " of previous DocEntry failed."); return NULL; } if ( !AddEntry(valEntry)) { + delete valEntry; dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: adding" " promoted ValEntry failed."); return NULL; @@ -611,7 +619,7 @@ BinEntry* Document::ReplaceOrCreateByNumber( int lgth, uint16_t group, uint16_t elem, - std::string const& VR ) + TagName const & vr ) { BinEntry* binEntry = 0; DocEntry* currentEntry = GetDocEntryByNumber( group, elem); @@ -628,7 +636,7 @@ BinEntry* Document::ReplaceOrCreateByNumber( if (!dictEntry) { - currentEntry = NewDocEntryByNumber(group, elem, VR); + currentEntry = NewDocEntryByNumber(group, elem, vr); } else { @@ -685,9 +693,7 @@ BinEntry* Document::ReplaceOrCreateByNumber( * \return pointer to the modified/created SeqEntry (NULL when creation * failed). */ -SeqEntry* Document::ReplaceOrCreateByNumber( - uint16_t group, - uint16_t elem) +SeqEntry* Document::ReplaceOrCreateByNumber( uint16_t group, uint16_t elem) { SeqEntry* b = 0; DocEntry* a = GetDocEntryByNumber( group, elem); @@ -714,7 +720,7 @@ SeqEntry* Document::ReplaceOrCreateByNumber( * \return boolean */ bool Document::ReplaceIfExistByNumber(std::string const & value, - uint16_t group, uint16_t elem ) + uint16_t group, uint16_t elem ) { SetEntryByNumber(value, group, elem); @@ -733,7 +739,7 @@ bool Document::ReplaceIfExistByNumber(std::string const & value, bool Document::CheckIfEntryExistByNumber(uint16_t group, uint16_t element ) { const std::string &key = DictEntry::TranslateToKey(group, element ); - return TagHT.count(key); + return TagHT.count(key) != 0; } /** @@ -745,7 +751,7 @@ bool Document::CheckIfEntryExistByNumber(uint16_t group, uint16_t element ) * @return Corresponding element value when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string Document::GetEntryByName(TagName const& tagName) +std::string Document::GetEntryByName(TagName const & tagName) { DictEntry* dictEntry = RefPubDict->GetDictEntryByName(tagName); if( !dictEntry ) @@ -778,7 +784,7 @@ std::string Document::GetEntryVRByName(TagName const& tagName) } DocEntry* elem = GetDocEntryByNumber(dictEntry->GetGroup(), - dictEntry->GetElement()); + dictEntry->GetElement()); return elem->GetVR(); } @@ -850,7 +856,8 @@ int Document::GetEntryLengthByNumber(uint16_t group, uint16_t element) * @param tagName name of the searched Dicom Element. * @return true when found */ -bool Document::SetEntryByName(std::string const & content,std::string const & tagName) +bool Document::SetEntryByName(std::string const & content, + TagName const & tagName) { DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( !dictEntry ) @@ -871,8 +878,7 @@ bool Document::SetEntryByName(std::string const & content,std::string const & ta * @param element element number of the Dicom Element to modify */ bool Document::SetEntryByNumber(std::string const& content, - uint16_t group, - uint16_t element) + uint16_t group, uint16_t element) { int c; int l; @@ -885,13 +891,10 @@ bool Document::SetEntryByNumber(std::string const& content, return false; } // Non even content must be padded with a space (020H)... - std::string finalContent = content; - if( finalContent.length() % 2 ) - { - finalContent += '\0'; // ... therefore we padd with (000H) .!?! - } + std::string finalContent = Util::DicomString( content.c_str() ); + assert( !(finalContent.size() % 2) ); valEntry->SetValue(finalContent); - + // Integers have a special treatement for their length: l = finalContent.length(); @@ -924,10 +927,8 @@ bool Document::SetEntryByNumber(std::string const& content, * @param group group number of the Dicom Element to modify * @param element element number of the Dicom Element to modify */ -bool Document::SetEntryByNumber(uint8_t*content, - int lgth, - uint16_t group, - uint16_t element) +bool Document::SetEntryByNumber(uint8_t*content, int lgth, + uint16_t group, uint16_t element) { (void)lgth; //not used TagKey key = DictEntry::TranslateToKey(group, element); @@ -963,8 +964,7 @@ bool Document::SetEntryByNumber(uint8_t*content, * @return true on success, false otherwise. */ bool Document::SetEntryLengthByNumber(uint32_t l, - uint16_t group, - uint16_t element) + uint16_t group, uint16_t element) { /// \todo use map methods, instead of multimap JPR TagKey key = DictEntry::TranslateToKey(group, element); @@ -1093,8 +1093,7 @@ void* Document::LoadEntryBinArea(BinEntry* element) * @return */ bool Document::SetEntryBinAreaByNumber(uint8_t* area, - uint16_t group, - uint16_t element) + uint16_t group, uint16_t element) { DocEntry* currentEntry = GetDocEntryByNumber(group, element); if ( !currentEntry ) @@ -1164,7 +1163,7 @@ void Document::UpdateShaEntries() * @return Corresponding Dicom Element when it exists, and NULL * otherwise. */ -DocEntry* Document::GetDocEntryByName(std::string const & tagName) +DocEntry* Document::GetDocEntryByName(TagName const & tagName) { DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); if( !dictEntry ) @@ -1185,8 +1184,7 @@ DocEntry* Document::GetDocEntryByName(std::string const & tagName) * @param element Element number of the searched Dicom Element * @return */ -DocEntry* Document::GetDocEntryByNumber(uint16_t group, - uint16_t element) +DocEntry* Document::GetDocEntryByNumber(uint16_t group, uint16_t element) { TagKey key = DictEntry::TranslateToKey(group, element); if ( !TagHT.count(key)) @@ -1202,8 +1200,7 @@ DocEntry* Document::GetDocEntryByNumber(uint16_t group, * ValEntry. * @return When present, the corresponding ValEntry. */ -ValEntry* Document::GetValEntryByNumber(uint16_t group, - uint16_t element) +ValEntry* Document::GetValEntryByNumber(uint16_t group, uint16_t element) { DocEntry* currentEntry = GetDocEntryByNumber(group, element); if ( !currentEntry ) @@ -1303,10 +1300,8 @@ uint16_t Document::UnswapShort(uint16_t a) * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) * @return length of the parsed set. */ -void Document::ParseDES(DocEntrySet *set, - long offset, - long l_max, - bool delim_mode) +void Document::ParseDES(DocEntrySet *set, long offset, + long l_max, bool delim_mode) { DocEntry *newDocEntry = 0; @@ -1371,7 +1366,7 @@ void Document::ParseDES(DocEntrySet *set, //////////////////// BinEntry or UNKOWN VR: BinEntry* newBinEntry = - new BinEntry( newDocEntry->GetDictEntry() ); + new BinEntry( newDocEntry->GetDictEntry() ); //LEAK newBinEntry->Copy( newDocEntry ); // When "this" is a Document the Key is simply of the @@ -1479,7 +1474,7 @@ void Document::ParseDES(DocEntrySet *set, * @return parsed length for this level */ void Document::ParseSQ( SeqEntry* seqEntry, - long offset, long l_max, bool delim_mode) + long offset, long l_max, bool delim_mode) { int SQItemNumber = 0; bool dlm_mod; @@ -1598,7 +1593,8 @@ void Document::LoadDocEntry(DocEntry* entry) } // to be sure we are at the end of the value ... - Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),std::ios_base::beg); + Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(), + std::ios_base::beg); return; } @@ -1660,15 +1656,28 @@ void Document::LoadDocEntry(DocEntry* entry) return; } - // We need an additional byte for storing \0 that is not on disk + // FIXME: We need an additional byte for storing \0 that is not on disk char *str = new char[length+1]; Fp->read(str, (size_t)length); - str[length] = '\0'; - std::string newValue = str; + str[length] = '\0'; //this is only useful when length is odd + // Special DicomString call to properly handle \0 and even length + std::string newValue; + if( length % 2 ) + { + newValue = Util::DicomString(str, length+1); + //dbg.Verbose(0, "Warning: bad length: ", length ); + dbg.Verbose(0, "For string :", newValue.c_str()); + // Since we change the length of string update it length + entry->SetReadLength(length+1); + } + else + { + newValue = Util::DicomString(str, length); + } delete[] str; if ( ValEntry* valEntry = dynamic_cast(entry) ) - { + { if ( Fp->fail() || Fp->eof())//Fp->gcount() == 1 { dbg.Verbose(1, "Document::LoadDocEntry", @@ -2110,7 +2119,7 @@ void Document::SkipToNextDocEntry(DocEntry *entry) * @param foundLength fist assumption about length */ void Document::FixDocEntryFoundLength(DocEntry *entry, - uint32_t foundLength) + uint32_t foundLength) { entry->SetReadLength( foundLength ); // will be updated only if a bug is found if ( foundLength == 0xffffffff) @@ -2192,7 +2201,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) { uint16_t element = entry->GetElement(); uint16_t group = entry->GetGroup(); - std::string vr = entry->GetVR(); + const std::string & vr = entry->GetVR(); uint32_t length = entry->GetLength(); // When we have some semantics on the element we just read, and if we @@ -2304,7 +2313,7 @@ uint16_t Document::ReadInt16() Fp->read ((char*)&g, (size_t)2); if ( Fp->fail() ) { - throw FormatError( "Document::ReadInt16()", " file error." ); + throw FormatError( "Document::ReadInt16()", " file error." ); } if( Fp->eof() ) { @@ -2697,8 +2706,18 @@ bool Document::ReadTag(uint16_t testGroup, uint16_t testElement) //// Read the Item Tag group and element, and make // sure they are what we expected: - uint16_t itemTagGroup = ReadInt16(); - uint16_t itemTagElement = ReadInt16(); + uint16_t itemTagGroup; + uint16_t itemTagElement; + try + { + itemTagGroup = ReadInt16(); + itemTagElement = ReadInt16(); + } + catch ( FormatError e ) + { + //std::cerr << e << std::endl; + return false; + } if ( itemTagGroup != testGroup || itemTagElement != testElement ) { std::ostringstream s; @@ -2940,19 +2959,19 @@ void Document::ComputeJPEGFragmentInfo() * @param set The structure to be traversed (recursively). */ void Document::BuildFlatHashTableRecurse( TagDocEntryHT& builtHT, - DocEntrySet* set ) + DocEntrySet* set ) { if (ElementSet* elementSet = dynamic_cast< ElementSet* > ( set ) ) { - TagDocEntryHT* currentHT = elementSet->GetTagHT(); - for( TagDocEntryHT::const_iterator i = currentHT->begin(); - i != currentHT->end(); + TagDocEntryHT const & currentHT = elementSet->GetTagHT(); + for( TagDocEntryHT::const_iterator i = currentHT.begin(); + i != currentHT.end(); ++i) { DocEntry* entry = i->second; if ( SeqEntry* seqEntry = dynamic_cast(entry) ) { - ListSQItem& items = seqEntry->GetSQItems(); + const ListSQItem& items = seqEntry->GetSQItems(); for( ListSQItem::const_iterator item = items.begin(); item != items.end(); ++item) @@ -2968,15 +2987,15 @@ void Document::BuildFlatHashTableRecurse( TagDocEntryHT& builtHT, if (SQItem* SQItemSet = dynamic_cast< SQItem* > ( set ) ) { - ListDocEntry& currentList = SQItemSet->GetDocEntries(); - for (ListDocEntry::iterator i = currentList.begin(); - i != currentList.end(); - ++i) + const ListDocEntry& currentList = SQItemSet->GetDocEntries(); + for (ListDocEntry::const_iterator i = currentList.begin(); + i != currentList.end(); + ++i) { DocEntry* entry = *i; if ( SeqEntry* seqEntry = dynamic_cast(entry) ) { - ListSQItem& items = seqEntry->GetSQItems(); + const ListSQItem& items = seqEntry->GetSQItems(); for( ListSQItem::const_iterator item = items.begin(); item != items.end(); ++item)