+/**
+ * \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)
+ * @param set DocEntrySet we are going to parse ('zero level' or a SQItem)
+ * @param offset start of parsing
+ * @param l_max length to parse (meaningless when we are in 'delimitor mode')
+ * @param delim_mode : whether we are in 'delimitor mode' (l=0xffffff) or not
+ */
+void Document::ParseDES(DocEntrySet *set, long offset,
+ long l_max, bool delim_mode)
+{
+ DocEntry *newDocEntry;
+ DataEntry *newDataEntry;
+ SeqEntry *newSeqEntry;
+ //VRKey vr;
+ bool used; // will be set to false when something wrong happens to an Entry.
+ // (Entry will then be deleted)
+ bool delim_mode_intern = delim_mode;
+ bool first = true;
+ gdcmDebugMacro( "Enter in ParseDES, delim-mode " << delim_mode
+ << " at offset " << std::hex << "0x(" << offset << ")" );
+ while (true)
+ {
+
+ ///\todo FIXME : On 64 bits processors, tellg gives unexpected results after a while ?
+ /// Probabely a bug in gdcm code somwhere (some memory erased ?)
+
+// Uncomment to track the bug
+/*
+ if( Debug::GetDebugFlag() )
+ std::cout << std::dec <<"(long)(Fp->tellg()) " << (long)(Fp->tellg()) // in Debug mode
+ << std::hex << " 0x(" <<(long)(Fp->tellg()) << ")" << std::endl;
+ */
+
+ // if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry
+ if ( !delim_mode ) // 'and then' doesn't exist in C++ :-(
+ if ( ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry, when no delim mode
+ {
+ break;
+ }
+
+ newDocEntry = ReadNextDocEntry( );
+
+ if ( !newDocEntry )
+ {
+ break;
+ }
+
+ // Uncoment this cerr line to be able to 'follow' the DocEntries
+ // when something *very* strange happens
+ if( Debug::GetDebugFlag() )
+ std::cerr<<newDocEntry->GetKey()<<" "<<newDocEntry->GetVR()<<std::endl;
+
+ // an Item Starter found elsewhere but in the first position
+ // of a SeqEntry means previous entry was a Sequence
+ // but we didn't get it (private Sequence + Implicit VR)
+ // we have to backtrack.
+ if ( !first && newDocEntry->IsItemStarter() )
+ {
+ // Debug message within the method !
+ newDocEntry = Backtrack(newDocEntry);
+ }
+ else
+ {
+ PreviousDocEntry = newDocEntry;
+ }
+
+ used = true;
+ newDataEntry = dynamic_cast<DataEntry*>(newDocEntry);
+
+ if ( newDataEntry )
+ {
+ //////////////////////////// DataEntry
+
+ //vr = newDocEntry->GetVR(); // useless ?
+
+ if ( !set->AddEntry( newDataEntry ) )
+ {
+ gdcmDebugMacro( "in ParseDES : cannot add a DataEntry "
+ << newDataEntry->GetKey()
+ << " (at offset : 0x("
+ << newDataEntry->GetOffset() << ") )" );
+ used=false;
+ }
+ else
+ {
+ newDataEntry->Delete();
+ // Load only if we can add (not a duplicate key)
+ LoadDocEntry( newDataEntry );
+ }
+ if ( newDataEntry->GetElement() == 0x0000 ) // if on group length
+ {
+ if ( newDataEntry->GetGroup()%2 != 0 ) // if Shadow Group
+ {
+ if ( LoadMode & LD_NOSHADOW ) // if user asked to skip shad.gr
+ {
+ std::string strLgrGroup = newDataEntry->GetString();
+
+ int lgrGroup;
+ //if ( newDataEntry->IsUnfound() ) /?!? JPR
+ {
+ lgrGroup = atoi(strLgrGroup.c_str());
+ Fp->seekg(lgrGroup, std::ios::cur); // Once per Shadow group, when NOSHADOW
+ RemoveEntry( newDocEntry ); // Remove and delete
+ continue;
+ }
+ }
+ }
+ }
+
+ bool delimitor = newDataEntry->IsItemDelimitor();
+ bool outOfBounds = false;
+ if (!delim_mode )
+ if ( ((long)(Fp->tellg())-offset) >= l_max ) //Once per DataEntry when no delim mode
+ outOfBounds = true;
+
+ // 'and then', 'or else' don't exist in C++ :-(
+ // if ( (delimitor) ||
+ // (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) ) // Once per DataEntry
+
+ if ( delimitor || outOfBounds )
+ {
+ if ( !used )
+ newDocEntry->Delete();
+ break;
+ }
+
+ // Just to make sure we are at the beginning of next entry.
+ SkipToNextDocEntry(newDocEntry); // FIXME : once per DocEntry, segfault if commented out
+ }
+ else
+ {
+ /////////////////////// SeqEntry : VR = "SQ"
+
+ unsigned long l = newDocEntry->GetReadLength();
+ if ( l != 0 ) // don't mess the delim_mode for 'zero-length sequence'
+ {
+ if ( l == 0xffffffff )
+ {
+ delim_mode_intern = true;
+ }
+ else
+ {
+ delim_mode_intern = false;
+ }
+ }
+
+ if ( (LoadMode & LD_NOSHADOWSEQ) && ! delim_mode_intern )
+ {
+ // User asked to skip SeQuences *only* if they belong to Shadow Group
+ if ( newDocEntry->GetGroup()%2 != 0 )
+ {
+ Fp->seekg( l, std::ios::cur); // once per SQITEM, when NOSHADOWSEQ
+ newDocEntry->Delete(); // Delete, not in the set
+ continue;
+ }
+ }
+ if ( (LoadMode & LD_NOSEQ) && ! delim_mode_intern )
+ {
+ // User asked to skip *any* SeQuence
+ Fp->seekg( l, std::ios::cur); // Once per SQ, when NOSEQ
+ newDocEntry->Delete(); // Delete, not in the set
+ continue;
+ }
+ // delay the dynamic cast as late as possible
+ newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
+
+ // no other way to create the Delimitor ...
+ newSeqEntry->SetDelimitorMode( delim_mode_intern );
+
+ // At the top of the hierarchy, stands a Document. When "set"
+ // is a Document, then we are building the first depth level.
+ // Hence the SeqEntry we are building simply has a depth
+ // level of one:
+ if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
+ {
+ newSeqEntry->SetDepthLevel( 1 );
+ }
+ // But when "set" is already a SQItem, we are building a nested
+ // sequence, and hence the depth level of the new SeqEntry
+ // we are building, is one level deeper:
+
+ // time waste hunting
+ else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+ {
+ newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
+ }
+
+ if ( l != 0 )
+ { // Don't try to parse zero-length sequences
+
+ gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
+ << " at offset 0x(" << std::hex
+ << newDocEntry->GetOffset() << ")");
+
+ ParseSQ( newSeqEntry,
+ newDocEntry->GetOffset(),
+ l, delim_mode_intern);
+
+ gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
+ }
+ if ( !set->AddEntry( newSeqEntry ) )
+ {
+ gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry "
+ << newSeqEntry->GetKey()
+ << " (at offset : 0x("
+ << newSeqEntry->GetOffset() << ") )" );
+ used = false;
+ }
+ else
+ {
+ newDocEntry->Delete();
+ }
+
+ // if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) // Once per SeqEntry
+
+ if ( !delim_mode ) // 'and then' doesn't exist in C++ :-(
+ if ( ((long)(Fp->tellg())-offset) >= l_max) // Once per SeqEntry when no delim mode
+
+ {
+ if ( !used )
+ newDocEntry->Delete();
+ break;
+ }
+ } // end SeqEntry : VR = "SQ"
+
+ if ( !used )
+ {
+ newDocEntry->Delete();
+ }
+ first = false;
+ } // end While
+ gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
+}