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