X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=0b907069e0465b3684389aeb0dd4747898ee550d;hb=e51bf0565bbe4c0e269dd941cb4071ebde6012e4;hp=5dd5ef264c0fae05ec66b2724956abbe631da62e;hpb=1ce6ae86daabc8b64c9309acce4ecf137ee79f07;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 5dd5ef26..0b907069 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2005/01/31 12:19:34 $ - Version: $Revision: 1.217 $ + Date: $Date: 2005/02/14 10:45:04 $ + Version: $Revision: 1.230 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -30,19 +30,10 @@ #include #include - -// For nthos: -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) - #include -#endif - -#ifdef CMAKE_HAVE_NETINET_IN_H - #include -#endif +#include namespace gdcm { - //----------------------------------------------------------------------------- // Refer to Document::CheckSwap() //const unsigned int Document::HEADER_LENGTH_TO_READ = 256; @@ -53,12 +44,13 @@ const unsigned int Document::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff; //----------------------------------------------------------------------------- // Constructor / Destructor - +// Constructors and destructors are protected to avoid user to invoke directly /** * \brief constructor * @param filename 'Document' (File or DicomDir) 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; @@ -72,13 +64,12 @@ Document::Document( std::string const &filename ) : ElementSet(-1) Group0002Parsed = false; - gdcmVerboseMacro( "Starting parsing of file: " << Filename.c_str()); - // Fp->seekg( 0, std::ios::beg); - - Fp->seekg(0, std::ios::end); + gdcmWarningMacro( "Starting parsing of file: " << Filename.c_str()); + + Fp->seekg(0, std::ios::end); long lgt = Fp->tellg(); - Fp->seekg( 0, std::ios::beg); + Fp->seekg(0, std::ios::beg); CheckSwap(); long beg = Fp->tellg(); @@ -154,7 +145,8 @@ Document::Document( std::string const &filename ) : ElementSet(-1) * \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) { Fp = 0; @@ -174,31 +166,6 @@ Document::~Document () RefShaDict = NULL; } -//----------------------------------------------------------------------------- -// Print - -/** - * \brief Prints The Dict Entries of THE public Dicom Dictionary - * @param os ostream to print to - * @return - */ -void Document::PrintPubDict(std::ostream &os) -{ - RefPubDict->SetPrintLevel(PrintLevel); - RefPubDict->Print(os); -} - -/** - * \brief Prints The Dict Entries of THE shadow Dicom Dictionary - * @param os ostream to print to - * @return - */ -void Document::PrintShaDict(std::ostream &os) -{ - RefShaDict->SetPrintLevel(PrintLevel); - RefShaDict->Print(os); -} - //----------------------------------------------------------------------------- // Public /** @@ -249,13 +216,13 @@ bool Document::IsReadable() { if( Filetype == Unknown) { - gdcmVerboseMacro( "Wrong filetype"); + gdcmWarningMacro( "Wrong filetype"); return false; } if ( IsEmpty() ) { - gdcmVerboseMacro( "No tag in internal hash table."); + gdcmWarningMacro( "No tag in internal hash table."); return false; } @@ -356,7 +323,7 @@ std::string Document::GetTransferSyntaxName() } if ( transferSyntax == GDCM_UNFOUND ) { - gdcmVerboseMacro( "Unfound Transfer Syntax (0002,0010)"); + gdcmWarningMacro( "Unfound Transfer Syntax (0002,0010)"); return "Uncompressed ACR-NEMA"; } @@ -376,7 +343,9 @@ uint16_t Document::SwapShort(uint16_t a) { if ( SwapCode == 4321 || SwapCode == 2143 ) { - a = ((( a << 8 ) & 0x0ff00 ) | (( a >> 8 ) & 0x00ff ) ); + //a = ((( a << 8 ) & 0xff00 ) | (( a >> 8 ) & 0x00ff ) ); + // Save CPU time + a = ( a << 8 ) | ( a >> 8 ); } return a; } @@ -393,11 +362,15 @@ uint32_t Document::SwapLong(uint32_t a) case 1234 : break; case 4321 : - a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) | - ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) ); +// a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) | +// ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) ); +// save CPU time + a=( ( a<<24) | ((a<<8) & 0x00ff0000) | + ((a>>8) & 0x0000ff00) | (a>>24) ); break; case 3412 : - a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) ); +// a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) ); + a=( (a<<16) | (a>>16) ); break; case 2143 : a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); @@ -426,7 +399,7 @@ std::ifstream *Document::OpenFile() if(Fp) { - gdcmVerboseMacro( "File already open: " << Filename.c_str()); + gdcmWarningMacro( "File already open: " << Filename.c_str()); CloseFile(); } @@ -439,7 +412,7 @@ std::ifstream *Document::OpenFile() return 0; } - uint16_t zero; + uint16_t zero = 0; Fp->read((char*)&zero, (size_t)2); if( Fp->eof() ) { @@ -456,13 +429,13 @@ std::ifstream *Document::OpenFile() { std::string msg = Util::Format("ACR/DICOM with no preamble: (%04x)\n", zero); - gdcmVerboseMacro( msg.c_str() ); + gdcmWarningMacro( msg.c_str() ); return Fp; } //DICOM Fp->seekg(126L, std::ios::cur); - char dicm[4]; + char dicm[4] = {' ',' ',' ',' '}; Fp->read(dicm, (size_t)4); if( Fp->eof() ) { @@ -476,7 +449,7 @@ std::ifstream *Document::OpenFile() } CloseFile(); - gdcmVerboseMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str()); + gdcmWarningMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str()); return 0; } @@ -493,7 +466,7 @@ bool Document::CloseFile() delete Fp; Fp = 0; } - return true; //FIXME how do we detect a non-closed ifstream ? + return true; } /** @@ -520,24 +493,23 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype) fp->write("DICM", 4); } -/* - * \todo rewrite later, if really usefull - * - 'Group Length' element is optional in DICOM - * - but un-updated odd groups lengthes can causes pb - * (xmedcon breaker) - * - * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) ) - * UpdateGroupLength(false,filetype); - * if ( filetype == ACR) - * UpdateGroupLength(true,ACR); - */ - + /* + * \todo rewrite later, if really usefull + * - 'Group Length' element is optional in DICOM + * - but un-updated odd groups lengthes can causes pb + * (xmedcon breaker) + * + * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) ) + * UpdateGroupLength(false,filetype); + * if ( filetype == ACR) + * UpdateGroupLength(true,ACR); + */ + ElementSet::WriteContent(fp, filetype); // This one is recursive } // ----------------------------------------- // Content entries - /** * \brief Loads (from disk) the element content * when a string is not suitable @@ -579,11 +551,10 @@ void Document::LoadEntryBinArea(BinEntry *elem) uint8_t *a = new uint8_t[l]; if( !a ) { - gdcmVerboseMacro( "Cannot allocate BinEntry content"); + gdcmWarningMacro( "Cannot allocate BinEntry content"); return; } - /// \todo check the result Fp->read((char*)a, l); if( Fp->fail() || Fp->eof()) { @@ -601,8 +572,7 @@ void Document::LoadEntryBinArea(BinEntry *elem) * \brief Loads the element while preserving the current * underlying file position indicator as opposed to * LoadDocEntry that modifies it. - * @param entry Header Entry whose value will be loaded. - * @return + * @param entry DocEntry whose value will be loaded. */ void Document::LoadDocEntrySafe(DocEntry *entry) { @@ -614,14 +584,76 @@ void Document::LoadDocEntrySafe(DocEntry *entry) } } +/** + * \brief Compares two documents, according to \ref DicomDir rules + * \warning Does NOT work with ACR-NEMA files + * \todo Find a trick to solve the pb (use RET fields ?) + * @param document to compare with current one + * @return true if 'smaller' + */ +bool Document::operator<(Document &document) +{ + // Patient Name + std::string s1 = GetEntryValue(0x0010,0x0010); + std::string s2 = document.GetEntryValue(0x0010,0x0010); + if(s1 < s2) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + else + { + // Patient ID + s1 = GetEntryValue(0x0010,0x0020); + s2 = document.GetEntryValue(0x0010,0x0020); + if ( s1 < s2 ) + { + return true; + } + else if ( s1 > s2 ) + { + return false; + } + else + { + // Study Instance UID + s1 = GetEntryValue(0x0020,0x000d); + s2 = document.GetEntryValue(0x0020,0x000d); + if ( s1 < s2 ) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + else + { + // Serie Instance UID + s1 = GetEntryValue(0x0020,0x000e); + s2 = document.GetEntryValue(0x0020,0x000e); + if ( s1 < s2 ) + { + return true; + } + else if( s1 > s2 ) + { + return false; + } + } + } + } + return false; +} + //----------------------------------------------------------------------------- // Protected - -// Constructors and destructors are protected to avoid user to invoke directly - /** * \brief Reads a supposed to be 16 Bits integer - * (swaps it depending on processor endianity) + * (swaps it depending on processor endianness) * @return read value */ uint16_t Document::ReadInt16() @@ -643,7 +675,7 @@ uint16_t Document::ReadInt16() /** * \brief Reads a supposed to be 32 Bits integer - * (swaps it depending on processor endianity) + * (swaps it depending on processor endianness) * @return read value */ uint32_t Document::ReadInt32() @@ -721,6 +753,16 @@ int Document::ComputeGroup0002Length( FileType filetype ) //----------------------------------------------------------------------------- // Private +/** + * \brief Loads all the needed Dictionaries + * \warning NOT end user intended method ! + */ +void Document::Initialize() +{ + RefPubDict = Global::GetDicts()->GetDefaultPubDict(); + RefShaDict = NULL; + Filetype = Unknown; +} /** * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) @@ -764,7 +806,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, !Global::GetVR()->IsVROfBinaryRepresentable(vr) ) { ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR - gdcmVerboseMacro( std::hex << newDocEntry->GetGroup() + gdcmWarningMacro( std::hex << newDocEntry->GetGroup() << "|" << newDocEntry->GetElement() << " : Neither Valentry, nor BinEntry." "Probably unknown VR."); @@ -951,12 +993,6 @@ void Document::ParseSQ( SeqEntry *seqEntry, { dlm_mod = false; } - // FIXME, TODO - // when we're here, element fffe,e000 is already passed. - // it's lost for the SQItem we're going to process !! - - //ParseDES(itemSQ, newDocEntry->GetOffset(), l, dlm_mod); - //delete newDocEntry; // FIXME well ... it's too late to use it ! // Let's try :------------ // remove fff0,e000, created out of the SQItem @@ -1054,7 +1090,6 @@ void Document::LoadDocEntry(DocEntry *entry) return; } - /// \todo Any compacter code suggested (?) if ( IsDocEntryAnInteger(entry) ) { uint32_t NewInt; @@ -1112,7 +1147,7 @@ void Document::LoadDocEntry(DocEntry *entry) if( length % 2 ) { newValue = Util::DicomString(str, length+1); - gdcmVerboseMacro("Warning: bad length: " << length << + gdcmWarningMacro("Warning: bad length: " << length << ",For string :" << newValue.c_str()); // Since we change the length of string update it length //entry->SetReadLength(length+1); @@ -1127,7 +1162,7 @@ void Document::LoadDocEntry(DocEntry *entry) { if ( Fp->fail() || Fp->eof()) { - gdcmVerboseMacro("Unread element value"); + gdcmWarningMacro("Unread element value"); valEntry->SetValue(GDCM_UNREAD); return; } @@ -1327,7 +1362,7 @@ uint32_t Document::FindDocEntryLengthOBOrOW() if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) ) { long filePosition = Fp->tellg(); - gdcmVerboseMacro( "Neither an Item tag nor a Sequence delimiter tag on :" + gdcmWarningMacro( "Neither an Item tag nor a Sequence delimiter tag on :" << std::hex << group << " , " << elem << ") -before- position x(" << filePosition << ")" ); @@ -1392,9 +1427,6 @@ std::string Document::FindDocEntryVR() */ bool Document::CheckDocEntryVR(VRKey vr) { - // CLEANME searching the dicom_vr at each occurence is expensive. - // PostPone this test in an optional integrity check at the end - // of parsing or only in debug mode. if ( !Global::GetVR()->IsValidVR(vr) ) return false; @@ -1574,7 +1606,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, if ( foundLength % 2) { - gdcmVerboseMacro( "Warning : Tag with uneven length " << foundLength + gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength << " in x(" << std::hex << gr << "," << elem <<")"); } @@ -1590,7 +1622,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) ) { foundLength = 10; - entry->SetReadLength(10); /// \todo a bug is to be fixed !? + entry->SetReadLength(10); // a bug is to be fixed !? } } @@ -1601,7 +1633,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) ) { foundLength = 4; - entry->SetReadLength(4); /// \todo a bug is to be fixed !? + entry->SetReadLength(4); // a bug is to be fixed !? } else if ( entry->GetVR() == "SQ" ) @@ -1633,10 +1665,10 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, */ bool Document::IsDocEntryAnInteger(DocEntry *entry) { - uint16_t elem = entry->GetElement(); - uint16_t group = entry->GetGroup(); + uint16_t elem = entry->GetElement(); + uint16_t group = entry->GetGroup(); const std::string &vr = entry->GetVR(); - uint32_t length = entry->GetLength(); + uint32_t length = entry->GetLength(); // When we have some semantics on the element we just read, and if we // a priori know we are dealing with an integer, then we shall be @@ -1657,7 +1689,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) // encounter such an ill-formed image, we simply display a warning // message and proceed on parsing (while crossing fingers). long filePosition = Fp->tellg(); - gdcmVerboseMacro( "Erroneous Group Length element length on : (" + gdcmWarningMacro( "Erroneous Group Length element length on : (" << std::hex << group << " , " << elem << ") -before- position x(" << filePosition << ")" << "lgt : " << length ); @@ -1671,17 +1703,6 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) return false; } -/** - * \brief Loads all the needed Dictionaries - * \warning NOT end user intended method ! - */ -void Document::Initialize() -{ - RefPubDict = Global::GetDicts()->GetDefaultPubDict(); - RefShaDict = NULL; - Filetype = Unknown; -} - /** * \brief Discover what the swap code is (among little endian, big endian, * bad little endian, bad big endian). @@ -1697,8 +1718,6 @@ bool Document::CheckSwap() // 0x00000004. Finding the swap code in then straigthforward. Trouble // occurs when we can't find such group... - uint32_t x = 4; // x : for ntohs - bool net2host; // true when HostByteOrder is the same as NetworkByteOrder uint32_t s32; uint16_t s16; @@ -1706,14 +1725,7 @@ bool Document::CheckSwap() // First, compare HostByteOrder and NetworkByteOrder in order to // determine if we shall need to swap bytes (i.e. the Endian type). - if ( x == ntohs(x) ) - { - net2host = true; - } - else - { - net2host = false; - } + bool net2host = Util::IsCurrentProcessorBigEndian(); // The easiest case is the one of a 'true' DICOM header, we just have // to look for the string "DICM" inside the file preamble. @@ -1722,7 +1734,7 @@ bool Document::CheckSwap() char *entCur = deb + 128; if( memcmp(entCur, "DICM", (size_t)4) == 0 ) { - gdcmVerboseMacro( "Looks like DICOM Version3 (preamble + DCM)" ); + gdcmWarningMacro( "Looks like DICOM Version3 (preamble + DCM)" ); // Group 0002 should always be VR, and the first element 0000 // Let's be carefull (so many wrong headers ...) @@ -1754,24 +1766,24 @@ bool Document::CheckSwap() // instead of just checking for UL, OB and UI !? group 0000 { Filetype = ExplicitVR; - gdcmVerboseMacro( "Group 0002 : Explicit Value Representation"); + gdcmWarningMacro( "Group 0002 : Explicit Value Representation"); } else { Filetype = ImplicitVR; - gdcmVerboseMacro( "Group 0002 :Not an explicit Value Representation;" + gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;" << "Looks like a bugged Header!"); } if ( net2host ) { SwapCode = 4321; - gdcmVerboseMacro( "HostByteOrder != NetworkByteOrder"); + gdcmWarningMacro( "HostByteOrder != NetworkByteOrder"); } else { SwapCode = 1234; - gdcmVerboseMacro( "HostByteOrder = NetworkByteOrder"); + gdcmWarningMacro( "HostByteOrder = NetworkByteOrder"); } // Position the file position indicator at first tag @@ -1784,7 +1796,7 @@ bool Document::CheckSwap() // Alas, this is not a DicomV3 file and whatever happens there is no file // preamble. We can reset the file position indicator to where the data // is (i.e. the beginning of the file). - gdcmVerboseMacro( "Not a DICOM Version3 file"); + gdcmWarningMacro( "Not a DICOM Version3 file"); Fp->seekg(0, std::ios::beg); // Our next best chance would be to be considering a 'clean' ACR/NEMA file. @@ -1859,7 +1871,7 @@ bool Document::CheckSwap() Filetype = ACR; return true; default : - gdcmVerboseMacro( "ACR/NEMA unfound swap info (Really hopeless !)"); + gdcmWarningMacro( "ACR/NEMA unfound swap info (Really hopeless !)"); Filetype = Unknown; return false; } @@ -1871,7 +1883,7 @@ bool Document::CheckSwap() */ void Document::SwitchByteSwapCode() { - gdcmVerboseMacro( "Switching Byte Swap code from "<< SwapCode); + gdcmWarningMacro( "Switching Byte Swap code from "<< SwapCode); if ( SwapCode == 1234 ) { SwapCode = 4321; @@ -1892,7 +1904,7 @@ void Document::SwitchByteSwapCode() /** * \brief during parsing, Header Elements too long are not loaded in memory - * @param newSize + * @param newSize new size */ void Document::SetMaxSizeLoadEntry(long newSize) { @@ -1910,8 +1922,8 @@ void Document::SetMaxSizeLoadEntry(long newSize) /** * \brief Header Elements too long will not be printed - * \todo See comments of \ref Document::MAX_SIZE_PRINT_ELEMENT_VALUE - * @param newSize + * See comments of \ref Document::MAX_SIZE_PRINT_ELEMENT_VALUE + * @param newSize new size */ void Document::SetMaxSizePrintEntry(long newSize) { @@ -1949,7 +1961,6 @@ DocEntry *Document::ReadNextDocEntry() { // We reached the EOF (or an error occured) therefore // header parsing has to be considered as finished. - //std::cout << e; return 0; } @@ -1989,7 +2000,7 @@ DocEntry *Document::ReadNextDocEntry() std::string msg; msg = Util::Format("Entry (%04x,%04x) should be Explicit VR\n", newEntry->GetGroup(), newEntry->GetElement()); - gdcmVerboseMacro( msg.c_str() ); + gdcmWarningMacro( msg.c_str() ); } } newEntry->SetImplicitVR(); @@ -2057,7 +2068,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) std::string ts = GetTransferSyntax(); if ( !Global::GetTS()->IsTransferSyntax(ts) ) { - gdcmVerboseMacro("True DICOM File, with NO Tansfer Syntax: " << ts ); + gdcmWarningMacro("True DICOM File, with NO Tansfer Syntax: " << ts ); return; } @@ -2072,7 +2083,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) //'Implicit VR Transfer Syntax (GE Private) if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian ) { - gdcmVerboseMacro("Transfer Syntax Name = [" + gdcmWarningMacro("Transfer Syntax Name = [" << GetTransferSyntaxName() << "]" ); SwitchByteSwapCode(); group = SwapShort(group); @@ -2081,183 +2092,8 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) } } -// GenerateFreeTagKeyInGroup? -// --> What was it designed for ?!? -/** - * \brief Generate a free TagKey i.e. a TagKey that is not present - * in the TagHt dictionary. - * @param group The generated tag must belong to this group. - * @return The element of tag with given group which is fee. - */ -//uint32_t Document::GenerateFreeTagKeyInGroup(uint16_t group) -//{ -// for (uint32_t elem = 0; elem < UINT32_MAX; elem++) -// { -// TagKey key = DictEntry::TranslateToKey(group, elem); -// if (TagHT.count(key) == 0) -// { -// return elem; -// } -// } -// return UINT32_MAX; -//} - -/** - * \brief Compares two documents, according to \ref DicomDir rules - * \warning Does NOT work with ACR-NEMA files - * \todo Find a trick to solve the pb (use RET fields ?) - * @param document - * @return true if 'smaller' - */ -bool Document::operator<(Document &document) -{ - // Patient Name - std::string s1 = GetEntryValue(0x0010,0x0010); - std::string s2 = document.GetEntryValue(0x0010,0x0010); - if(s1 < s2) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - else - { - // Patient ID - s1 = GetEntryValue(0x0010,0x0020); - s2 = document.GetEntryValue(0x0010,0x0020); - if ( s1 < s2 ) - { - return true; - } - else if ( s1 > s2 ) - { - return false; - } - else - { - // Study Instance UID - s1 = GetEntryValue(0x0020,0x000d); - s2 = document.GetEntryValue(0x0020,0x000d); - if ( s1 < s2 ) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - else - { - // Serie Instance UID - s1 = GetEntryValue(0x0020,0x000e); - s2 = document.GetEntryValue(0x0020,0x000e); - if ( s1 < s2 ) - { - return true; - } - else if( s1 > s2 ) - { - return false; - } - } - } - } - return false; -} - -/* - * \brief Walk recursively the given \ref DocEntrySet, and feed - * the given hash table (\ref TagDocEntryHT) with all the - * \ref DocEntry (Dicom entries) encountered. - * This method does the job for \ref BuildFlatHashTable. - * @param builtHT Where to collect all the \ref DocEntry encountered - * when recursively walking the given set. - * @param set The structure to be traversed (recursively). - */ -/*void Document::BuildFlatHashTableRecurse( TagDocEntryHT &builtHT, - DocEntrySet *set ) -{ - if (ElementSet *elementSet = dynamic_cast< ElementSet* > ( set ) ) - { - TagDocEntryHT const ¤tHT = elementSet->GetTagHT(); - for( TagDocEntryHT::const_iterator i = currentHT.begin(); - i != currentHT.end(); - ++i) - { - DocEntry *entry = i->second; - if ( SeqEntry *seqEntry = dynamic_cast(entry) ) - { - const ListSQItem& items = seqEntry->GetSQItems(); - for( ListSQItem::const_iterator item = items.begin(); - item != items.end(); - ++item) - { - BuildFlatHashTableRecurse( builtHT, *item ); - } - continue; - } - builtHT[entry->GetKey()] = entry; - } - return; - } - - if (SQItem *SQItemSet = dynamic_cast< SQItem* > ( set ) ) - { - 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) ) - { - const ListSQItem& items = seqEntry->GetSQItems(); - for( ListSQItem::const_iterator item = items.begin(); - item != items.end(); - ++item) - { - BuildFlatHashTableRecurse( builtHT, *item ); - } - continue; - } - builtHT[entry->GetKey()] = entry; - } - - } -}*/ - -/* - * \brief Build a \ref TagDocEntryHT (i.e. a std::map<>) from the current - * Document. - * - * The structure used by a Document (through \ref ElementSet), - * in order to hold the parsed entries of a Dicom header, is a recursive - * one. This is due to the fact that the sequences (when present) - * can be nested. Additionaly, the sequence items (represented in - * gdcm as \ref SQItem) add an extra complexity to the data - * structure. Hence, a gdcm user whishing to visit all the entries of - * a Dicom header will need to dig in the gdcm internals (which - * implies exposing all the internal data structures to the API). - * In order to avoid this burden to the user, \ref BuildFlatHashTable - * recursively builds a temporary hash table, which holds all the - * Dicom entries in a flat structure (a \ref TagDocEntryHT i.e. a - * std::map<>). - * \warning Of course there is NO integrity constrain between the - * returned \ref TagDocEntryHT and the \ref ElementSet used - * to build it. Hence if the underlying \ref ElementSet is - * altered, then it is the caller responsability to invoke - * \ref BuildFlatHashTable again... - * @return The flat std::map<> we juste build. - */ -/*TagDocEntryHT *Document::BuildFlatHashTable() -{ - TagDocEntryHT *FlatHT = new TagDocEntryHT; - BuildFlatHashTableRecurse( *FlatHT, this ); - return FlatHT; -}*/ - -} // end namespace gdcm +//----------------------------------------------------------------------------- +// Print //----------------------------------------------------------------------------- +} // end namespace gdcm