+/**
+ * \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)
+{
+ DocEntry *newDocEntry = 0;
+ ValEntry *newValEntry;
+ BinEntry *newBinEntry;
+ SeqEntry *newSeqEntry;
+ VRKey vr;
+ bool used = false;
+
+ while (true)
+ {
+ if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+ {
+ break;
+ }
+
+ used = true;
+ newDocEntry = ReadNextDocEntry( );
+
+ if ( !newDocEntry )
+ {
+ break;
+ }
+
+ vr = newDocEntry->GetVR();
+ newValEntry = dynamic_cast<ValEntry*>(newDocEntry);
+ newBinEntry = dynamic_cast<BinEntry*>(newDocEntry);
+ newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
+
+ if ( newValEntry || newBinEntry )
+ {
+ if ( newBinEntry )
+ {
+ if ( Filetype == ExplicitVR && ! Global::GetVR()->IsVROfBinaryRepresentable(vr) )
+ {
+ ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
+ gdcmVerboseMacro( std::hex << newDocEntry->GetGroup()
+ << "|" << newDocEntry->GetElement()
+ << " : Neither Valentry, nor BinEntry."
+ "Probably unknown VR.");
+ }
+
+ //////////////////// BinEntry or UNKOWN VR:
+ // When "this" is a Document the Key is simply of the
+ // form ( group, elem )...
+ if ( dynamic_cast< Document* > ( set ) )
+ {
+ newBinEntry->SetKey( newBinEntry->GetKey() );
+ }
+ // but when "this" is a SQItem, we are inserting this new
+ // valEntry in a sequence item, and the key has the
+ // generalized form (refer to \ref BaseTagKey):
+ if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+ {
+ newBinEntry->SetKey( parentSQItem->GetBaseTagKey()
+ + newBinEntry->GetKey() );
+ }
+
+ LoadDocEntry( newBinEntry );
+ if( !set->AddEntry( newBinEntry ) )
+ {
+ //Expect big troubles if here
+ //delete newBinEntry;
+ used=false;
+ }
+ }
+ else
+ {
+ /////////////////////// ValEntry
+ // When "set" is a Document, then we are at the top of the
+ // hierarchy and the Key is simply of the form ( group, elem )...
+ if ( dynamic_cast< Document* > ( set ) )
+ {
+ newValEntry->SetKey( newValEntry->GetKey() );
+ }
+ // ...but when "set" is a SQItem, we are inserting this new
+ // valEntry in a sequence item. Hence the key has the
+ // generalized form (refer to \ref BaseTagKey):
+ if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+ {
+ newValEntry->SetKey( parentSQItem->GetBaseTagKey()
+ + newValEntry->GetKey() );
+ }
+
+ LoadDocEntry( newValEntry );
+ bool delimitor=newValEntry->IsItemDelimitor();
+ if( !set->AddEntry( newValEntry ) )
+ {
+ // If here expect big troubles
+ //delete newValEntry; //otherwise mem leak
+ used=false;
+ }
+
+ if (delimitor)
+ {
+ if(!used)
+ delete newDocEntry;
+ break;
+ }
+ if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+ {
+ if(!used)
+ delete newDocEntry;
+ break;
+ }
+ }
+
+ if ( ( newDocEntry->GetGroup() == 0x7fe0 )
+ && ( newDocEntry->GetElement() == 0x0010 ) )
+ {
+ std::string ts = GetTransferSyntax();
+ if ( Global::GetTS()->IsRLELossless(ts) )
+ {
+ long positionOnEntry = Fp->tellg();
+ Fp->seekg( newDocEntry->GetOffset(), std::ios::beg );
+ ComputeRLEInfo();
+ Fp->seekg( positionOnEntry, std::ios::beg );
+ }
+ else if ( Global::GetTS()->IsJPEG(ts) )
+ {
+ long positionOnEntry = Fp->tellg();
+ Fp->seekg( newDocEntry->GetOffset(), std::ios::beg );
+ ComputeJPEGFragmentInfo();
+ Fp->seekg( positionOnEntry, std::ios::beg );
+ }
+ }
+
+ // Just to make sure we are at the beginning of next entry.
+ SkipToNextDocEntry(newDocEntry);
+ }
+ else
+ {
+ // 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 = true;
+ }
+ else
+ {
+ delim_mode = false;
+ }
+ }
+ // no other way to create it ...
+ newSeqEntry->SetDelimitorMode( delim_mode );
+
+ // 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 (/*Document *dummy =*/ dynamic_cast< Document* > ( set ) )
+ {
+ //(void)dummy;
+ newSeqEntry->SetDepthLevel( 1 );
+ newSeqEntry->SetKey( newSeqEntry->GetKey() );
+ }
+ // 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:
+ if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+ {
+ newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
+ newSeqEntry->SetKey( parentSQItem->GetBaseTagKey()
+ + newSeqEntry->GetKey() );
+ }
+
+ if ( l != 0 )
+ { // Don't try to parse zero-length sequences
+ ParseSQ( newSeqEntry,
+ newDocEntry->GetOffset(),
+ l, delim_mode);
+ }
+ set->AddEntry( newSeqEntry );
+ if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+ {
+ break;
+ }
+ }
+
+ if(!used)
+ delete newDocEntry;
+ }
+}
+
+/**
+ * \brief Parses a Sequence ( SeqEntry after SeqEntry)
+ * @return parsed length for this level
+ */
+void Document::ParseSQ( SeqEntry *seqEntry,
+ long offset, long l_max, bool delim_mode)
+{
+ int SQItemNumber = 0;
+ bool dlm_mod;
+ long offsetStartCurrentSQItem = offset;
+
+ while (true)
+ {
+ // the first time, we read the fff0,e000 of the first SQItem
+ DocEntry *newDocEntry = ReadNextDocEntry();
+
+ if ( !newDocEntry )
+ {
+ // FIXME Should warn user
+ break;
+ }
+ if( delim_mode )
+ {
+ if ( newDocEntry->IsSequenceDelimitor() )
+ {
+ seqEntry->SetDelimitationItem( newDocEntry );
+ break;
+ }
+ }
+ if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+ {
+ delete newDocEntry;
+ break;
+ }
+ // create the current SQItem
+ SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
+ std::ostringstream newBase;
+ newBase << seqEntry->GetKey()
+ << "/"
+ << SQItemNumber
+ << "#";
+ itemSQ->SetBaseTagKey( newBase.str() );
+ unsigned int l = newDocEntry->GetReadLength();
+
+ if ( l == 0xffffffff )
+ {
+ dlm_mod = true;
+ }
+ else
+ {
+ 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
+ delete newDocEntry;
+ Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
+ // fill up the current SQItem, starting at the beginning of fff0,e000
+ ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
+ offsetStartCurrentSQItem = Fp->tellg();
+ // end try -----------------
+
+ seqEntry->AddSQItem( itemSQ, SQItemNumber );
+ SQItemNumber++;
+ if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
+ {
+ break;
+ }
+ }
+}
+