GDCM  2.2.0
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 
00144   GDCM_LEGACY(const SequenceOfItems* GetSequenceOfItems() const)
00145   GDCM_LEGACY(SequenceOfItems* GetSequenceOfItems())
00146 
00153   SmartPointer<SequenceOfItems> GetValueAsSQ() const;
00154 
00157   const SequenceOfFragments* GetSequenceOfFragments() const;
00158 
00160   bool IsUndefinedLength() const {
00161     return ValueLengthField.IsUndefined();
00162   }
00163 
00164   DataElement(const DataElement &_val)
00165     {
00166     if( this != &_val)
00167       {
00168       *this = _val;
00169       }
00170     }
00171 
00172   bool operator<(const DataElement &de) const
00173     {
00174     return GetTag() < de.GetTag();
00175     }
00176   DataElement &operator=(const DataElement &de)
00177     {
00178     TagField = de.TagField;
00179     ValueLengthField = de.ValueLengthField;
00180     VRField = de.VRField;
00181     ValueField = de.ValueField; // Pointer copy
00182     return *this;
00183     }
00184 
00185   bool operator==(const DataElement &de) const
00186     {
00187     bool b = TagField == de.TagField
00188       && ValueLengthField == de.ValueLengthField
00189       && VRField == de.VRField;
00190     if( !ValueField && !de.ValueField )
00191       {
00192       return b;
00193       }
00194     if( ValueField && de.ValueField )
00195       {
00196       return b && (*ValueField == *de.ValueField);
00197       }
00198     // ValueField != de.ValueField
00199     return false;
00200     }
00201 
00202   // The following fonctionalities are dependant on:
00203   // # The Transfer Syntax: Explicit or Implicit
00204   // # The Byte encoding: Little Endian / Big Endian
00205 
00206   /*
00207    * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern
00208    * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
00209    * The typename TDE is typically a derived class *without* any data
00210    * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of
00211    * highly identical code)
00212    */
00213   template <typename TDE>
00214   VL GetLength() const {
00215     return static_cast<const TDE*>(this)->GetLength();
00216   }
00217 
00218   template <typename TDE, typename TSwap>
00219   std::istream &Read(std::istream &is) {
00220     return static_cast<TDE*>(this)->template Read<TSwap>(is);
00221   }
00222 
00223   template <typename TDE, typename TSwap>
00224   std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) {
00225     (void)skiptags;
00226     return static_cast<TDE*>(this)->template Read<TSwap>(is);
00227   }
00228 
00229   template <typename TDE, typename TSwap>
00230   std::istream &ReadPreValue(std::istream &is, std::set<Tag> const &skiptags) {
00231     (void)skiptags;
00232     return static_cast<TDE*>(this)->template ReadPreValue<TSwap>(is);
00233   }
00234   template <typename TDE, typename TSwap>
00235   std::istream &ReadValue(std::istream &is, std::set<Tag> const &skiptags) {
00236     (void)skiptags;
00237     return static_cast<TDE*>(this)->template ReadValue<TSwap>(is);
00238   }
00239 
00240   template <typename TDE, typename TSwap>
00241   std::istream &ReadWithLength(std::istream &is, VL &length) {
00242     return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length);
00243   }
00244 
00245   template <typename TDE, typename TSwap>
00246   const std::ostream &Write(std::ostream &os) const {
00247     return static_cast<const TDE*>(this)->template Write<TSwap>(os);
00248   }
00249 
00250 protected:
00251   Tag TagField;
00252   // This is the value read from the file, might be different from the length of Value Field
00253   VL ValueLengthField; // Can be 0xFFFFFFFF
00254 
00255   // Value Representation
00256   VR VRField;
00257   typedef SmartPointer<Value> ValuePtr;
00258   ValuePtr ValueField;
00259 };
00260 //-----------------------------------------------------------------------------
00261 inline std::ostream& operator<<(std::ostream &os, const DataElement &val)
00262 {
00263   os << val.TagField;
00264   os << "\t" << val.VRField;
00265   os << "\t" << val.ValueLengthField;
00266   if( val.ValueField )
00267     {
00268     val.ValueField->Print( os << "\t" );
00269     }
00270   return os;
00271 }
00272 
00273 inline bool operator!=(const DataElement& lhs, const DataElement& rhs)
00274 {
00275   return ! ( lhs == rhs );
00276 }
00277 
00278 } // end namespace gdcm
00279 
00280 #endif //GDCMDATAELEMENT_H

Generated on Sun Jun 3 2012 15:26:46 for GDCM by doxygen 1.8.0
SourceForge.net Logo