
| Current Path : /usr/include/gdcm-3.0/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //usr/include/gdcm-3.0/gdcmSequenceOfItems.h |
/*=========================================================================
Program: GDCM (Grassroots DICOM). A DICOM library
Copyright (c) 2006-2011 Mathieu Malaterre
All rights reserved.
See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef GDCMSEQUENCEOFITEMS_H
#define GDCMSEQUENCEOFITEMS_H
#include "gdcmValue.h"
#include "gdcmItem.h"
#include <vector>
#include <cstring> // strcmp
namespace gdcm_ns
{
/**
* \brief Class to represent a Sequence Of Items
* \details (value representation : SQ)
* - a Value Representation for Data Elements that contains a sequence of Data Sets.
* - Sequence of Item allows for Nested Data Sets
*
* See PS 3.5, 7.4.6 Data Element Type Within a Sequence
* \note
* SEQUENCE OF ITEMS (VALUE REPRESENTATION SQ)
* A Value Representation for Data Elements that contain a sequence of
* Data Sets. Sequence of Items allows for Nested Data Sets.
*/
class GDCM_EXPORT SequenceOfItems : public Value
{
public:
// Typdefs:
typedef std::vector< Item > ItemVector;
typedef ItemVector::size_type SizeType;
typedef ItemVector::iterator Iterator;
typedef ItemVector::const_iterator ConstIterator;
Iterator Begin() { return Items.begin(); }
Iterator End() { return Items.end(); }
ConstIterator Begin() const { return Items.begin(); }
ConstIterator End() const { return Items.end(); }
/// \brief constructor (UndefinedLength by default)
SequenceOfItems():SequenceLengthField(0xFFFFFFFF) { }
//SequenceOfItems(VL const &vl = 0xFFFFFFFF):SequenceLengthField(vl),NType(type) { }
/// \brief Returns the SQ length, as read from disk
VL GetLength() const override { return SequenceLengthField; }
/// \brief Sets the actual SQ length
void SetLength(VL length) override {
SequenceLengthField = length;
}
/// \brief Properly set the Sequence of Item to be undefined length
void SetLengthToUndefined();
/// return if Value Length if of undefined length
bool IsUndefinedLength() const {
return SequenceLengthField.IsUndefined();
}
template <typename TDE>
VL ComputeLength() const;
/// remove all items within the sequence
void Clear() override;
/// \brief Appends an Item to the already added ones
void AddItem(Item const &item);
/// \brief Appends an Item to the already added ones
Item & AddNewUndefinedLengthItem();
/// Remove an Item as specified by its index, if index > size, false is returned
/// Index starts at 1 not 0
bool RemoveItemByIndex( const SizeType index );
bool IsEmpty() const { return Items.empty(); };
SizeType GetNumberOfItems() const { return Items.size(); }
void SetNumberOfItems(SizeType n) { Items.resize(n); }
/* WARNING: first item is #1 (see DICOM standard)
* Each Item shall be implicitly assigned an ordinal position starting with the value 1 for the
* first Item in the Sequence, and incremented by 1 with each subsequent Item. The last Item in the
* Sequence shall have an ordinal position equal to the number of Items in the Sequence.
*/
const Item &GetItem(SizeType position) const;
Item &GetItem(SizeType position);
SequenceOfItems &operator=(const SequenceOfItems &val) {
SequenceLengthField = val.SequenceLengthField;
Items = val.Items;
return *this;
}
template <typename TDE, typename TSwap>
std::istream &Read(std::istream &is, bool readvalues = true)
{
(void)readvalues;
const Tag seqDelItem(0xfffe,0xe0dd);
if( SequenceLengthField.IsUndefined() )
{
Item item;
while( item.Read<TDE,TSwap>(is) && item.GetTag() != seqDelItem )
{
//gdcmDebugMacro( "Item: " << item );
assert( item.GetTag() != seqDelItem );
Items.push_back( item );
item.Clear();
}
//assert( item.GetTag() == seqDelItem && item.GetVL() == 0 );
}
else
{
Item item;
VL l = 0;
//is.seekg( SequenceLengthField, std::ios::cur ); return is;
while( l != SequenceLengthField )
{
try
{
item.Read<TDE,TSwap>(is);
}
catch( Exception &ex )
{
if( strcmp( ex.GetDescription(), "Changed Length" ) == 0 )
{
VL newlength = l + item.template GetLength<TDE>();
if( newlength > SequenceLengthField )
{
// BogugsItemAndSequenceLength.dcm
gdcmWarningMacro( "SQ length is wrong" );
SequenceLengthField = newlength;
}
}
else
{
throw ex;
}
}
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
if( item.GetTag() == seqDelItem )
{
gdcmWarningMacro( "SegDelItem found in defined length Sequence. Skipping" );
assert( item.GetVL() == 0 );
assert( item.GetNestedDataSet().Size() == 0 );
// we need to pay attention that the length of the Sequence of Items will be wrong
// this way. Indeed by not adding this item we are changing the size of this sqi
}
else // Not a seq del item marker
#endif
{
// By design we never load them. If we were to load those attribute
// as normal item it would become very complex to convert a sequence
// from defined length to undefined length with the risk to write two
// seq del marker
Items.push_back( item );
}
l += item.template GetLength<TDE>();
if( l > SequenceLengthField )
{
gdcmDebugMacro( "Found: Length of Item larger than expected" )
throw "Length of Item larger than expected";
}
assert( l <= SequenceLengthField );
//std::cerr << "sqi debug len: " << is.tellg() << " " << l << " " << SequenceLengthField << std::endl;
#ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
// MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm
// (0x2005, 0x1080): for some reason computation of length fails...
if( SequenceLengthField == 778 && l == 774 )
{
gdcmWarningMacro( "PMS: Super bad hack" );
SequenceLengthField = l;
throw Exception( "Wrong Length" );
//l = SequenceLengthField;
}
// Bug_Philips_ItemTag_3F3F
// (0x2005, 0x1080): Because we do not handle fully the bug at the item
// level we need to check here too
else if ( SequenceLengthField == 444 && l == 3*71 )
{
// This one is a double bug. Item length is wrong and impact SQ length
gdcmWarningMacro( "PMS: Super bad hack" );
l = SequenceLengthField;
}
#endif
}
assert( l == SequenceLengthField );
}
return is;
}
template <typename TDE,typename TSwap>
std::ostream const &Write(std::ostream &os) const
{
typename ItemVector::const_iterator it = Items.begin();
for(;it != Items.end(); ++it)
{
it->Write<TDE,TSwap>(os);
}
if( SequenceLengthField.IsUndefined() )
{
// seq del item is not stored, write it !
const Tag seqDelItem(0xfffe,0xe0dd);
seqDelItem.Write<TSwap>(os);
VL zero = 0;
zero.Write<TSwap>(os);
}
return os;
}
//protected:
void Print(std::ostream &os) const override {
os << "\t(" << SequenceLengthField << ")\n";
ItemVector::const_iterator it =
Items.begin();
for(;it != Items.end(); ++it)
{
os << " " << *it;
}
if( SequenceLengthField.IsUndefined() )
{
const Tag seqDelItem(0xfffe,0xe0dd);
VL zero = 0;
os << seqDelItem;
os << "\t" << zero;
}
}
static SmartPointer<SequenceOfItems> New()
{
return new SequenceOfItems;
}
bool FindDataElement(const Tag &t) const;
bool operator==(const Value &val) const override
{
const SequenceOfItems &sqi = dynamic_cast<const SequenceOfItems&>(val);
return SequenceLengthField == sqi.SequenceLengthField &&
Items == sqi.Items;
}
private:
public:
/// \brief Total length of the Sequence (or 0xffffffff) if undefined
VL SequenceLengthField;
/// \brief Vector of Sequence Items
ItemVector Items;
};
} // end namespace gdcm_ns
#include "gdcmSequenceOfItems.txx"
#endif //GDCMSEQUENCEOFITEMS_H