# gdcmDataElement.h

Go to the documentation of this file.

    00001 /*=========================================================================
    00002
    00003   Program: GDCM (Grassroots DICOM). A DICOM library
    00004   Module:  $URL$
    00005
    00006   Copyright (c) 2006-2010 Mathieu Malaterre
    00007   All rights reserved.
    00008   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
    00009
    00010      This software is distributed WITHOUT ANY WARRANTY; without even
    00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    00012      PURPOSE.  See the above copyright notice for more information.
    00013
    00014 =========================================================================*/
    00015 #ifndef GDCMDATAELEMENT_H
    00016 #define GDCMDATAELEMENT_H
    00017
    00018 #include "gdcmTag.h"
    00019 #include "gdcmVL.h"
    00020 #include "gdcmVR.h"
    00021 #include "gdcmByteValue.h"
    00022 #include "gdcmSmartPointer.h"
    00023
    00024 #include <set>
    00025
    00026 namespace gdcm
    00027 {
    00028 // Data Element
    00029 // Contains multiple fields:
    00030 // -> Tag
    00031 // -> Optional VR (Explicit Transfer Syntax)
    00032 // -> ValueLength
    00033 // -> Value
    00034 // TODO: This class SHOULD be pure virtual. I dont want a user
    00035 // to shoot himself in the foot.
    00036
    00037 class SequenceOfItems;
    00038 class SequenceOfFragments;
    00059 class GDCM_EXPORT DataElement
    00060 {
    00061 public:
    00062   DataElement(const Tag& t = Tag(0), const VL& vl = 0, const VR &vr = VR::INVALID):TagField(t),ValueLengthField(vl),VRField(vr),ValueField(0) {}
    00063   //DataElement( Attribute const &att );
    00064
    00065   friend std::ostream& operator<<(std::ostream &_os, const DataElement &_val);
    00066
    00068   const Tag& GetTag() const { return TagField; }
    00069   Tag& GetTag() { return TagField; }
    00072   void SetTag(const Tag &t) { TagField = t; }
    00073
    00075   const VL& GetVL() const { return ValueLengthField; }
    00076   VL& GetVL() { return ValueLengthField; }
    00080   void SetVL(const VL &vl) { ValueLengthField = vl; }
    00081   void SetVLToUndefined();
    00082
    00085   VR const &GetVR() const { return VRField; }
    00089   void SetVR(VR const &vr) {
    00090     // assert( vr.IsVRFile() );
    00091     VRField = vr;
    00092   }
    00093
    00095   Value const &GetValue() const { return *ValueField; }
    00096   Value &GetValue() { return *ValueField; }
    00098   void SetValue(Value const & vl) {
    00099     //assert( ValueField == 0 );
    00100     ValueField = vl;
    00101     ValueLengthField = vl.GetLength();
    00102   }
    00104   bool IsEmpty() const { return ValueField == 0 || (GetByteValue() && GetByteValue()->IsEmpty()); }
    00105
    00107   void Empty() { ValueField = 0; ValueLengthField = 0; }
    00108
    00110   void Clear()
    00111     {
    00112     TagField = 0;
    00113     VRField = VR::INVALID;
    00114     ValueField = 0;
    00115     ValueLengthField = 0;
    00116     }
    00117
    00118   // Helper:
    00124   void SetByteValue(const char *array, VL length)
    00125     {
    00126     ByteValue *bv = new ByteValue(array,length);
    00127     SetValue( *bv );
    00128     }
    00131   const ByteValue* GetByteValue() const {
    00132     // Get the raw pointer from the gdcm::SmartPointer
    00133     const ByteValue *bv = dynamic_cast<const ByteValue*>(ValueField.GetPointer());
    00134     return bv; // Will return NULL if not ByteValue
    00135   }
    00136   ByteValue* GetByteValue() {
    00137     // Get the raw pointer from the gdcm::SmartPointer
    00138     ByteValue *bv = dynamic_cast<ByteValue*>(ValueField.GetPointer());
    00139     return bv; // Will return NULL if not ByteValue
    00140   }
    00141
    00150   GDCM_LEGACY(const SequenceOfItems* GetSequenceOfItems() const)
    00151   GDCM_LEGACY(SequenceOfItems* GetSequenceOfItems())
    00152
    00159   SmartPointer<SequenceOfItems> GetValueAsSQ() const;
    00160
    00163   const SequenceOfFragments* GetSequenceOfFragments() const;
    00164
    00166   bool IsUndefinedLength() const {
    00167     return ValueLengthField.IsUndefined();
    00168   }
    00169
    00170   DataElement(const DataElement &_val)
    00171     {
    00172     if( this != &_val)
    00173       {
    00174       *this = _val;
    00175       }
    00176     }
    00177
    00178   bool operator<(const DataElement &de) const
    00179     {
    00180     return GetTag() < de.GetTag();
    00181     }
    00182   DataElement &operator=(const DataElement &de)
    00183     {
    00184     TagField = de.TagField;
    00185     ValueLengthField = de.ValueLengthField;
    00186     VRField = de.VRField;
    00187     ValueField = de.ValueField; // Pointer copy
    00188     return *this;
    00189     }
    00190
    00191   bool operator==(const DataElement &de) const
    00192     {
    00193     bool b = TagField == de.TagField
    00194       && ValueLengthField == de.ValueLengthField
    00195       && VRField == de.VRField;
    00196     if( !ValueField && !de.ValueField )
    00197       {
    00198       return b;
    00199       }
    00200     if( ValueField && de.ValueField )
    00201       {
    00202       return b && (*ValueField == *de.ValueField);
    00203       }
    00204     // ValueField != de.ValueField
    00205     return false;
    00206     }
    00207
    00208   // The following fonctionalities are dependant on:
    00209   // # The Transfer Syntax: Explicit or Implicit
    00210   // # The Byte encoding: Little Endian / Big Endian
    00211
    00212   /*
    00213    * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern
    00214    * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
    00215    * The typename TDE is typically a derived class *without* any data
    00216    * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of
    00217    * highly identical code)
    00218    */
    00219   template <typename TDE>
    00220   VL GetLength() const {
    00221     return static_cast<const TDE*>(this)->GetLength();
    00222   }
    00223
    00224   template <typename TDE, typename TSwap>
    00225   std::istream &Read(std::istream &is) {
    00226     return static_cast<TDE*>(this)->template Read<TSwap>(is);
    00227   }
    00228
    00229   template <typename TDE, typename TSwap>
    00230   std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) {
    00231     (void)skiptags;
    00232     return static_cast<TDE*>(this)->template Read<TSwap>(is);
    00233   }
    00234
    00235   template <typename TDE, typename TSwap>
    00236   std::istream &ReadPreValue(std::istream &is, std::set<Tag> const &skiptags) {
    00237     (void)skiptags;
    00238     return static_cast<TDE*>(this)->template ReadPreValue<TSwap>(is);
    00239   }
    00240   template <typename TDE, typename TSwap>
    00241   std::istream &ReadValue(std::istream &is, std::set<Tag> const &skiptags) {
    00242     (void)skiptags;
    00243     return static_cast<TDE*>(this)->template ReadValue<TSwap>(is);
    00244   }
    00245
    00246   template <typename TDE, typename TSwap>
    00247   std::istream &ReadWithLength(std::istream &is, VL &length) {
    00248     return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length);
    00249   }
    00250
    00251   template <typename TDE, typename TSwap>
    00252   const std::ostream &Write(std::ostream &os) const {
    00253     return static_cast<const TDE*>(this)->template Write<TSwap>(os);
    00254   }
    00255
    00256 protected:
    00257   Tag TagField;
    00258   // This is the value read from the file, might be different from the length of Value Field
    00259   VL ValueLengthField; // Can be 0xFFFFFFFF
    00260
    00261   // Value Representation
    00262   VR VRField;
    00263   typedef SmartPointer<Value> ValuePtr;
    00264   ValuePtr ValueField;
    00265 };
    00266 //-----------------------------------------------------------------------------
    00267 inline std::ostream& operator<<(std::ostream &os, const DataElement &val)
    00268 {
    00269   os << val.TagField;
    00270   os << "\t" << val.VRField;
    00271   os << "\t" << val.ValueLengthField;
    00272   if( val.ValueField )
    00273     {
    00274     val.ValueField->Print( os << "\t" );
    00275     }
    00276   return os;
    00277 }
    00278
    00279 } // end namespace gdcm
    00280
    00281 #endif //GDCMDATAELEMENT_H