# 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-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 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     if( de.IsEmpty() ) return;
    00212     const ByteValue *bv = de.GetByteValue();
    00213     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
    00214       {
    00215       SetByteValue(bv);
    00216       }
    00217     else
    00218       {
    00219       SetByteValueNoSwap(bv);
    00220       }
    00221   }
    00222   void Set(DataSet const &ds) {
    00223     SetFromDataElement( ds.GetDataElement( GetTag() ) );
    00224   }
    00225   void SetFromDataSet(DataSet const &ds) {
    00226     if( ds.FindDataElement( GetTag() ) &&
    00227       !ds.GetDataElement( GetTag() ).IsEmpty() )
    00228       {
    00229       SetFromDataElement( ds.GetDataElement( GetTag() ) );
    00230       }
    00231   }
    00232 protected:
    00233   void SetByteValueNoSwap(const ByteValue *bv) {
    00234     if( !bv ) return; // That would be bad...
    00235     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
    00236     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
    00237     //  {
    00238     //  // always do a copy !
    00239     //  SetValues(bv->GetPointer(), bv->GetLength());
    00240     //  }
    00241     //else
    00242       {
    00243       std::stringstream ss;
    00244       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00245       ss.str( s );
    00246       EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
    00247         GetNumberOfValues(),ss);
    00248       }
    00249   }
    00250   void SetByteValue(const ByteValue *bv) {
    00251     if( !bv ) return; // That would be bad...
    00252     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
    00253     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
    00254     //  {
    00255     //  // always do a copy !
    00256     //  SetValues(bv->GetPointer(), bv->GetLength());
    00257     //  }
    00258     //else
    00259       {
    00260       std::stringstream ss;
    00261       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00262       ss.str( s );
    00263       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00264         GetNumberOfValues(),ss);
    00265       }
    00266   }
    00267 #if 0 // TODO  FIXME the implicit way:
    00268   // explicit:
    00269   void Read(std::istream &_is) {
    00270     const uint16_t cref[] = { Group, Element };
    00271     uint16_t c[2];
    00272     _is.read((char*)&c, sizeof(c));
    00273     assert( c[0] == cref[0] && c[1] == cref[1] );
    00274     char vr[2];
    00275     _is.read(vr, 2); // Check consistency ?
    00276     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00277     uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is);
    00278     l /= sizeof( typename VRToType<TVR>::Type );
    00279     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00280       l,_is);
    00281   }
    00282   void Write(std::ostream &_os) const {
    00283     uint16_t c[] = { Group, Element };
    00284     _os.write((char*)&c, 4);
    00285     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00286     _os.write((char*)&l, 4);
    00287     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00288       GetLength(),_os);
    00289     }
    00290   void Read(std::istream &_is) {
    00291     uint16_t cref[] = { Group, Element };
    00292     uint16_t c[2];
    00293     _is.read((char*)&c, 4);
    00294     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00295     uint32_t l;
    00296     _is.read((char*)&l, 4);
    00297     l /= sizeof( typename VRToType<TVR>::Type );
    00298      return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00299       l,_is);
    00300     }
    00301   void Write(std::ostream &_os) const {
    00302     uint16_t c[] = { Group, Element };
    00303     _os.write((char*)&c, 4);
    00304     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
    00305     _os.write((char*)&l, 4);
    00306     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00307       GetLength(),_os);
    00308     }
    00309 #endif
    00310
    00311 };
    00312
    00313
    00314 // No need to repeat default template arg, since primary template
    00315 // will be used to generate the default arguments
    00316 template<uint16_t Group, uint16_t Element, int TVR >
    00317 class Attribute<Group,Element,TVR,VM::VM1_n>
    00318 {
    00319 public:
    00320   typedef typename VRToType<TVR>::Type ArrayType;
    00321
    00322   // Make sure that user specified VR/VM are compatible with the public dictionary:
    00323   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
    00324   GDCM_STATIC_ASSERT( (VM::VM1_n & (VM::VMType)(TagToType<Group, Element>::VMType)) );
    00325   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TagToType<Group,Element>::VMType == VM::VM1) )
    00326                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
    00327
    00328   static Tag GetTag() { return Tag(Group,Element); }
    00329   static VR  GetVR()  { return (VR::VRType)TVR; }
    00330   static VM  GetVM()  { return VM::VM1_n; }
    00331
    00332   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
    00333   static VM  GetDictVM() { return GetVM(); }
    00334
    00335   // This the way to prevent default initialization
    00336   explicit Attribute() { Internal=0; Length=0; Own = true; }
    00337   ~Attribute() {
    00338     if( Own ) {
    00339       delete[] Internal;
    00340     }
    00341     Internal = 0; // paranoid
    00342   }
    00343
    00344   unsigned int GetNumberOfValues() const { return Length; }
    00345
    00346   void SetNumberOfValues(unsigned int numel)
    00347     {
    00348     SetValues(NULL, numel, true);
    00349     }
    00350
    00351   const ArrayType* GetValues() const {
    00352     return Internal;
    00353   }
    00354   void Print(std::ostream &os) const {
    00355     os << GetTag() << " ";
    00356     os << GetVR()  << " ";
    00357     os << GetVM()  << " ";
    00358     os << Internal[0]; // VM is at least garantee to be one
    00359     for(unsigned int i=1; i<GetNumberOfValues(); ++i)
    00360       os << "," << Internal[i];
    00361     }
    00362   ArrayType &GetValue(unsigned int idx = 0) {
    00363     assert( idx < GetNumberOfValues() );
    00364     return Internal[idx];
    00365   }
    00366   ArrayType &operator[] (unsigned int idx) {
    00367     return GetValue(idx);
    00368   }
    00369   // const reference
    00370   ArrayType const &GetValue(unsigned int idx = 0) const {
    00371     assert( idx < GetNumberOfValues() );
    00372     return Internal[idx];
    00373   }
    00374   ArrayType const & operator[] (unsigned int idx) const {
    00375     return GetValue(idx);
    00376   }
    00377   void SetValue(unsigned int idx, ArrayType v) {
    00378     assert( idx < GetNumberOfValues() );
    00379     Internal[idx] = v;
    00380   }
    00381   void SetValue(ArrayType v) { SetValue(0, v); }
    00382
    00383   void SetValues(const ArrayType *array, unsigned int numel, bool own = false)
    00384     {
    00385     if( Internal ) // were we used before ?
    00386       {
    00387       // yes !
    00388       if( Own ) delete[] Internal;
    00389       Internal = 0;
    00390       }
    00391     Own = own;
    00392     Length = numel;
    00393     assert( Internal == 0 );
    00394     if( own ) // make a copy:
    00395       {
    00396       assert( /*array &&*/ numel );
    00397       Internal = new ArrayType[numel];
    00398       if( array && numel )
    00399         std::copy(array, array+numel, Internal);
    00400       }
    00401     else // pass pointer
    00402       {
    00403       Internal = const_cast<ArrayType*>(array);
    00404       }
    00405     // postcondition
    00406     assert( numel == GetNumberOfValues() );
    00407     }
    00408
    00409   DataElement GetAsDataElement() const {
    00410     DataElement ret( GetTag() );
    00411     std::ostringstream os;
    00412     if( Internal )
    00413       {
    00414       EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00415         GetNumberOfValues(),os);
    00416       if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
    00417         {
    00418         if( GetVR() != VR::UI )
    00419           {
    00420           if( os.str().size() % 2 )
    00421             {
    00422             os << " ";
    00423             }
    00424           }
    00425         }
    00426       }
    00427     ret.SetVR( GetVR() );
    00428     assert( ret.GetVR() != VR::SQ );
    00429     ret.SetByteValue( os.str().c_str(), os.str().size() );
    00430     return ret;
    00431   }
    00432   void SetFromDataElement(DataElement const &de) {
    00433     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
    00434     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 );
    00435     assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator
    00436     assert( !de.IsEmpty() );
    00437     const ByteValue *bv = de.GetByteValue();
    00438     SetByteValue(bv);
    00439   }
    00440 protected:
    00441   void SetByteValue(const ByteValue *bv) {
    00442     assert( bv ); // FIXME
    00443     std::stringstream ss;
    00444     std::string s = std::string( bv->GetPointer(), bv->GetLength() );
    00445     Length = bv->GetLength(); // HACK FIXME
    00446     ss.str( s );
    00447     ArrayType *internal;
    00448     ArrayType buffer[256];
    00449     if( bv->GetLength() < 256 )
    00450       {
    00451       internal = buffer;
    00452       }
    00453     else
    00454       {
    00455       internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation
    00456       }
    00457     EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss);
    00458     SetValues( internal, Length, true );
    00459     if( !(bv->GetLength() < 256) )
    00460       {
    00461       delete[] internal;
    00462       }
    00463     //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00464     //  GetNumberOfValues(),ss);
    00465   }
    00466
    00467 private:
    00468   ArrayType *Internal;
    00469   unsigned int Length;
    00470   bool Own : 1;
    00471 };
    00472
    00473 template<uint16_t Group, uint16_t Element, int TVR>
    00474 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00475 {
    00476 public:
    00477   VM  GetVM() const { return VM::VM1_8; }
    00478 };
    00479
    00480 template<uint16_t Group, uint16_t Element, int TVR>
    00481 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00482 {
    00483 public:
    00484   VM  GetVM() const { return VM::VM2_n; }
    00485 };
    00486
    00487 template<uint16_t Group, uint16_t Element, int TVR>
    00488 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n>
    00489 {
    00490 public:
    00491   static VM  GetVM() { return VM::VM2_2n; }
    00492 };
    00493
    00494 template<uint16_t Group, uint16_t Element, int TVR>
    00495 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
    00496 {
    00497 public:
    00498   static VM  GetVM() { return VM::VM3_n; }
    00499 };
    00500
    00501 template<uint16_t Group, uint16_t Element, int TVR>
    00502 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n>
    00503 {
    00504 public:
    00505   static VM  GetVM() { return VM::VM3_3n; }
    00506 };
    00507
    00508
    00509 // For particular case for ASCII string
    00510 // WARNING: This template explicitely instanciates a particular
    00511 // EncodingImplementation THEREFORE it is required to be declared after the
    00512 // EncodingImplementation is needs (doh!)
    00513 #if 0
    00514 template<int TVM>
    00515 class Attribute<TVM>
    00516 {
    00517 public:
    00518   Attribute(const char array[])
    00519     {
    00520     unsigned int i = 0;
    00521     const char sep = '\\';
    00522     std::string sarray = array;
    00523     std::string::size_type pos1 = 0;
    00524     std::string::size_type pos2 = sarray.find(sep, pos1+1);
    00525     while(pos2 != std::string::npos)
    00526       {
    00527       Internal[i++] = sarray.substr(pos1, pos2-pos1);
    00528       pos1 = pos2+1;
    00529       pos2 = sarray.find(sep, pos1+1);
    00530       }
    00531     Internal[i] = sarray.substr(pos1, pos2-pos1);
    00532     // Shouldn't we do the contrary, since we know how many separators
    00533     // (and default behavior is to discard anything after the VM declared
    00534     assert( GetLength()-1 == i );
    00535     }
    00536
    00537   unsigned long GetLength() const {
    00538     return VMToLength<TVM>::Length;
    00539   }
    00540   // Implementation of Print is common to all Mode (ASCII/Binary)
    00541   void Print(std::ostream &_os) const {
    00542     _os << Internal[0]; // VM is at least garantee to be one
    00543     for(int i=1; i<VMToLength<TVM>::Length; ++i)
    00544       _os << "," << Internal[i];
    00545     }
    00546
    00547   void Read(std::istream &_is) {
    00548     EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
    00549     }
    00550   void Write(std::ostream &_os) const {
    00551     EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
    00552     }
    00553 private:
    00554   typename String Internal[VMToLength<TVM>::Length];
    00555 };
    00556
    00557 template< int TVM>
    00558 class Attribute<VR::PN, TVM> : public StringAttribute<TVM>
    00559 {
    00560 };
    00561 #endif
    00562
    00563 #if 0
    00564
    00565 // Implementation for the undefined length (dynamically allocated array)
    00566 template<int TVR>
    00567 class Attribute<TVR, VM::VM1_n>
    00568 {
    00569 public:
    00570   // This the way to prevent default initialization
    00571   explicit Attribute() { Internal=0; Length=0; }
    00572   ~Attribute() {
    00573     delete[] Internal;
    00574     Internal = 0;
    00575   }
    00576
    00577   // Length manipulation
    00578   // SetLength should really be protected anyway...all operation
    00579   // should go through SetArray
    00580   unsigned long GetLength() const { return Length; }
    00581   typedef typename VRToType<TVR>::Type ArrayType;
    00582   void SetLength(unsigned long len) {
    00583     const unsigned int size = sizeof(ArrayType);
    00584     if( len ) {
    00585       if( len > Length ) {
    00586         // perform realloc
    00587         assert( (len / size) * size == len );
    00588         ArrayType *internal = new ArrayType[len / size];
    00589         memcpy(internal, Internal, Length * size);
    00590         delete[] Internal;
    00591         Internal = internal;
    00592         }
    00593       }
    00594     Length = len / size;
    00595   }
    00596
    00597   // If save is set to zero user should not delete the pointer
    00598   //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
    00599   void SetArray(const ArrayType *array, unsigned long len,
    00600     bool save = false) {
    00601     if( save ) {
    00602       SetLength(len); // realloc
    00603       memcpy(Internal, array, len/*/sizeof(ArrayType)*/);
    00604       }
    00605     else {
    00606       // TODO rewrite this stupid code:
    00607       Length = len;
    00608       //Internal = array;
    00609       assert(0);
    00610       }
    00611   }
    00612   // Implementation of Print is common to all Mode (ASCII/Binary)
    00613   void Print(std::ostream &_os) const {
    00614     assert( Length );
    00615     assert( Internal );
    00616     _os << Internal[0]; // VM is at least garantee to be one
    00617     const unsigned long length = GetLength() < 25 ? GetLength() : 25;
    00618     for(unsigned long i=1; i<length; ++i)
    00619       _os << "," << Internal[i];
    00620     }
    00621   void Read(std::istream &_is) {
    00622     EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
    00623       GetLength(),_is);
    00624     }
    00625   void Write(std::ostream &_os) const {
    00626     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
    00627       GetLength(),_os);
    00628     }
    00629
    00630   Attribute(const Attribute&_val) {
    00631     if( this != &_val) {
    00632       *this = _val;
    00633       }
    00634     }
    00635
    00636   Attribute &operator=(const Attribute &_val) {
    00637     Length = 0; // SYITF
    00638     Internal = 0;
    00639     SetArray(_val.Internal, _val.Length, true);
    00640     return *this;
    00641     }
    00642
    00643 private:
    00644   typename VRToType<TVR>::Type *Internal;
    00645   unsigned long Length; // unsigned int ??
    00646 };
    00647
    00648 //template <int TVM = VM::VM1_n>
    00649 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {};
    00650
    00651 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
    00652 template<int TVR>
    00653 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n>
    00654 {
    00655 public:
    00656   typedef Attribute<TVR, VM::VM1_n> Parent;
    00657   void SetLength(int len) {
    00658     if( len <= 1 ) return;
    00659     Parent::SetLength(len);
    00660   }
    00661 };
    00662 template<int TVR>
    00663 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n>
    00664 {
    00665 public:
    00666   typedef Attribute<TVR, VM::VM2_n> Parent;
    00667   void SetLength(int len) {
    00668     if( len % 2 ) return;
    00669     Parent::SetLength(len);
    00670   }
    00671 };
    00672 template<int TVR>
    00673 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n>
    00674 {
    00675 public:
    00676   typedef Attribute<TVR, VM::VM1_n> Parent;
    00677   void SetLength(int len) {
    00678     if( len <= 2 ) return;
    00679     Parent::SetLength(len);
    00680   }
    00681 };
    00682 template<int TVR>
    00683 class Attribute<TVR, VM::VM3_3n> : public Attribute<TVR, VM::VM3_n>
    00684 {
    00685 public:
    00686   typedef Attribute<TVR, VM::VM3_n> Parent;
    00687   void SetLength(int len) {
    00688     if( len % 3 ) return;
    00689     Parent::SetLength(len);
    00690   }
    00691 };
    00692
    00693
    00694 //template<int T> struct VRToLength;
    00695 //template <> struct VRToLength<VR::AS>
    00696 //{ enum { Length  = VM::VM1 }; }
    00697 //template<>
    00698 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length >
    00699
    00700 // only 0010 1010 AS 1 Patient’s Age
    00701 template<>
    00702 class Attribute<VR::AS, VM::VM5>
    00703 {
    00704 public:
    00705   char Internal[VMToLength<VM::VM5>::Length];
    00706   void Print(std::ostream &_os) const {
    00707     _os << Internal;
    00708     }
    00709 };
    00710
    00711 template <>
    00712 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {};
    00713 // Make it impossible to compile any other cases:
    00714 template <int TVM> class Attribute<VR::OB, TVM>;
    00715
    00716 // Same for OW:
    00717 template <>
    00718 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {};
    00719 // Make it impossible to compile any other cases:
    00720 template <int TVM> class Attribute<VR::OW, TVM>;
    00721 #endif
    00722
    00723 #if 0
    00724 template<>
    00725 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1>
    00726 {
    00727 public:
    00728   char *Internal;
    00729   unsigned long Length; // unsigned int ??
    00730
    00731   void Print(std::ostream &_os) const {
    00732     _os << Internal[0];
    00733     }
    00734   void SetBytes(char *bytes, unsigned long length) {
    00735     Internal = bytes;
    00736     Length = length;
    00737   }
    00738   void Read(std::istream &_is) {
    00739      uint16_t c[2];
    00740     _is.read((char*)&c, 4);
    00741     uint32_t l;
    00742     _is.read((char*)&l, 4);
    00743     Length = l;
    00744     _is.read( Internal, Length );
    00745     }
    00746   void Write(std::ostream &_os) const {
    00747      uint16_t c[] = {0x7fe0, 0x0010};
    00748     _os.write((char*)&c, 4);
    00749     _os.write((char*)&Length, 4);
    00750     _os.write( Internal, Length );
    00751     }
    00752 };
    00753 #endif
    00754
    00755 /*
    00756 // Removing Attribute for SQ for now...
    00757 template<uint16_t Group, uint16_t Element, typename SQA>
    00758 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA>
    00759 {
    00760 public:
    00761   SQA sqa;
    00762   void Print(std::ostream &_os) const {
    00763     _os << Tag(Group,Element);
    00764     sqa.Print(_os << std::endl << '\t');
    00765     }
    00766  void Write(std::ostream &_os) const {
    00767     uint16_t c[] = {Group, Element};
    00768     _os.write((char*)&c, 4);
    00769     uint32_t undef = 0xffffffff;
    00770     _os.write((char*)&undef, 4);
    00771     uint16_t item_beg[] = {0xfffe,0xe000};
    00772     _os.write((char*)&item_beg, 4);
    00773     _os.write((char*)&undef, 4);
    00774     sqa.Write(_os);
    00775     uint16_t item_end[] = {0xfffe,0xe00d};
    00776     _os.write((char*)&item_end, 4);
    00777     uint32_t zero = 0x0;
    00778     _os.write((char*)&zero, 4);
    00779     uint16_t seq_end[] = {0xfffe, 0xe0dd};
    00780     _os.write((char*)&seq_end, 4);
    00781     _os.write((char*)&zero, 4);
    00782     }
    00783 };
    00784 */
    00785
    00791 } // namespace gdcm
    00792
    00793 #endif //GDCMATTRIBUTE_H