GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

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