+/**
+ * \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;
+
+ while (true)
+ {
+ if ( !delim_mode && (Fp->tellg()-offset) >= l_max)
+ {
+ break;
+ }
+ newDocEntry = ReadNextDocEntry( );
+ if ( !newDocEntry )
+ {
+ break;
+ }
+
+ VRKey vr = newDocEntry->GetVR();
+ if ( vr != "SQ" )
+ {
+
+ if ( Global::GetVR()->IsVROfGdcmStringRepresentable(vr) )
+ {
+ /////////////////////// ValEntry
+ ValEntry* newValEntry =
+ new ValEntry( newDocEntry->GetDictEntry() );
+ newValEntry->Copy( newDocEntry );
+
+ // 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 (Document* dummy = dynamic_cast< Document* > ( set ) )
+ {
+ (void)dummy;
+ 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() );
+ }
+
+ set->AddEntry( newValEntry );
+ LoadDocEntry( newValEntry );
+ if (newValEntry->IsItemDelimitor())
+ {
+ break;
+ }
+ if ( !delim_mode && (Fp->tellg()-offset) >= l_max)
+ {
+ break;
+ }
+ }
+ else
+ {
+ if ( ! Global::GetVR()->IsVROfGdcmBinaryRepresentable(vr) )
+ {
+ ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
+ dbg.Verbose(0, "Document::ParseDES: neither Valentry, "
+ "nor BinEntry. Probably unknown VR.");
+ }
+
+ //////////////////// BinEntry or UNKOWN VR:
+ BinEntry* newBinEntry =
+ new BinEntry( newDocEntry->GetDictEntry() );
+ newBinEntry->Copy( newDocEntry );
+
+ // When "this" is a Document the Key is simply of the
+ // form ( group, elem )...
+ if (Document* dummy = dynamic_cast< Document* > ( set ) )
+ {
+ (void)dummy;
+ newBinEntry->SetKey( newBinEntry->GetKey() );
+ }
+ // but when "this" is a SQItem, we are inserting this new
+ // valEntry in a sequence item, and the kay has the
+ // generalized form (refer to \ref BaseTagKey):
+ if (SQItem* parentSQItem = dynamic_cast< SQItem* > ( set ) )
+ {
+ newBinEntry->SetKey( parentSQItem->GetBaseTagKey()
+ + newBinEntry->GetKey() );
+ }
+
+ set->AddEntry( newBinEntry );
+ LoadDocEntry( newBinEntry );
+ }
+
+ if ( ( newDocEntry->GetGroup() == 0x7fe0 )
+ && ( newDocEntry->GetElement() == 0x0010 ) )
+ {
+ TransferSyntaxType ts = GetTransferSyntax();
+ if ( ts == RLELossless )
+ {
+ long PositionOnEntry = Fp->tellg();
+ Fp->seekg( newDocEntry->GetOffset(), std::ios_base::beg );
+ ComputeRLEInfo();
+ Fp->seekg( PositionOnEntry, std::ios_base::beg );
+ }
+ else if ( IsJPEG() )
+ {
+ long PositionOnEntry = Fp->tellg();
+ Fp->seekg( newDocEntry->GetOffset(), std::ios_base::beg );
+ ComputeJPEGFragmentInfo();
+ Fp->seekg( PositionOnEntry, std::ios_base::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 ...
+ SeqEntry* newSeqEntry =
+ new SeqEntry( newDocEntry->GetDictEntry() );
+ newSeqEntry->Copy( newDocEntry );
+ 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 allready 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 && (Fp->tellg()-offset) >= l_max)
+ {
+ break;
+ }
+ }
+ 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;
+
+ while (true)
+ {
+ DocEntry* newDocEntry = ReadNextDocEntry();
+ if ( !newDocEntry )
+ {
+ // FIXME Should warn user
+ break;
+ }
+ if( delim_mode )
+ {
+ if ( newDocEntry->IsSequenceDelimitor() )
+ {
+ seqEntry->SetSequenceDelimitationItem( newDocEntry );
+ break;
+ }
+ }
+ if ( !delim_mode && (Fp->tellg()-offset) >= l_max)
+ {
+ break;
+ }
+
+ 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;
+ }
+
+ ParseDES(itemSQ, newDocEntry->GetOffset(), l, dlm_mod);
+
+ seqEntry->AddEntry( itemSQ, SQItemNumber );
+ SQItemNumber++;
+ if ( !delim_mode && ( Fp->tellg() - offset ) >= l_max )
+ {
+ break;
+ }
+ }
+}
+