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

Generated on Tue Dec 6 2011 07:25:31 for GDCM by doxygen 1.7.5.1
SourceForge.net Logo