# gdcmAttribute.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 __gdcmAttribute_h
    00016 #define __gdcmAttribute_h
    00017
    00018 #include "gdcmTypes.h"
    00019 #include "gdcmVR.h"
    00020 #include "gdcmTagToType.h"
    00021 #include "gdcmVM.h"
    00022 #include "gdcmElement.h"
    00023 #include "gdcmDataElement.h"
    00024 #include "gdcmDataSet.h"
    00025 #include "gdcmStaticAssert.h"
    00026
    00027 #include <string>
    00028 #include <vector>
    00029 #include <sstream>
    00030
    00031 namespace gdcm
    00032 {
    00033
    00034 struct void_;
    00035
    00036 // Declaration, also serve as forward declaration
    00037 template<int T> class VRVLSize;
    00038
    00039 // Implementation when VL is coded on 16 bits:
    00040 template<> class VRVLSize<0> {
    00041 public:
    00042   static inline uint16_t Read(std::istream &_is) {
    00043     uint16_t l;
    00044     _is.read((char*)&l, 2);
    00045     return l;
    00046     }
    00047
    00048   static inline void Write(std::ostream &os)  { (void)os;
    00049     }
    00050 };
    00051 // Implementation when VL is coded on 32 bits:
    00052 template<> class VRVLSize<1> {
    00053 public:
    00054   static inline uint32_t Read(std::istream &_is) {
    00055     char dummy[2];
    00056     _is.read(dummy, 2);
    00057
    00058     uint32_t l;
    00059     _is.read((char*)&l, 4);
    00060     return l;
    00061     }
    00062
    00063   static inline void Write(std::ostream &os)  { (void)os;
    00064     }
    00065 };
    00066
    00082 template<uint16_t Group, uint16_t Element,
    00083    int TVR = TagToType<Group, Element>::VRType, // can the user override this value ?
    00084    int TVM = TagToType<Group, Element>::VMType // can the user override this value ?
    00085    /*typename SQAttribute = void_*/ > // if only I had variadic template...
    00086 class Attribute
    00087 {
    00088 public:
    00089   typedef typename VRToType<TVR>::Type ArrayType;
    00090   enum { VMType = VMToLength<TVM>::Length };
    00091   ArrayType Internal[VMToLength<TVM>::Length];
    00092
    00093   // Make sure that user specified VR/VM are compatible with the public dictionary:
    00094   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
    00095   GDCM_STATIC_ASSERT( ((VM::VMType)TVM & (VM::VMType)(TagToType<Group, Element>::VMType)) );
    00096   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TVM == VM::VM1) )
    00097                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
    00098
    00099   static Tag GetTag() { return Tag(Group,Element); }
    00100   static VR  GetVR()  { return (VR::VRType)TVR; }
    00101   static VM  GetVM()  { return (VM::VMType)TVM; }
    00102
    00103   // The following two methods do make sense only in case of public element,
    00104   // when the template is intanciated with private element the VR/VM are simply
    00105   // defaulted to allow everything (see gdcmTagToType.h default template for TagToType)
    00106   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
    00107   static VM  GetDictVM() { return (VM::VMType)(TagToType<Group, Element>::VMType); }
    00108
    00109   // Some extra dummy checks:
    00110   // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one.
    00111
    00112   unsigned int GetNumberOfValues() const {
    00113     return VMToLength<TVM>::Length;
    00114   }
    00115   // Implementation of Print is common to all Mode (ASCII/Binary)
    00116   // TODO: Can we print a \ when in ASCII...well I don't think so
    00117   // it would mean we used a bad VM then, right ?
    00118   void Print(std::ostream &os) const {
    00119     os << GetTag() << " ";
    00120     os << TagToType<Group,Element>::GetVRString()  << " ";
    00121     os << TagToType<Group,Element>::GetVMString()  << " ";
    00122     os << Internal[0]; // VM is at least garantee to be one
    00123     for(unsigned int i=1; i<GetNumberOfValues(); ++i)
    00124       os << "," << Internal[i];
    00125     }
    00126
    00127   // copy:
    00128   //ArrayType GetValue(unsigned int idx = 0) {
    00129   //  assert( idx < GetNumberOfValues() );
    00130   //  return Internal[idx];
    00131   //}
    00132   //ArrayType operator[] (unsigned int idx) {
    00133   //  return GetValue(idx);
    00134   //}
    00135   // FIXME: is this always a good idea ?
    00136   // I do not think so, I prefer operator
    00137   //operator ArrayType () const { return Internal[0]; }
    00138
    00139   bool operator==(const Attribute &att) const
    00140     {
    00141     return std::equal(Internal, Internal+GetNumberOfValues(),
    00142       att.GetValues());
    00143     }
    00144   bool operator!=(const Attribute &att) const
    00145     {
    00146     return !std::equal(Internal, Internal+GetNumberOfValues(),
    00147       att.GetValues());
    00148     }
    00149   bool operator<(const Attribute &att) const
    00150     {
    00151     return std::lexicographical_compare(Internal, Internal+GetNumberOfValues(),
    00152       att.GetValues(), att.GetValues() + att.GetNumberOfValues() );
    00153     }
    00154
    00155   ArrayType &GetValue(unsigned int idx = 0) {
    00156     assert( idx < GetNumberOfValues() );
    00157     return Internal[idx];
    00158   }
    00159   ArrayType & operator[] (unsigned int idx) {
    00160     return GetValue(idx);
    00161   }
    00162   // const reference
    00163   ArrayType const &GetValue(unsigned int idx = 0) const {
    00164     assert( idx < GetNumberOfValues() );
    00165     return Internal[idx];
    00166   }
    00167   ArrayType const & operator[] (unsigned int idx) const {
    00168     return GetValue(idx);
    00169   }
    00170   void SetValue(ArrayType v, unsigned int idx = 0) {
    00171     assert( idx < GetNumberOfValues() );
    00172     Internal[idx] = v;
    00173   }
    00174   void SetValues(const ArrayType* array, unsigned int numel = VMType ) {
    00175     assert( array && numel && numel == GetNumberOfValues() );
    00176     // std::copy is smarted than a memcpy, and will call memcpy when POD type
    00177     std::copy(array, array+numel, Internal);
    00178   }
    00179   const ArrayType* GetValues() const {
    00180     return Internal;
    00181   }
    00182
    00183   // API to talk to the run-time layer: gdcm::DataElement
    00184   DataElement GetAsDataElement() const {
    00185     DataElement ret( GetTag() );
    00186     std::ostringstream os;
    00187     // os.imbue(std::locale::classic()); // This is not required AFAIK
    00188     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00189       GetNumberOfValues(),os);
    00190     ret.SetVR( GetVR() );
    00191     assert( ret.GetVR() != VR::SQ );
    00192     if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
    00193       {
    00194       if( GetVR() != VR::UI )
    00195         {
    00196         if( os.str().size() % 2 )
    00197           {
    00198           os << " ";
    00199           }
    00200         }
    00201       }
    00202     ret.SetByteValue( os.str().c_str(), os.str().size() );
    00203     return ret;
    00204   }
    00205
    00206   void SetFromDataElement(DataElement const &de) {
    00207     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
    00208     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 || GetTag().GetGroup() == 0x5000 );
    00209     assert( GetVR() != VR::INVALID );
    00210     assert( GetVR().Compatible( de.GetVR() ) || de.GetVR() == VR::INVALID ); // In case of VR::INVALID cannot use the & operator
    00211     const ByteValue *bv = de.GetByteValue();
    00212     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
    00213       {
    00214       SetByteValue(bv);
    00215       }
    00216     else
    00217       {
    00218       SetByteValueNoSwap(bv);
    00219       }
    00220   }
    00221   void Set(DataSet const &ds) {
    00222     SetFromDataElement( ds.GetDataElement( GetTag() ) );
    00223   }
    00224 protected:
    00225   void SetByteValueNoSwap(const ByteValue *bv) {
    00226     if( !bv ) return; // That would be bad...
    00227     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
    00228     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
    00229     //  {
    00230     //  // always do a copy !
    00231     //  SetValues(bv->GetPointer(), bv->GetLength());
    00232     //  }
    00233     //else
    00234       {
    00235       std::stringstream ss;
    00236       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00237       ss.str( s );
    00238       EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
    00239         GetNumberOfValues(),ss);
    00240       }
    00241   }
    00242   void SetByteValue(const ByteValue *bv) {
    00243     if( !bv ) return; // That would be bad...
    00244     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
    00245     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
    00246     //  {
    00247     //  // always do a copy !
    00248     //  SetValues(bv->GetPointer(), bv->GetLength());
    00249     //  }
    00250     //else
    00251       {
    00252       std::stringstream ss;
    00253       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00254       ss.str( s );
    00255       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00256         GetNumberOfValues(),ss);
    00257       }
    00258   }
    00259 #if 0 // TODO  FIXME the implicit way:
    00260   // explicit:
    00261   void Read(std::istream &_is) {
    00262     const uint16_t cref[] = { Group, Element };
    00263     uint16_t c[2];
    00264     _is.read((char*)&c, sizeof(c));
    00265     assert( c[0] == cref[0] && c[1] == cref[1] );
    00266     char vr[2];
    00267     _is.read(vr, 2); // Check consistency ?
    00268     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00269     uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is);
    00270     l /= sizeof( typename VRToType<TVR>::Type );
    00271     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00272       l,_is);
    00273   }
    00274   void Write(std::ostream &_os) const {
    00275     uint16_t c[] = { Group, Element };
    00276     _os.write((char*)&c, 4);
    00277     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00278     _os.write((char*)&l, 4);
    00279     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00280       GetLength(),_os);
    00281     }
    00282   void Read(std::istream &_is) {
    00283     uint16_t cref[] = { Group, Element };
    00284     uint16_t c[2];
    00285     _is.read((char*)&c, 4);
    00286     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00287     uint32_t l;
    00288     _is.read((char*)&l, 4);
    00289     l /= sizeof( typename VRToType<TVR>::Type );
    00290      return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00291       l,_is);
    00292     }
    00293   void Write(std::ostream &_os) const {
    00294     uint16_t c[] = { Group, Element };
    00295     _os.write((char*)&c, 4);
    00296     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00297     _os.write((char*)&l, 4);
    00298     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00299       GetLength(),_os);
    00300     }
    00301 #endif
    00302
    00303 };
    00304
    00305
    00306 // No need to repeat default template arg, since primary template
    00307 // will be used to generate the default arguments
    00308 template<uint16_t Group, uint16_t Element, int TVR >
    00309 class Attribute<Group,Element,TVR,VM::VM1_n>
    00310 {
    00311 public:
    00312   typedef typename VRToType<TVR>::Type ArrayType;
    00313
    00314   // Make sure that user specified VR/VM are compatible with the public dictionary:
    00315   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
    00316   GDCM_STATIC_ASSERT( (VM::VM1_n & (VM::VMType)(TagToType<Group, Element>::VMType)) );
    00317   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TagToType<Group,Element>::VMType == VM::VM1) )
    00318                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
    00319
    00320   static Tag GetTag() { return Tag(Group,Element); }
    00321   static VR  GetVR()  { return (VR::VRType)TVR; }
    00322   static VM  GetVM()  { return VM::VM1_n; }
    00323
    00324   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
    00325   static VM  GetDictVM() { return GetVM(); }
    00326
    00327   // This the way to prevent default initialization
    00328   explicit Attribute() { Internal=0; Length=0; Own = true; }
    00329   ~Attribute() {
    00330     if( Own ) {
    00331       delete[] Internal;
    00332     }
    00333     Internal = 0; // paranoid
    00334   }
    00335
    00336   unsigned int GetNumberOfValues() const { return Length; }
    00337
    00338   void SetNumberOfValues(unsigned int numel)
    00339     {
    00340     SetValues(NULL, numel, true);
    00341     }
    00342
    00343   const ArrayType* GetValues() const {
    00344     return Internal;
    00345   }
    00346   void Print(std::ostream &os) const {
    00347     os << GetTag() << " ";
    00348     os << GetVR()  << " ";
    00349     os << GetVM()  << " ";
    00350     os << Internal[0]; // VM is at least garantee to be one
    00351     for(unsigned int i=1; i<GetNumberOfValues(); ++i)
    00352       os << "," << Internal[i];
    00353     }
    00354   ArrayType &GetValue(unsigned int idx = 0) {
    00355     assert( idx < GetNumberOfValues() );
    00356     return Internal[idx];
    00357   }
    00358   ArrayType &operator[] (unsigned int idx) {
    00359     return GetValue(idx);
    00360   }
    00361   // const reference
    00362   ArrayType const &GetValue(unsigned int idx = 0) const {
    00363     assert( idx < GetNumberOfValues() );
    00364     return Internal[idx];
    00365   }
    00366   ArrayType const & operator[] (unsigned int idx) const {
    00367     return GetValue(idx);
    00368   }
    00369   void SetValue(unsigned int idx, ArrayType v) {
    00370     assert( idx < GetNumberOfValues() );
    00371     Internal[idx] = v;
    00372   }
    00373   void SetValue(ArrayType v) { SetValue(0, v); }
    00374
    00375   void SetValues(const ArrayType *array, unsigned int numel, bool own = false)
    00376     {
    00377     if( Internal ) // were we used before ?
    00378       {
    00379       // yes !
    00380       if( Own ) delete[] Internal;
    00381       Internal = 0;
    00382       }
    00383     Own = own;
    00384     Length = numel;
    00385     assert( Internal == 0 );
    00386     if( own ) // make a copy:
    00387       {
    00388       assert( /*array &&*/ numel );
    00389       Internal = new ArrayType[numel];
    00390       if( array && numel )
    00391         std::copy(array, array+numel, Internal);
    00392       }
    00393     else // pass pointer
    00394       {
    00395       Internal = const_cast<ArrayType*>(array);
    00396       }
    00397     // postcondition
    00398     assert( numel == GetNumberOfValues() );
    00399     }
    00400
    00401   DataElement GetAsDataElement() const {
    00402     DataElement ret( GetTag() );
    00403     std::ostringstream os;
    00404     if( Internal )
    00405       {
    00406       EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00407         GetNumberOfValues(),os);
    00408       if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
    00409         {
    00410         if( GetVR() != VR::UI )
    00411           {
    00412           if( os.str().size() % 2 )
    00413             {
    00414             os << " ";
    00415             }
    00416           }
    00417         }
    00418       }
    00419     ret.SetVR( GetVR() );
    00420     assert( ret.GetVR() != VR::SQ );
    00421     ret.SetByteValue( os.str().c_str(), os.str().size() );
    00422     return ret;
    00423   }
    00424   void SetFromDataElement(DataElement const &de) {
    00425     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
    00426     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 );
    00427     assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator
    00428     assert( !de.IsEmpty() );
    00429     const ByteValue *bv = de.GetByteValue();
    00430     SetByteValue(bv);
    00431   }
    00432 protected:
    00433   void SetByteValue(const ByteValue *bv) {
    00434     assert( bv ); // FIXME
    00435     std::stringstream ss;
    00436     std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00437     Length = bv->GetLength(); // HACK FIXME
    00438     ss.str( s );
    00439     ArrayType *internal;
    00440     ArrayType buffer[256];
    00441     if( bv->GetLength() < 256 )
    00442       {
    00443       internal = buffer;
    00444       }
    00445     else
    00446       {
    00447       internal = new ArrayType[bv->GetLength()]; // over allocation
    00448       }
    00449     EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss);
    00450     SetValues( internal, Length, true );
    00451     if( !(bv->GetLength() < 256) )
    00452       {
    00453       delete[] internal;
    00454       }
    00455     //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00456     //  GetNumberOfValues(),ss);
    00457   }
    00458
    00459 private:
    00460   ArrayType *Internal;
    00461   unsigned int Length;
    00462   bool Own : 1;
    00463 };
    00464
    00465 template<uint16_t Group, uint16_t Element, int TVR>
    00466 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00467 {
    00468 public:
    00469   VM  GetVM() const { return VM::VM1_8; }
    00470 };
    00471
    00472 template<uint16_t Group, uint16_t Element, int TVR>
    00473 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00474 {
    00475 public:
    00476   VM  GetVM() const { return VM::VM2_n; }
    00477 };
    00478
    00479 template<uint16_t Group, uint16_t Element, int TVR>
    00480 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n>
    00481 {
    00482 public:
    00483   static VM  GetVM() { return VM::VM2_2n; }
    00484 };
    00485
    00486 template<uint16_t Group, uint16_t Element, int TVR>
    00487 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00488 {
    00489 public:
    00490   static VM  GetVM() { return VM::VM3_n; }
    00491 };
    00492
    00493 template<uint16_t Group, uint16_t Element, int TVR>
    00494 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n>
    00495 {
    00496 public:
    00497   static VM  GetVM() { return VM::VM3_3n; }
    00498 };
    00499
    00500
    00501 // For particular case for ASCII string
    00502 // WARNING: This template explicitely instanciates a particular
    00503 // EncodingImplementation THEREFORE it is required to be declared after the
    00504 // EncodingImplementation is needs (doh!)
    00505 #if 0
    00506 template<int TVM>
    00507 class Attribute<TVM>
    00508 {
    00509 public:
    00510   Attribute(const char array[])
    00511     {
    00512     unsigned int i = 0;
    00513     const char sep = '\\';
    00514     std::string sarray = array;
    00515     std::string::size_type pos1 = 0;
    00516     std::string::size_type pos2 = sarray.find(sep, pos1+1);
    00517     while(pos2 != std::string::npos)
    00518       {
    00519       Internal[i++] = sarray.substr(pos1, pos2-pos1);
    00520       pos1 = pos2+1;
    00521       pos2 = sarray.find(sep, pos1+1);
    00522       }
    00523     Internal[i] = sarray.substr(pos1, pos2-pos1);
    00524     // Shouldn't we do the contrary, since we know how many separators
    00525     // (and default behavior is to discard anything after the VM declared
    00526     assert( GetLength()-1 == i );
    00527     }
    00528
    00529   unsigned long GetLength() const {
    00530     return VMToLength<TVM>::Length;
    00531   }
    00532   // Implementation of Print is common to all Mode (ASCII/Binary)
    00533   void Print(std::ostream &_os) const {
    00534     _os << Internal[0]; // VM is at least garantee to be one
    00535     for(int i=1; i<VMToLength<TVM>::Length; ++i)
    00536       _os << "," << Internal[i];
    00537     }
    00538
    00539   void Read(std::istream &_is) {
    00540     EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
    00541     }
    00542   void Write(std::ostream &_os) const {
    00543     EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
    00544     }
    00545 private:
    00546   typename String Internal[VMToLength<TVM>::Length];
    00547 };
    00548
    00549 template< int TVM>
    00550 class Attribute<VR::PN, TVM> : public StringAttribute<TVM>
    00551 {
    00552 };
    00553 #endif
    00554
    00555 #if 0
    00556
    00557 // Implementation for the undefined length (dynamically allocated array)
    00558 template<int TVR>
    00559 class Attribute<TVR, VM::VM1_n>
    00560 {
    00561 public:
    00562   // This the way to prevent default initialization
    00563   explicit Attribute() { Internal=0; Length=0; }
    00564   ~Attribute() {
    00565     delete[] Internal;
    00566     Internal = 0;
    00567   }
    00568
    00569   // Length manipulation
    00570   // SetLength should really be protected anyway...all operation
    00571   // should go through SetArray
    00572   unsigned long GetLength() const { return Length; }
    00573   typedef typename VRToType<TVR>::Type ArrayType;
    00574   void SetLength(unsigned long len) {
    00575     const unsigned int size = sizeof(ArrayType);
    00576     if( len ) {
    00577       if( len > Length ) {
    00578         // perform realloc
    00579         assert( (len / size) * size == len );
    00580         ArrayType *internal = new ArrayType[len / size];
    00581         memcpy(internal, Internal, Length * size);
    00582         delete[] Internal;
    00583         Internal = internal;
    00584         }
    00585       }
    00586     Length = len / size;
    00587   }
    00588
    00589   // If save is set to zero user should not delete the pointer
    00590   //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
    00591   void SetArray(const ArrayType *array, unsigned long len,
    00592     bool save = false) {
    00593     if( save ) {
    00594       SetLength(len); // realloc
    00595       memcpy(Internal, array, len/*/sizeof(ArrayType)*/);
    00596       }
    00597     else {
    00598       // TODO rewrite this stupid code:
    00599       Length = len;
    00600       //Internal = array;
    00601       assert(0);
    00602       }
    00603   }
    00604   // Implementation of Print is common to all Mode (ASCII/Binary)
    00605   void Print(std::ostream &_os) const {
    00606     assert( Length );
    00607     assert( Internal );
    00608     _os << Internal[0]; // VM is at least garantee to be one
    00609     const unsigned long length = GetLength() < 25 ? GetLength() : 25;
    00610     for(unsigned long i=1; i<length; ++i)
    00611       _os << "," << Internal[i];
    00612     }
    00613   void Read(std::istream &_is) {
    00614     EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00615       GetLength(),_is);
    00616     }
    00617   void Write(std::ostream &_os) const {
    00618     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00619       GetLength(),_os);
    00620     }
    00621
    00622   Attribute(const Attribute&_val) {
    00623     if( this != &_val) {
    00624       *this = _val;
    00625       }
    00626     }
    00627
    00628   Attribute &operator=(const Attribute &_val) {
    00629     Length = 0; // SYITF
    00630     Internal = 0;
    00631     SetArray(_val.Internal, _val.Length, true);
    00632     return *this;
    00633     }
    00634
    00635 private:
    00636   typename VRToType<TVR>::Type *Internal;
    00637   unsigned long Length; // unsigned int ??
    00638 };
    00639
    00640 //template <int TVM = VM::VM1_n>
    00641 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {};
    00642
    00643 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
    00644 template<int TVR>
    00645 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n>
    00646 {
    00647 public:
    00648   typedef Attribute<TVR, VM::VM1_n> Parent;
    00649   void SetLength(int len) {
    00650     if( len <= 1 ) return;
    00651     Parent::SetLength(len);
    00652   }
    00653 };
    00654 template<int TVR>
    00655 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n>
    00656 {
    00657 public:
    00658   typedef Attribute<TVR, VM::VM2_n> Parent;
    00659   void SetLength(int len) {
    00660     if( len % 2 ) return;
    00661     Parent::SetLength(len);
    00662   }
    00663 };
    00664 template<int TVR>
    00665 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n>
    00666 {
    00667 public:
    00668   typedef Attribute<TVR, VM::VM1_n> Parent;
    00669   void SetLength(int len) {
    00670     if( len <= 2 ) return;
    00671     Parent::SetLength(len);
    00672   }
    00673 };
    00674 template<int TVR>
    00675 class Attribute<TVR, VM::VM3_3n> : public Attribute<TVR, VM::VM3_n>
    00676 {
    00677 public:
    00678   typedef Attribute<TVR, VM::VM3_n> Parent;
    00679   void SetLength(int len) {
    00680     if( len % 3 ) return;
    00681     Parent::SetLength(len);
    00682   }
    00683 };
    00684
    00685
    00686 //template<int T> struct VRToLength;
    00687 //template <> struct VRToLength<VR::AS>
    00688 //{ enum { Length  = VM::VM1 }; }
    00689 //template<>
    00690 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length >
    00691
    00692 // only 0010 1010 AS 1 Patient’s Age
    00693 template<>
    00694 class Attribute<VR::AS, VM::VM5>
    00695 {
    00696 public:
    00697   char Internal[VMToLength<VM::VM5>::Length];
    00698   void Print(std::ostream &_os) const {
    00699     _os << Internal;
    00700     }
    00701 };
    00702
    00703 template <>
    00704 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {};
    00705 // Make it impossible to compile any other cases:
    00706 template <int TVM> class Attribute<VR::OB, TVM>;
    00707
    00708 // Same for OW:
    00709 template <>
    00710 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {};
    00711 // Make it impossible to compile any other cases:
    00712 template <int TVM> class Attribute<VR::OW, TVM>;
    00713 #endif
    00714
    00715 #if 0
    00716 template<>
    00717 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1>
    00718 {
    00719 public:
    00720   char *Internal;
    00721   unsigned long Length; // unsigned int ??
    00722
    00723   void Print(std::ostream &_os) const {
    00724     _os << Internal[0];
    00725     }
    00726   void SetBytes(char *bytes, unsigned long length) {
    00727     Internal = bytes;
    00728     Length = length;
    00729   }
    00730   void Read(std::istream &_is) {
    00731      uint16_t c[2];
    00732     _is.read((char*)&c, 4);
    00733     uint32_t l;
    00734     _is.read((char*)&l, 4);
    00735     Length = l;
    00736     _is.read( Internal, Length );
    00737     }
    00738   void Write(std::ostream &_os) const {
    00739      uint16_t c[] = {0x7fe0, 0x0010};
    00740     _os.write((char*)&c, 4);
    00741     _os.write((char*)&Length, 4);
    00742     _os.write( Internal, Length );
    00743     }
    00744 };
    00745 #endif
    00746
    00747 /*
    00748 // Removing Attribute for SQ for now...
    00749 template<uint16_t Group, uint16_t Element, typename SQA>
    00750 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA>
    00751 {
    00752 public:
    00753   SQA sqa;
    00754   void Print(std::ostream &_os) const {
    00755     _os << Tag(Group,Element);
    00756     sqa.Print(_os << std::endl << '\t');
    00757     }
    00758  void Write(std::ostream &_os) const {
    00759     uint16_t c[] = {Group, Element};
    00760     _os.write((char*)&c, 4);
    00761     uint32_t undef = 0xffffffff;
    00762     _os.write((char*)&undef, 4);
    00763     uint16_t item_beg[] = {0xfffe,0xe000};
    00764     _os.write((char*)&item_beg, 4);
    00765     _os.write((char*)&undef, 4);
    00766     sqa.Write(_os);
    00767     uint16_t item_end[] = {0xfffe,0xe00d};
    00768     _os.write((char*)&item_end, 4);
    00769     uint32_t zero = 0x0;
    00770     _os.write((char*)&zero, 4);
    00771     uint16_t seq_end[] = {0xfffe, 0xe0dd};
    00772     _os.write((char*)&seq_end, 4);
    00773     _os.write((char*)&zero, 4);
    00774     }
    00775 };
    00776 */
    00777
    00783 } // namespace gdcm
    00784
    00785 #endif //__gdcmAttribute_h