# gdcmElement.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 GDCMELEMENT_H
    00016 #define GDCMELEMENT_H
    00017
    00018 #include "gdcmTypes.h"
    00019 #include "gdcmVR.h"
    00020 #include "gdcmTag.h"
    00021 #include "gdcmVM.h"
    00022 #include "gdcmByteValue.h"
    00023 #include "gdcmDataElement.h"
    00024 #include "gdcmSwapper.h"
    00025
    00026 #include <string>
    00027 #include <vector>
    00028 #include <sstream>
    00029 #include <limits>
    00030 #include <cmath>
    00031
    00032 namespace gdcm
    00033 {
    00034
    00035 // Forward declaration
    00041 template<int T> class EncodingImplementation;
    00042
    00048 template<int TVR, int TVM>
    00049 class Element
    00050 {
    00051 public:
    00052   typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length];
    00053   typedef typename VRToType<TVR>::Type Type;
    00054
    00055   unsigned long GetLength() const {
    00056     return VMToLength<TVM>::Length;
    00057   }
    00058   // Implementation of Print is common to all Mode (ASCII/Binary)
    00059   // TODO: Can we print a \ when in ASCII...well I don't think so
    00060   // it would mean we used a bad VM then, right ?
    00061   void Print(std::ostream &_os) const {
    00062     _os << Internal[0]; // VM is at least garantee to be one
    00063     for(int i=1; i<VMToLength<TVM>::Length; ++i)
    00064       _os << "," << Internal[i];
    00065     }
    00066
    00067   const typename VRToType<TVR>::Type *GetValues() const {
    00068     return Internal;
    00069   }
    00070   const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
    00071     assert( idx < VMToLength<TVM>::Length );
    00072     return Internal[idx];
    00073   }
    00074   typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
    00075     assert( idx < VMToLength<TVM>::Length );
    00076     return Internal[idx];
    00077   }
    00078   typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
    00079     return GetValue(idx);
    00080   }
    00081   void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
    00082     assert( idx < VMToLength<TVM>::Length );
    00083     Internal[idx] = v;
    00084   }
    00085
    00086   void SetFromDataElement(DataElement const &de) {
    00087     const ByteValue *bv = de.GetByteValue();
    00088     if( !bv ) return;
    00089 #ifdef GDCM_WORDS_BIGENDIAN
    00090     if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
    00091 #else
    00092     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
    00093 #endif
    00094       {
    00095       Set(de.GetValue());
    00096       }
    00097     else
    00098       {
    00099       SetNoSwap(de.GetValue());
    00100       }
    00101   }
    00102
    00103   void Read(std::istream &_is) {
    00104     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00105       GetLength(),_is);
    00106     }
    00107   void Write(std::ostream &_os) const {
    00108     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00109       GetLength(),_os);
    00110     }
    00111
    00112   // FIXME: remove this function
    00113   // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
    00114   void Set(Value const &v) {
    00115     const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
    00116     if( bv ) {
    00117       //memcpy(Internal, bv->GetPointer(), bv->GetLength());
    00118       std::stringstream ss;
    00119       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00120       ss.str( s );
    00121       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00122         GetLength(),ss);
    00123     }
    00124   }
    00125 protected:
    00126   void SetNoSwap(Value const &v) {
    00127     const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
    00128     assert( bv ); // That would be bad...
    00129     //memcpy(Internal, bv->GetPointer(), bv->GetLength());
    00130     std::stringstream ss;
    00131     std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00132     ss.str( s );
    00133     EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
    00134       GetLength(),ss);
    00135   }
    00136 };
    00137
    00138 struct ignore_char {
    00139   ignore_char(char c): m_char(c) {}
    00140   char m_char;
    00141 };
    00142 ignore_char const backslash('\\');
    00143
    00144   inline std::istream& operator>> (std::istream& in, ignore_char const& ic) {
    00145     if (!in.eof())
    00146       in.clear(in.rdstate() & ~std::ios_base::failbit);
    00147     if (in.get() != ic.m_char)
    00148       in.setstate(std::ios_base::failbit);
    00149     return in;
    00150   }
    00151
    00152
    00153 // Implementation to perform formatted read and write
    00154 template<> class EncodingImplementation<VR::VRASCII> {
    00155 public:
    00156   template<typename T> // FIXME this should be VRToType<TVR>::Type
    00157   static inline void ReadComputeLength(T* data, unsigned int &length,
    00158                           std::istream &_is) {
    00159     assert( data );
    00160     //assert( length ); // != 0
    00161     length = 0;
    00162     assert( _is );
    00163 #if 0
    00164     char sep;
    00165     while( _is >> data[length++] )
    00166       {
    00167       // Get the separator in between the values
    00168       assert( _is );
    00169       _is.get(sep);
    00170       assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert
    00171       if( sep == ' ' ) length--; // FIXME
    00172       }
    00173 #else
    00174   while( _is >> std::ws >> data[length++] >> std::ws >> backslash )
    00175     {
    00176     }
    00177 #endif
    00178     }
    00179
    00180   template<typename T> // FIXME this should be VRToType<TVR>::Type
    00181   static inline void Read(T* data, unsigned long length,
    00182                           std::istream &_is) {
    00183     assert( data );
    00184     assert( length ); // != 0
    00185     assert( _is );
    00186     // FIXME BUG: what if >> operation fails ?
    00187     // gdcmData/MR00010001.dcm / SpacingBetweenSlices
    00188     _is >> std::ws >> data[0];
    00189     char sep;
    00190     //std::cout << "GetLength: " << af->GetLength() << std::endl;
    00191     for(unsigned long i=1; i<length;++i) {
    00192       assert( _is );
    00193       // Get the separator in between the values
    00194       _is >> std::ws >> sep; //_is.get(sep);
    00195       assert( sep == '\\' ); // FIXME: Bad use of assert
    00196       _is >> std::ws >> data[i];
    00197       }
    00198     }
    00199
    00200   template<typename T>
    00201   static inline void ReadNoSwap(T* data, unsigned long length,
    00202                           std::istream &_is) {
    00203     Read(data,length,_is);
    00204 }
    00205   template<typename T>
    00206   static inline void Write(const T* data, unsigned long length,
    00207                            std::ostream &_os)  {
    00208     assert( data );
    00209     assert( length );
    00210     assert( _os );
    00211     _os << data[0];
    00212     for(unsigned long i=1; i<length; ++i) {
    00213       assert( _os );
    00214       _os << "\\" << data[i];
    00215       }
    00216     }
    00217 };
    00218
    00219 template < typename Float >
    00220 std::string to_string ( Float data ) {
    00221   std::stringstream in;
    00222   // in.imbue(std::locale::classic()); // This is not required AFAIK
    00223   unsigned long const digits =
    00224     static_cast< unsigned long >(
    00225     - std::log( std::numeric_limits<Float>::epsilon() )
    00226     / std::log( 10.0 ) );
    00227   if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) {
    00228     return ( in.str() );
    00229   } else {
    00230     throw "Impossible Conversion"; // should not happen ...
    00231   }
    00232 }
    00233
    00234 /* Writing VR::DS is not that easy after all */
    00235 // http://groups.google.com/group/comp.lang.c++/browse_thread/thread/69ccd26f000a0802
    00236 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const float * data, unsigned long length, std::ostream &_os)  {
    00237     assert( data );
    00238     assert( length );
    00239     assert( _os );
    00240     _os << to_string(data[0]);
    00241     for(unsigned long i=1; i<length; ++i) {
    00242       assert( _os );
    00243       _os << "\\" << to_string(data[i]);
    00244       }
    00245     }
    00246
    00247 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os)  {
    00248     assert( data );
    00249     assert( length );
    00250     assert( _os );
    00251     _os << to_string(data[0]);
    00252     for(unsigned long i=1; i<length; ++i) {
    00253       assert( _os );
    00254       _os << "\\" << to_string(data[i]);
    00255       }
    00256     }
    00257
    00258
    00259 // Implementation to perform binary read and write
    00260 // TODO rewrite operation so that either:
    00261 // #1. dummy implementation use a pointer to Internal and do ++p (faster)
    00262 // #2. Actually do some meta programming to unroll the loop
    00263 // (no notion of order in VM ...)
    00264 template<> class EncodingImplementation<VR::VRBINARY> {
    00265 public:
    00266   template<typename T> // FIXME this should be VRToType<TVR>::Type
    00267     static inline void ReadComputeLength(T* data, unsigned int &length,
    00268       std::istream &_is) {
    00269     const unsigned int type_size = sizeof(T);
    00270     assert( data ); // Can we read from pointer ?
    00271     //assert( length );
    00272     length /= type_size;
    00273     assert( _is ); // Is stream valid ?
    00274     _is.read( reinterpret_cast<char*>(data+0), type_size);
    00275     for(unsigned long i=1; i<length; ++i) {
    00276       assert( _is );
    00277       _is.read( reinterpret_cast<char*>(data+i), type_size );
    00278     }
    00279     }
    00280   template<typename T>
    00281   static inline void ReadNoSwap(T* data, unsigned long length,
    00282     std::istream &_is) {
    00283     const unsigned int type_size = sizeof(T);
    00284     assert( data ); // Can we read from pointer ?
    00285     assert( length );
    00286     assert( _is ); // Is stream valid ?
    00287     _is.read( reinterpret_cast<char*>(data+0), type_size);
    00288     for(unsigned long i=1; i<length; ++i) {
    00289       assert( _is );
    00290       _is.read( reinterpret_cast<char*>(data+i), type_size );
    00291     }
    00292     //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
    00293     //  _is.GetSwapCode(), length);
    00294     //SwapperNoOp::SwapArray(data,length);
    00295   }
    00296   template<typename T>
    00297   static inline void Read(T* data, unsigned long length,
    00298     std::istream &_is) {
    00299     const unsigned int type_size = sizeof(T);
    00300     assert( data ); // Can we read from pointer ?
    00301     assert( length );
    00302     assert( _is ); // Is stream valid ?
    00303     _is.read( reinterpret_cast<char*>(data+0), type_size);
    00304     for(unsigned long i=1; i<length; ++i) {
    00305       assert( _is );
    00306       _is.read( reinterpret_cast<char*>(data+i), type_size );
    00307     }
    00308     //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
    00309     //  _is.GetSwapCode(), length);
    00310     SwapperNoOp::SwapArray(data,length);
    00311   }
    00312   template<typename T>
    00313   static inline void Write(const T* data, unsigned long length,
    00314     std::ostream &_os) {
    00315     const unsigned int type_size = sizeof(T);
    00316     assert( data ); // Can we write into pointer ?
    00317     assert( length );
    00318     assert( _os ); // Is stream valid ?
    00319     //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
    00320     //  _os.GetSwapCode(), length);
    00321     T swappedData = SwapperNoOp::Swap(data[0]);
    00322     _os.write( reinterpret_cast<const char*>(&swappedData), type_size);
    00323     for(unsigned long i=1; i<length;++i) {
    00324       assert( _os );
    00325       swappedData = SwapperNoOp::Swap(data[i]);
    00326       _os.write( reinterpret_cast<const char*>(&swappedData), type_size );
    00327     }
    00328     //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
    00329     //  _os.GetSwapCode(), length);
    00330   }
    00331 };
    00332
    00333 // For particular case for ASCII string
    00334 // WARNING: This template explicitely instanciates a particular
    00335 // EncodingImplementation THEREFORE it is required to be declared after the
    00336 // EncodingImplementation is needs (doh!)
    00337 #if 0
    00338 template<int TVM>
    00339 class Element<TVM>
    00340 {
    00341 public:
    00342   Element(const char array[])
    00343     {
    00344     unsigned int i = 0;
    00345     const char sep = '\\';
    00346     std::string sarray = array;
    00347     std::string::size_type pos1 = 0;
    00348     std::string::size_type pos2 = sarray.find(sep, pos1+1);
    00349     while(pos2 != std::string::npos)
    00350       {
    00351       Internal[i++] = sarray.substr(pos1, pos2-pos1);
    00352       pos1 = pos2+1;
    00353       pos2 = sarray.find(sep, pos1+1);
    00354       }
    00355     Internal[i] = sarray.substr(pos1, pos2-pos1);
    00356     // Shouldn't we do the contrary, since we know how many separators
    00357     // (and default behavior is to discard anything after the VM declared
    00358     assert( GetLength()-1 == i );
    00359     }
    00360
    00361   unsigned long GetLength() const {
    00362     return VMToLength<TVM>::Length;
    00363   }
    00364   // Implementation of Print is common to all Mode (ASCII/Binary)
    00365   void Print(std::ostream &_os) const {
    00366     _os << Internal[0]; // VM is at least garantee to be one
    00367     for(int i=1; i<VMToLength<TVM>::Length; ++i)
    00368       _os << "," << Internal[i];
    00369     }
    00370
    00371   void Read(std::istream &_is) {
    00372     EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
    00373     }
    00374   void Write(std::ostream &_os) const {
    00375     EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
    00376     }
    00377 private:
    00378   typename String Internal[VMToLength<TVM>::Length];
    00379 };
    00380
    00381 template< int TVM>
    00382 class Element<VR::PN, TVM> : public StringElement<TVM>
    00383 {
    00384 };
    00385 #endif
    00386
    00387 // Implementation for the undefined length (dynamically allocated array)
    00388 template<int TVR>
    00389 class Element<TVR, VM::VM1_n>
    00390 {
    00391 public:
    00392   // This the way to prevent default initialization
    00393   explicit Element() { Internal=0; Length=0; Save = false; }
    00394   ~Element() {
    00395     if( Save ) {
    00396       delete[] Internal;
    00397     }
    00398     Internal = 0;
    00399   }
    00400
    00401   // Length manipulation
    00402   // SetLength should really be protected anyway...all operation
    00403   // should go through SetArray
    00404   unsigned long GetLength() const { return Length; }
    00405   typedef typename VRToType<TVR>::Type Type;
    00406
    00407   void SetLength(unsigned long len) {
    00408     const unsigned int size = sizeof(Type);
    00409     if( len ) {
    00410       if( len > Length ) {
    00411         // perform realloc
    00412         assert( (len / size) * size == len );
    00413         Type *internal = new Type[len / size];
    00414         assert( Save == false );
    00415         Save = true; // ????
    00416         if( Internal )
    00417           {
    00418           memcpy(internal, Internal, len);
    00419           delete[] Internal;
    00420           }
    00421         Internal = internal;
    00422         }
    00423       }
    00424     Length = len / size;
    00425   }
    00426
    00427   // If save is set to zero user should not delete the pointer
    00428   //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
    00429   void SetArray(const Type *array, unsigned long len,
    00430     bool save = false) {
    00431     if( save ) {
    00432       SetLength(len); // realloc
    00433       memcpy(Internal, array, len/*/sizeof(Type)*/);
    00434       assert( Save == false );
    00435       }
    00436     else {
    00437       // TODO rewrite this stupid code:
    00438       assert( Length == 0 );
    00439       assert( Internal == 0 );
    00440       assert( Save == false );
    00441       Length = len / sizeof(Type);
    00442       //assert( (len / sizeof(Type)) * sizeof(Type) == len );
    00443       // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
    00444       // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
    00445       if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = 0; Length = 0; }
    00446       else Internal = const_cast<Type*>(array);
    00447       }
    00448       Save = save;
    00449   }
    00450   void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
    00451     assert( idx < Length );
    00452     Internal[idx] = v;
    00453   }
    00454   const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
    00455     assert( idx < Length );
    00456     return Internal[idx];
    00457   }
    00458   typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
    00459     assert( idx < Length );
    00460     return Internal[idx];
    00461   }
    00462   typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
    00463     return GetValue(idx);
    00464   }
    00465   void Set(Value const &v) {
    00466     const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
    00467     assert( bv ); // That would be bad...
    00468     if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
    00469       {
    00470       const Type* array = (Type*)bv->GetPointer();
    00471       if( array ) {
    00472         assert( array ); // That would be bad...
    00473         assert( Internal == 0 );
    00474         SetArray(array, bv->GetLength() ); }
    00475       }
    00476     else
    00477       {
    00478       std::stringstream ss;
    00479       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00480       ss.str( s );
    00481       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00482         GetLength(),ss);
    00483       }
    00484   }
    00485   void SetFromDataElement(DataElement const &de) {
    00486     const ByteValue *bv = de.GetByteValue();
    00487     if( !bv ) return;
    00488 #ifdef GDCM_WORDS_BIGENDIAN
    00489     if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
    00490 #else
    00491     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
    00492 #endif
    00493       {
    00494       Set(de.GetValue());
    00495       }
    00496     else
    00497       {
    00498       SetNoSwap(de.GetValue());
    00499       }
    00500   }
    00501
    00502
    00503   // Need to be placed after definition of EncodingImplementation<VR::VRASCII>
    00504   void WriteASCII(std::ostream &os) const {
    00505     return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os);
    00506     }
    00507
    00508   // Implementation of Print is common to all Mode (ASCII/Binary)
    00509   void Print(std::ostream &_os) const {
    00510     assert( Length );
    00511     assert( Internal );
    00512     _os << Internal[0]; // VM is at least garantee to be one
    00513     const unsigned long length = GetLength() < 25 ? GetLength() : 25;
    00514     for(unsigned long i=1; i<length; ++i)
    00515       _os << "," << Internal[i];
    00516     }
    00517   void Read(std::istream &_is) {
    00518     if( !Internal ) return;
    00519     EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00520       GetLength(),_is);
    00521     }
    00522   //void ReadComputeLength(std::istream &_is) {
    00523   //  if( !Internal ) return;
    00524   //  EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
    00525   //    Length,_is);
    00526   //  }
    00527   void Write(std::ostream &_os) const {
    00528     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00529       GetLength(),_os);
    00530     }
    00531
    00532   DataElement GetAsDataElement() const {
    00533     DataElement ret;
    00534     ret.SetVR( (VR::VRType)TVR );
    00535     if( Internal )
    00536       {
    00537       std::ostringstream os;
    00538       EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00539         GetLength(),os);
    00540       ret.SetByteValue( os.str().c_str(), os.str().size() );
    00541       }
    00542     return ret;
    00543   }
    00544
    00545   Element(const Element&_val) {
    00546     if( this != &_val) {
    00547       *this = _val;
    00548       }
    00549     }
    00550
    00551   Element &operator=(const Element &_val) {
    00552     Length = 0; // SYITF
    00553     Internal = 0;
    00554     SetArray(_val.Internal, _val.Length, true);
    00555     return *this;
    00556     }
    00557 protected:
    00558   void SetNoSwap(Value const &v) {
    00559     const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
    00560     assert( bv ); // That would be bad...
    00561     if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
    00562       {
    00563       const Type* array = (Type*)bv->GetPointer();
    00564       if( array ) {
    00565         assert( array ); // That would be bad...
    00566         assert( Internal == 0 );
    00567         SetArray(array, bv->GetLength() ); }
    00568       }
    00569     else
    00570       {
    00571       std::stringstream ss;
    00572       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00573       ss.str( s );
    00574       EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
    00575         GetLength(),ss);
    00576       }
    00577   }
    00578
    00579 private:
    00580   typename VRToType<TVR>::Type *Internal;
    00581   unsigned long Length; // unsigned int ??
    00582   bool Save;
    00583 };
    00584
    00585 //template <int TVM = VM::VM1_n>
    00586 //class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
    00587
    00588 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
    00589 template<int TVR>
    00590 class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
    00591 {
    00592 public:
    00593   typedef Element<TVR, VM::VM1_n> Parent;
    00594   void SetLength(int len) {
    00595     if( len <= 1 ) return;
    00596     Parent::SetLength(len);
    00597   }
    00598 };
    00599 template<int TVR>
    00600 class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
    00601 {
    00602 public:
    00603   typedef Element<TVR, VM::VM2_n> Parent;
    00604   void SetLength(int len) {
    00605     if( len % 2 ) return;
    00606     Parent::SetLength(len);
    00607   }
    00608 };
    00609 template<int TVR>
    00610 class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
    00611 {
    00612 public:
    00613   typedef Element<TVR, VM::VM1_n> Parent;
    00614   void SetLength(int len) {
    00615     if( len <= 2 ) return;
    00616     Parent::SetLength(len);
    00617   }
    00618 };
    00619 template<int TVR>
    00620 class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
    00621 {
    00622 public:
    00623   typedef Element<TVR, VM::VM3_n> Parent;
    00624   void SetLength(int len) {
    00625     if( len % 3 ) return;
    00626     Parent::SetLength(len);
    00627   }
    00628 };
    00629
    00630
    00631 //template<int T> struct VRToLength;
    00632 //template <> struct VRToLength<VR::AS>
    00633 //{ enum { Length  = VM::VM1 }; }
    00634 //template<>
    00635 //class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
    00636
    00637 // only 0010 1010 AS 1 Patient’s Age
    00638 template<>
    00639 class Element<VR::AS, VM::VM5>
    00640 {
    00641 public:
    00642   char Internal[VMToLength<VM::VM5>::Length];
    00643   void Print(std::ostream &_os) const {
    00644     _os << Internal;
    00645     }
    00646   unsigned long GetLength() const {
    00647     return VMToLength<VM::VM5>::Length;
    00648   }
    00649 };
    00650
    00651 template <>
    00652 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
    00653 // Make it impossible to compile any other cases:
    00654 template <int TVM> class Element<VR::OB, TVM>;
    00655
    00656 // Same for OW:
    00657 template <>
    00658 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
    00659 // Make it impossible to compile any other cases:
    00660 template <int TVM> class Element<VR::OW, TVM>;
    00661
    00662 } // namespace gdcm
    00663
    00664 #endif //GDCMELEMENT_H