# 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-2009 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 //class Value;
    00037
    00038 class SequenceOfItems;
    00039 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     return TagField == de.TagField
    00194       && ValueLengthField == de.ValueLengthField
    00195       && VRField == de.VRField
    00196       && ValueField == de.ValueField;
    00197     }
    00198
    00199   // The following fonctionalities are dependant on:
    00200   // # The Transfer Syntax: Explicit or Implicit
    00201   // # The Byte encoding: Little Endian / Big Endian
    00202
    00203   /*
    00204    * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern
    00205    * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
    00206    * The typename TDE is typically a derived class *without* any data
    00207    * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of
    00208    * highly identical code)
    00209    */
    00210   template <typename TDE>
    00211   VL GetLength() const {
    00212     return static_cast<const TDE*>(this)->GetLength();
    00213   }
    00214
    00215   template <typename TDE, typename TSwap>
    00216   std::istream &Read(std::istream &is) {
    00217     return static_cast<TDE*>(this)->template Read<TSwap>(is);
    00218   }
    00219
    00220   template <typename TDE, typename TSwap>
    00221   std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) {
    00222     (void)skiptags;
    00223     return static_cast<TDE*>(this)->template Read<TSwap>(is);
    00224   }
    00225
    00226   template <typename TDE, typename TSwap>
    00227   std::istream &ReadWithLength(std::istream &is, VL &length) {
    00228     return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length);
    00229   }
    00230
    00231   template <typename TDE, typename TSwap>
    00232   const std::ostream &Write(std::ostream &os) const {
    00233     return static_cast<const TDE*>(this)->template Write<TSwap>(os);
    00234   }
    00235
    00236 protected:
    00237   Tag TagField;
    00238   // This is the value read from the file, might be different from the length of Value Field
    00239   VL ValueLengthField; // Can be 0xFFFFFFFF
    00240
    00241   // Value Representation
    00242   VR VRField;
    00243   typedef SmartPointer<Value> ValuePtr;
    00244   ValuePtr ValueField;
    00245 };
    00246 //-----------------------------------------------------------------------------
    00247 inline std::ostream& operator<<(std::ostream &os, const DataElement &val)
    00248 {
    00249   os << val.TagField;
    00250   os << "\t" << val.VRField;
    00251   os << "\t" << val.ValueLengthField;
    00252   if( val.ValueField )
    00253     {
    00254     val.ValueField->Print( os << "\t" );
    00255     }
    00256   return os;
    00257 }
    00258
    00259 } // end namespace gdcm
    00260
    00261 #endif //__gdcmDataElement_h
    00262