1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #ifndef GDCMATTRIBUTE_H
15 #define GDCMATTRIBUTE_H
16 
17 #include "gdcmTypes.h"
18 #include "gdcmVR.h"
19 #include "gdcmTagToType.h"
20 #include "gdcmVM.h"
21 #include "gdcmElement.h"
22 #include "gdcmDataElement.h"
23 #include "gdcmDataSet.h"
24 #include "gdcmStaticAssert.h"
25 
26 #include <string>
27 #include <vector>
28 #include <sstream>
29 
30 namespace gdcm_ns
31 {
32 
33 struct void_;
34 
35 // Declaration, also serve as forward declaration
36 template<int T> class VRVLSize;
37 
38 // Implementation when VL is coded on 16 bits:
39 template<> class VRVLSize<0> {
40 public:
Read(std::istream & _is)41   static inline uint16_t Read(std::istream &_is) {
42     uint16_t l;
43     _is.read((char*)&l, 2);
44     return l;
45     }
46 
Write(std::ostream & os)47   static inline void Write(std::ostream &os)  { (void)os;
48     }
49 };
50 // Implementation when VL is coded on 32 bits:
51 template<> class VRVLSize<1> {
52 public:
Read(std::istream & _is)53   static inline uint32_t Read(std::istream &_is) {
54     char dummy[2];
55     _is.read(dummy, 2);
56 
57     uint32_t l;
58     _is.read((char*)&l, 4);
59     return l;
60     }
61 
Write(std::ostream & os)62   static inline void Write(std::ostream &os)  { (void)os;
63     }
64 };
65 
66 /**
67  * \brief Attribute class
68  * This class use template metaprograming tricks to let the user know when the template
69  * instanciation does not match the public dictionary.
70  *
71  * Typical example that compile is:
72  * Attribute<0x0008,0x9007> a = {"ORIGINAL","PRIMARY","T1","NONE"};
73  *
74  * Examples that will NOT compile are:
75  *
76  * Attribute<0x0018,0x1182, VR::IS, VM::VM1> fd1 = {}; // not enough parameters
77  * Attribute<0x0018,0x1182, VR::IS, VM::VM2> fd2 = {0,1,2}; // too many initializers
78  * Attribute<0x0018,0x1182, VR::IS, VM::VM3> fd3 = {0,1,2}; // VM3 is not valid
79  * Attribute<0x0018,0x1182, VR::UL, VM::VM2> fd3 = {0,1}; // UL is not valid VR
80  */
81 template<uint16_t Group, uint16_t Element,
82    long long TVR = TagToType<Group, Element>::VRType, // can the user override this value ?
83    int TVM = TagToType<Group, Element>::VMType // can the user override this value ?
84    /*typename SQAttribute = void_*/ > // if only I had variadic template...
85 class Attribute
86 {
87 public:
88   typedef typename VRToType<TVR>::Type ArrayType;
89   enum { VMType = VMToLength<TVM>::Length };
90   ArrayType Internal[VMToLength<TVM>::Length];
91 
92   // Make sure that user specified VR/VM are compatible with the public dictionary:
93   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
94   GDCM_STATIC_ASSERT( ((VM::VMType)TVM & (VM::VMType)(TagToType<Group, Element>::VMType)) );
95   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TVM == VM::VM1) )
96                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
97 
GetTag()98   static Tag GetTag() { return Tag(Group,Element); }
GetVR()99   static VR  GetVR()  { return (VR::VRType)TVR; }
GetVM()100   static VM  GetVM()  { return (VM::VMType)TVM; }
101 
102   // The following two methods do make sense only in case of public element,
103   // when the template is intanciated with private element the VR/VM are simply
104   // defaulted to allow everything (see gdcmTagToType.h default template for TagToType)
GetDictVR()105   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
GetDictVM()106   static VM  GetDictVM() { return (VM::VMType)(TagToType<Group, Element>::VMType); }
107 
108   // Some extra dummy checks:
109   // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one.
110 
GetNumberOfValues()111   unsigned int GetNumberOfValues() const {
112     return VMToLength<TVM>::Length;
113   }
114   // Implementation of Print is common to all Mode (ASCII/Binary)
115   // TODO: Can we print a \ when in ASCII...well I don't think so
116   // it would mean we used a bad VM then, right ?
Print(std::ostream & os)117   void Print(std::ostream &os) const {
118     os << GetTag() << " ";
119     os << TagToType<Group,Element>::GetVRString()  << " ";
120     os << TagToType<Group,Element>::GetVMString()  << " ";
121     os << Internal[0]; // VM is at least garantee to be one
122     for(unsigned int i=1; i<GetNumberOfValues(); ++i)
123       os << "," << Internal[i];
124     }
125 
126   // copy:
127   //ArrayType GetValue(unsigned int idx = 0) {
128   //  assert( idx < GetNumberOfValues() );
129   //  return Internal[idx];
130   //}
131   //ArrayType operator[] (unsigned int idx) {
132   //  return GetValue(idx);
133   //}
134   // FIXME: is this always a good idea ?
135   // I do not think so, I prefer operator
136   //operator ArrayType () const { return Internal[0]; }
137 
138   bool operator==(const Attribute &att) const
139     {
140     return std::equal(Internal, Internal+GetNumberOfValues(),
141       att.GetValues());
142     }
143   bool operator!=(const Attribute &att) const
144     {
145     return !std::equal(Internal, Internal+GetNumberOfValues(),
146       att.GetValues());
147     }
148   bool operator<(const Attribute &att) const
149     {
150     return std::lexicographical_compare(Internal, Internal+GetNumberOfValues(),
151       att.GetValues(), att.GetValues() + att.GetNumberOfValues() );
152     }
153 
154   ArrayType &GetValue(unsigned int idx = 0) {
155     assert( idx < GetNumberOfValues() );
156     return Internal[idx];
157   }
158   ArrayType & operator[] (unsigned int idx) {
159     return GetValue(idx);
160   }
161   // const reference
162   ArrayType const &GetValue(unsigned int idx = 0) const {
163     assert( idx < GetNumberOfValues() );
164     return Internal[idx];
165   }
166   ArrayType const & operator[] (unsigned int idx) const {
167     return GetValue(idx);
168   }
169   void SetValue(ArrayType v, unsigned int idx = 0) {
170     assert( idx < GetNumberOfValues() );
171     Internal[idx] = v;
172   }
173   void SetValues(const ArrayType* array, unsigned int numel = VMType ) {
174     assert( array && numel && numel == GetNumberOfValues() );
175     // std::copy is smarted than a memcpy, and will call memcpy when POD type
176     std::copy(array, array+numel, Internal);
177   }
GetValues()178   const ArrayType* GetValues() const {
179     return Internal;
180   }
181 
182   // API to talk to the run-time layer: gdcm::DataElement
GetAsDataElement()183   DataElement GetAsDataElement() const {
184     DataElement ret( GetTag() );
185     std::ostringstream os;
186     // os.imbue(std::locale::classic()); // This is not required AFAIK
187     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
188       GetNumberOfValues(),os);
189     ret.SetVR( GetVR() );
190     assert( ret.GetVR() != VR::SQ );
191     if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
192       {
193       if( GetVR() != VR::UI )
194         {
195         if( os.str().size() % 2 )
196           {
197           os << " ";
198           }
199         }
200       }
201     VL::Type osStrSize = (VL::Type)os.str().size();
202     ret.SetByteValue( os.str().c_str(), osStrSize );
203     return ret;
204   }
205 
SetFromDataElement(DataElement const & de)206   void SetFromDataElement(DataElement const &de) {
207     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
208     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 || GetTag().GetGroup() == 0x5000 );
209     assert( GetVR() != VR::INVALID );
210     assert( GetVR().Compatible( de.GetVR() ) || de.GetVR() == VR::INVALID ); // In case of VR::INVALID cannot use the & operator
211     if( de.IsEmpty() ) return;
212     const ByteValue *bv = de.GetByteValue();
213 #ifdef GDCM_WORDS_BIGENDIAN
214     if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
215 #else
216     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
217 #endif
218       {
219       SetByteValue(bv);
220       }
221     else
222       {
223       SetByteValueNoSwap(bv);
224       }
225   }
Set(DataSet const & ds)226   void Set(DataSet const &ds) {
227     SetFromDataElement( ds.GetDataElement( GetTag() ) );
228   }
SetFromDataSet(DataSet const & ds)229   void SetFromDataSet(DataSet const &ds) {
230     if( ds.FindDataElement( GetTag() ) &&
231       !ds.GetDataElement( GetTag() ).IsEmpty() )
232       {
233       SetFromDataElement( ds.GetDataElement( GetTag() ) );
234       }
235   }
236 protected:
SetByteValueNoSwap(const ByteValue * bv)237   void SetByteValueNoSwap(const ByteValue *bv) {
238     if( !bv ) return; // That would be bad...
239     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
240     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
241     //  {
242     //  // always do a copy !
243     //  SetValues(bv->GetPointer(), bv->GetLength());
244     //  }
245     //else
246       {
247       std::stringstream ss;
248       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
249       ss.str( s );
250       EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
251         GetNumberOfValues(),ss);
252       }
253   }
SetByteValue(const ByteValue * bv)254   void SetByteValue(const ByteValue *bv) {
255     if( !bv ) return; // That would be bad...
256     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
257     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
258     //  {
259     //  // always do a copy !
260     //  SetValues(bv->GetPointer(), bv->GetLength());
261     //  }
262     //else
263       {
264       std::stringstream ss;
265       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
266       ss.str( s );
267       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
268         GetNumberOfValues(),ss);
269       }
270   }
271 #if 0 // TODO  FIXME the implicit way:
272   // explicit:
273   void Read(std::istream &_is) {
274     const uint16_t cref[] = { Group, Element };
275     uint16_t c[2];
276     _is.read((char*)&c, sizeof(c));
277     assert( c[0] == cref[0] && c[1] == cref[1] );
278     char vr[2];
279     _is.read(vr, 2); // Check consistency ?
280     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
281     uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is);
282     l /= sizeof( typename VRToType<TVR>::Type );
283     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
284       l,_is);
285   }
286   void Write(std::ostream &_os) const {
287     uint16_t c[] = { Group, Element };
288     _os.write((char*)&c, 4);
289     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
290     _os.write((char*)&l, 4);
291     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
292       GetLength(),_os);
293     }
294   void Read(std::istream &_is) {
295     uint16_t cref[] = { Group, Element };
296     uint16_t c[2];
297     _is.read((char*)&c, 4);
298     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
299     uint32_t l;
300     _is.read((char*)&l, 4);
301     l /= sizeof( typename VRToType<TVR>::Type );
302      return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
303       l,_is);
304     }
305   void Write(std::ostream &_os) const {
306     uint16_t c[] = { Group, Element };
307     _os.write((char*)&c, 4);
308     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
309     _os.write((char*)&l, 4);
310     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
311       GetLength(),_os);
312     }
313 #endif
314 
315 };
316 
317 template<uint16_t Group, uint16_t Element, long long TVR >
318 class Attribute<Group,Element,TVR,VM::VM1>
319 {
320 public:
321   typedef typename VRToType<TVR>::Type ArrayType;
322   enum { VMType = VMToLength<VM::VM1>::Length };
323   //ArrayType Internal[VMToLength<TVM>::Length];
324   ArrayType Internal;
325   GDCM_STATIC_ASSERT( VMToLength<VM::VM1>::Length == 1 );
326 
327   // Make sure that user specified VR/VM are compatible with the public dictionary:
328   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
329   GDCM_STATIC_ASSERT( ((VM::VMType)VM::VM1 & (VM::VMType)(TagToType<Group, Element>::VMType)) );
330   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)VM::VM1 == VM::VM1) )
331                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
332 
GetTag()333   static Tag GetTag() { return Tag(Group,Element); }
GetVR()334   static VR  GetVR()  { return (VR::VRType)TVR; }
GetVM()335   static VM  GetVM()  { return (VM::VMType)VM::VM1; }
336 
337   // The following two methods do make sense only in case of public element,
338   // when the template is intanciated with private element the VR/VM are simply
339   // defaulted to allow everything (see gdcmTagToType.h default template for TagToType)
GetDictVR()340   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
GetDictVM()341   static VM  GetDictVM() { return (VM::VMType)(TagToType<Group, Element>::VMType); }
342 
343   // Some extra dummy checks:
344   // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one.
345 
GetNumberOfValues()346   unsigned int GetNumberOfValues() const {
347     return VMToLength<VM::VM1>::Length;
348   }
349   // Implementation of Print is common to all Mode (ASCII/Binary)
350   // TODO: Can we print a \ when in ASCII...well I don't think so
351   // it would mean we used a bad VM then, right ?
Print(std::ostream & os)352   void Print(std::ostream &os) const {
353     os << GetTag() << " ";
354     os << TagToType<Group,Element>::GetVRString()  << " ";
355     os << TagToType<Group,Element>::GetVMString()  << " ";
356     os << Internal; // VM is at least garantee to be one
357   }
358   // copy:
359   //ArrayType GetValue(unsigned int idx = 0) {
360   //  assert( idx < GetNumberOfValues() );
361   //  return Internal[idx];
362   //}
363   //ArrayType operator[] (unsigned int idx) {
364   //  return GetValue(idx);
365   //}
366   // FIXME: is this always a good idea ?
367   // I do not think so, I prefer operator
368   //operator ArrayType () const { return Internal[0]; }
369 
370   bool operator==(const Attribute &att) const
371     {
372     return std::equal(&Internal, &Internal+GetNumberOfValues(),
373       att.GetValues());
374     }
375   bool operator!=(const Attribute &att) const
376     {
377     return !std::equal(&Internal, &Internal+GetNumberOfValues(),
378       att.GetValues());
379     }
380   bool operator<(const Attribute &att) const
381     {
382     return std::lexicographical_compare(&Internal, &Internal+GetNumberOfValues(),
383       att.GetValues(), att.GetValues() + att.GetNumberOfValues() );
384     }
385 
GetValue()386   ArrayType &GetValue() {
387 //    assert( idx < GetNumberOfValues() );
388     return Internal;
389   }
390 //  ArrayType & operator[] (unsigned int idx) {
391 //    return GetValue(idx);
392 //  }
393   // const reference
GetValue()394   ArrayType const &GetValue() const {
395     //assert( idx < GetNumberOfValues() );
396     return Internal;
397   }
398   //ArrayType const & operator[] () const {
399   //  return GetValue();
400   //}
SetValue(ArrayType v)401   void SetValue(ArrayType v) {
402 //    assert( idx < GetNumberOfValues() );
403     Internal = v;
404   }
405 /*  void SetValues(const ArrayType* array, unsigned int numel = VMType ) {
406     assert( array && numel && numel == GetNumberOfValues() );
407     // std::copy is smarted than a memcpy, and will call memcpy when POD type
408     std::copy(array, array+numel, Internal);
409   }
410 */
411 
412   // FIXME Should we remove this function ?
GetValues()413   const ArrayType* GetValues() const {
414     return &Internal;
415   }
416 
417   // API to talk to the run-time layer: gdcm::DataElement
GetAsDataElement()418   DataElement GetAsDataElement() const {
419     DataElement ret( GetTag() );
420     std::ostringstream os;
421     // os.imbue(std::locale::classic()); // This is not required AFAIK
422     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(&Internal,
423       GetNumberOfValues(),os);
424     ret.SetVR( GetVR() );
425     assert( ret.GetVR() != VR::SQ );
426     if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
427       {
428       if( GetVR() != VR::UI )
429         {
430         if( os.str().size() % 2 )
431           {
432           os << " ";
433           }
434         }
435       }
436     VL::Type osStrSize = (VL::Type)os.str().size();
437     ret.SetByteValue( os.str().c_str(), osStrSize );
438     return ret;
439   }
440 
SetFromDataElement(DataElement const & de)441   void SetFromDataElement(DataElement const &de) {
442     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
443     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 || GetTag().GetGroup() == 0x5000 );
444     assert( GetVR() != VR::INVALID );
445     assert( GetVR().Compatible( de.GetVR() ) || de.GetVR() == VR::INVALID ); // In case of VR::INVALID cannot use the & operator
446     if( de.IsEmpty() ) return;
447     const ByteValue *bv = de.GetByteValue();
448 #ifdef GDCM_WORDS_BIGENDIAN
449     if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
450 #else
451     if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
452 #endif
453       {
454       SetByteValue(bv);
455       }
456     else
457       {
458       SetByteValueNoSwap(bv);
459       }
460   }
Set(DataSet const & ds)461   void Set(DataSet const &ds) {
462     SetFromDataElement( ds.GetDataElement( GetTag() ) );
463   }
SetFromDataSet(DataSet const & ds)464   void SetFromDataSet(DataSet const &ds) {
465     if( ds.FindDataElement( GetTag() ) &&
466       !ds.GetDataElement( GetTag() ).IsEmpty() )
467       {
468       SetFromDataElement( ds.GetDataElement( GetTag() ) );
469       }
470   }
471 protected:
SetByteValueNoSwap(const ByteValue * bv)472   void SetByteValueNoSwap(const ByteValue *bv) {
473     if( !bv ) return; // That would be bad...
474     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
475     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
476     //  {
477     //  // always do a copy !
478     //  SetValues(bv->GetPointer(), bv->GetLength());
479     //  }
480     //else
481       {
482       std::stringstream ss;
483       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
484       ss.str( s );
485       EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(&Internal,
486         GetNumberOfValues(),ss);
487       }
488   }
SetByteValue(const ByteValue * bv)489   void SetByteValue(const ByteValue *bv) {
490     if( !bv ) return; // That would be bad...
491     assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty
492     //if( VRToEncoding<TVR>::Mode == VR::VRBINARY )
493     //  {
494     //  // always do a copy !
495     //  SetValues(bv->GetPointer(), bv->GetLength());
496     //  }
497     //else
498       {
499       std::stringstream ss;
500       std::string s = std::string( bv->GetPointer(), bv->GetLength() );
501       ss.str( s );
502       EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(&Internal,
503         GetNumberOfValues(),ss);
504       }
505   }
506 #if 0 // TODO  FIXME the implicit way:
507   // explicit:
508   void Read(std::istream &_is) {
509     const uint16_t cref[] = { Group, Element };
510     uint16_t c[2];
511     _is.read((char*)&c, sizeof(c));
512     assert( c[0] == cref[0] && c[1] == cref[1] );
513     char vr[2];
514     _is.read(vr, 2); // Check consistency ?
515     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
516     uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is);
517     l /= sizeof( typename VRToType<TVR>::Type );
518     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
519       l,_is);
520   }
521   void Write(std::ostream &_os) const {
522     uint16_t c[] = { Group, Element };
523     _os.write((char*)&c, 4);
524     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
525     _os.write((char*)&l, 4);
526     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
527       GetLength(),_os);
528     }
529   void Read(std::istream &_is) {
530     uint16_t cref[] = { Group, Element };
531     uint16_t c[2];
532     _is.read((char*)&c, 4);
533     const uint32_t lref = GetLength() * sizeof( typename VRToType<TVR>::Type );
534     uint32_t l;
535     _is.read((char*)&l, 4);
536     l /= sizeof( typename VRToType<TVR>::Type );
537      return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
538       l,_is);
539     }
540   void Write(std::ostream &_os) const {
541     uint16_t c[] = { Group, Element };
542     _os.write((char*)&c, 4);
543     uint32_t l = GetLength() * sizeof( typename VRToType<TVR>::Type );
544     _os.write((char*)&l, 4);
545     return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
546       GetLength(),_os);
547     }
548 #endif
549 
550 };
551 
552 // No need to repeat default template arg, since primary template
553 // will be used to generate the default arguments
554 template<uint16_t Group, uint16_t Element, long long TVR >
555 class Attribute<Group,Element,TVR,VM::VM1_n>
556 {
557 public:
558   typedef typename VRToType<TVR>::Type ArrayType;
559 
560   // Make sure that user specified VR/VM are compatible with the public dictionary:
561   GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType<Group, Element>::VRType)) );
562   GDCM_STATIC_ASSERT( (VM::VM1_n & (VM::VMType)(TagToType<Group, Element>::VMType)) );
563   GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TagToType<Group,Element>::VMType == VM::VM1) )
564                     || !((VR::VRType)TVR & VR::VR_VM1) ) );
565 
GetTag()566   static Tag GetTag() { return Tag(Group,Element); }
GetVR()567   static VR  GetVR()  { return (VR::VRType)TVR; }
GetVM()568   static VM  GetVM()  { return VM::VM1_n; }
569 
GetDictVR()570   static VR  GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
GetDictVM()571   static VM  GetDictVM() { return GetVM(); }
572 
573   // This the way to prevent default initialization
Attribute()574   explicit Attribute() { Internal=nullptr; Length=0; Own = true; }
~Attribute()575   ~Attribute() {
576     if( Own ) {
577       delete[] Internal;
578     }
579     Internal = nullptr; // paranoid
580   }
581 
GetNumberOfValues()582   unsigned int GetNumberOfValues() const { return Length; }
583 
SetNumberOfValues(unsigned int numel)584   void SetNumberOfValues(unsigned int numel)
585     {
586     SetValues(nullptr, numel, true);
587     }
588 
GetValues()589   const ArrayType* GetValues() const {
590     return Internal;
591   }
Print(std::ostream & os)592   void Print(std::ostream &os) const {
593     os << GetTag() << " ";
594     os << GetVR()  << " ";
595     os << GetVM()  << " ";
596     os << Internal[0]; // VM is at least garantee to be one
597     for(unsigned int i=1; i<GetNumberOfValues(); ++i)
598       os << "," << Internal[i];
599     }
600   ArrayType &GetValue(unsigned int idx = 0) {
601     assert( idx < GetNumberOfValues() );
602     return Internal[idx];
603   }
604   ArrayType &operator[] (unsigned int idx) {
605     return GetValue(idx);
606   }
607   // const reference
608   ArrayType const &GetValue(unsigned int idx = 0) const {
609     assert( idx < GetNumberOfValues() );
610     return Internal[idx];
611   }
612   ArrayType const & operator[] (unsigned int idx) const {
613     return GetValue(idx);
614   }
SetValue(unsigned int idx,ArrayType v)615   void SetValue(unsigned int idx, ArrayType v) {
616     assert( idx < GetNumberOfValues() );
617     Internal[idx] = v;
618   }
SetValue(ArrayType v)619   void SetValue(ArrayType v) { SetValue(0, v); }
620 
621   void SetValues(const ArrayType *array, unsigned int numel, bool own = false)
622     {
623     if( Internal ) // were we used before ?
624       {
625       // yes !
626       if( Own ) delete[] Internal;
627       Internal = nullptr;
628       }
629     Own = own;
630     Length = numel;
631     assert( Internal == 0 );
632     if( own ) // make a copy:
633       {
634       Internal = new ArrayType[numel];
635       if( array && numel )
636         std::copy(array, array+numel, Internal);
637       }
638     else // pass pointer
639       {
640       Internal = const_cast<ArrayType*>(array);
641       }
642     // postcondition
643     assert( numel == GetNumberOfValues() );
644     }
645 
GetAsDataElement()646   DataElement GetAsDataElement() const {
647     DataElement ret( GetTag() );
648     std::ostringstream os;
649     if( Internal )
650       {
651       EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
652         GetNumberOfValues(),os);
653       if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
654         {
655         if( GetVR() != VR::UI )
656           {
657           if( os.str().size() % 2 )
658             {
659             os << " ";
660             }
661           }
662         }
663       }
664     ret.SetVR( GetVR() );
665     assert( ret.GetVR() != VR::SQ );
666     VL::Type osStrSize = (VL::Type) os.str().size();
667     ret.SetByteValue( os.str().c_str(), osStrSize);
668     return ret;
669   }
SetFromDataElement(DataElement const & de)670   void SetFromDataElement(DataElement const &de) {
671     // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
672     assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000
673       || GetTag().GetGroup() == 0x5000 );
674     assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator
675     assert( !de.IsEmpty() );
676     const ByteValue *bv = de.GetByteValue();
677     SetByteValue(bv);
678   }
Set(DataSet const & ds)679   void Set(DataSet const &ds) {
680     SetFromDataElement( ds.GetDataElement( GetTag() ) );
681   }
SetFromDataSet(DataSet const & ds)682   void SetFromDataSet(DataSet const &ds) {
683     if( ds.FindDataElement( GetTag() ) &&
684       !ds.GetDataElement( GetTag() ).IsEmpty() )
685       {
686       SetFromDataElement( ds.GetDataElement( GetTag() ) );
687       }
688   }
689 protected:
SetByteValue(const ByteValue * bv)690   void SetByteValue(const ByteValue *bv) {
691     assert( bv ); // FIXME
692     std::stringstream ss;
693     std::string s = std::string( bv->GetPointer(), bv->GetLength() );
694     Length = bv->GetLength(); // HACK FIXME
695     ss.str( s );
696     ArrayType *internal;
697     ArrayType buffer[256];
698     if( bv->GetLength() < 256 )
699       {
700       internal = buffer;
701       }
702     else
703       {
704       internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation
705       }
706     EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss);
707     SetValues( internal, Length, true );
708     if( !(bv->GetLength() < 256) )
709       {
710       delete[] internal;
711       }
712     //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
713     //  GetNumberOfValues(),ss);
714   }
715 
716 private:
717   ArrayType *Internal;
718   unsigned int Length;
719   bool Own : 1;
720 };
721 
722 template<uint16_t Group, uint16_t Element, long long TVR>
723 class Attribute<Group,Element,TVR,VM::VM1_3> : public Attribute<Group,Element,TVR,VM::VM1_n>
724 {
725 public:
GetVM()726   VM  GetVM() const { return VM::VM1_3; }
727 };
728 
729 template<uint16_t Group, uint16_t Element, long long TVR>
730 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n>
731 {
732 public:
GetVM()733   VM  GetVM() const { return VM::VM1_8; }
734 };
735 
736 template<uint16_t Group, uint16_t Element, long long TVR>
737 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
738 {
739 public:
GetVM()740   VM  GetVM() const { return VM::VM2_n; }
741 };
742 
743 template<uint16_t Group, uint16_t Element, long long TVR>
744 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n>
745 {
746 public:
GetVM()747   static VM  GetVM() { return VM::VM2_2n; }
748 };
749 
750 template<uint16_t Group, uint16_t Element, long long TVR>
751 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
752 {
753 public:
GetVM()754   static VM  GetVM() { return VM::VM3_n; }
755 };
756 
757 template<uint16_t Group, uint16_t Element, long long TVR>
758 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n>
759 {
760 public:
GetVM()761   static VM  GetVM() { return VM::VM3_3n; }
762 };
763 
764 
765 // For particular case for ASCII string
766 // WARNING: This template explicitly instanciates a particular
767 // EncodingImplementation THEREFORE it is required to be declared after the
768 // EncodingImplementation is needs (doh!)
769 #if 0
770 template<int TVM>
771 class Attribute<TVM>
772 {
773 public:
774   Attribute(const char array[])
775     {
776     unsigned int i = 0;
777     const char sep = '\\';
778     std::string sarray = array;
779     std::string::size_type pos1 = 0;
780     std::string::size_type pos2 = sarray.find(sep, pos1+1);
781     while(pos2 != std::string::npos)
782       {
783       Internal[i++] = sarray.substr(pos1, pos2-pos1);
784       pos1 = pos2+1;
785       pos2 = sarray.find(sep, pos1+1);
786       }
787     Internal[i] = sarray.substr(pos1, pos2-pos1);
788     // Shouldn't we do the contrary, since we know how many separators
789     // (and default behavior is to discard anything after the VM declared
790     assert( GetLength()-1 == i );
791     }
792 
793   unsigned long GetLength() const {
794     return VMToLength<TVM>::Length;
795   }
796   // Implementation of Print is common to all Mode (ASCII/Binary)
797   void Print(std::ostream &_os) const {
798     _os << Internal[0]; // VM is at least garantee to be one
799     for(int i=1; i<VMToLength<TVM>::Length; ++i)
800       _os << "," << Internal[i];
801     }
802 
803   void Read(std::istream &_is) {
804     EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
805     }
806   void Write(std::ostream &_os) const {
807     EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
808     }
809 private:
810   typename String Internal[VMToLength<TVM>::Length];
811 };
812 
813 template< int TVM>
814 class Attribute<VR::PN, TVM> : public StringAttribute<TVM>
815 {
816 };
817 #endif
818 
819 #if 0
820 
821 // Implementation for the undefined length (dynamically allocated array)
822 template<int TVR>
823 class Attribute<TVR, VM::VM1_n>
824 {
825 public:
826   // This the way to prevent default initialization
827   explicit Attribute() { Internal=0; Length=0; }
828   ~Attribute() {
829     delete[] Internal;
830     Internal = 0;
831   }
832 
833   // Length manipulation
834   // SetLength should really be protected anyway...all operation
835   // should go through SetArray
836   unsigned long GetLength() const { return Length; }
837   typedef typename VRToType<TVR>::Type ArrayType;
838   void SetLength(unsigned long len) {
839     const unsigned int size = sizeof(ArrayType);
840     if( len ) {
841       if( len > Length ) {
842         // perform realloc
843         assert( (len / size) * size == len );
844         ArrayType *internal = new ArrayType[len / size];
845         memcpy(internal, Internal, Length * size);
846         delete[] Internal;
847         Internal = internal;
848         }
849       }
850     Length = len / size;
851   }
852 
853   // If save is set to zero user should not delete the pointer
854   //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
855   void SetArray(const ArrayType *array, unsigned long len,
856     bool save = false) {
857     if( save ) {
858       SetLength(len); // realloc
859       memcpy(Internal, array, len/*/sizeof(ArrayType)*/);
860       }
861     else {
862       // TODO rewrite this stupid code:
863       Length = len;
864       //Internal = array;
865       assert(0);
866       }
867   }
868   // Implementation of Print is common to all Mode (ASCII/Binary)
869   void Print(std::ostream &_os) const {
870     assert( Length );
871     assert( Internal );
872     _os << Internal[0]; // VM is at least garantee to be one
873     const unsigned long length = GetLength() < 25 ? GetLength() : 25;
874     for(unsigned long i=1; i<length; ++i)
875       _os << "," << Internal[i];
876     }
877   void Read(std::istream &_is) {
878     EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
879       GetLength(),_is);
880     }
881   void Write(std::ostream &_os) const {
882     EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
883       GetLength(),_os);
884     }
885 
886   Attribute(const Attribute&_val) {
887     if( this != &_val) {
888       *this = _val;
889       }
890     }
891 
892   Attribute &operator=(const Attribute &_val) {
893     Length = 0; // SYITF
894     Internal = 0;
895     SetArray(_val.Internal, _val.Length, true);
896     return *this;
897     }
898 
899 private:
900   typename VRToType<TVR>::Type *Internal;
901   unsigned long Length; // unsigned int ??
902 };
903 
904 //template <int TVM = VM::VM1_n>
905 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {};
906 
907 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
908 template<int TVR>
909 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n>
910 {
911 public:
912   typedef Attribute<TVR, VM::VM1_n> Parent;
913   void SetLength(int len) {
914     if( len <= 1 ) return;
915     Parent::SetLength(len);
916   }
917 };
918 template<int TVR>
919 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n>
920 {
921 public:
922   typedef Attribute<TVR, VM::VM2_n> Parent;
923   void SetLength(int len) {
924     if( len % 2 ) return;
925     Parent::SetLength(len);
926   }
927 };
928 template<int TVR>
929 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n>
930 {
931 public:
932   typedef Attribute<TVR, VM::VM1_n> Parent;
933   void SetLength(int len) {
934     if( len <= 2 ) return;
935     Parent::SetLength(len);
936   }
937 };
938 template<int TVR>
939 class Attribute<TVR, VM::VM3_3n> : public Attribute<TVR, VM::VM3_n>
940 {
941 public:
942   typedef Attribute<TVR, VM::VM3_n> Parent;
943   void SetLength(int len) {
944     if( len % 3 ) return;
945     Parent::SetLength(len);
946   }
947 };
948 
949 
950 //template<int T> struct VRToLength;
951 //template <> struct VRToLength<VR::AS>
952 //{ enum { Length  = VM::VM1 }; }
953 //template<>
954 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length >
955 
956 // only 0010 1010 AS 1 Patient's Age
957 template<>
958 class Attribute<VR::AS, VM::VM5>
959 {
960 public:
961   char Internal[VMToLength<VM::VM5>::Length];
962   void Print(std::ostream &_os) const {
963     _os << Internal;
964     }
965 };
966 
967 template <>
968 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {};
969 // Make it impossible to compile any other cases:
970 template <int TVM> class Attribute<VR::OB, TVM>;
971 
972 // Same for OW:
973 template <>
974 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {};
975 // Make it impossible to compile any other cases:
976 template <int TVM> class Attribute<VR::OW, TVM>;
977 #endif
978 
979 #if 0
980 template<>
981 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1>
982 {
983 public:
984   char *Internal;
985   unsigned long Length; // unsigned int ??
986 
987   void Print(std::ostream &_os) const {
988     _os << Internal[0];
989     }
990   void SetBytes(char *bytes, unsigned long length) {
991     Internal = bytes;
992     Length = length;
993   }
994   void Read(std::istream &_is) {
995      uint16_t c[2];
996     _is.read((char*)&c, 4);
997     uint32_t l;
998     _is.read((char*)&l, 4);
999     Length = l;
1000     _is.read( Internal, Length );
1001     }
1002   void Write(std::ostream &_os) const {
1003      uint16_t c[] = {0x7fe0, 0x0010};
1004     _os.write((char*)&c, 4);
1005     _os.write((char*)&Length, 4);
1006     _os.write( Internal, Length );
1007     }
1008 };
1009 #endif
1010 
1011 /*
1012 // Removing Attribute for SQ for now...
1013 template<uint16_t Group, uint16_t Element, typename SQA>
1014 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA>
1015 {
1016 public:
1017   SQA sqa;
1018   void Print(std::ostream &_os) const {
1019     _os << Tag(Group,Element);
1020     sqa.Print(_os << std::endl << '\t');
1021     }
1022  void Write(std::ostream &_os) const {
1023     uint16_t c[] = {Group, Element};
1024     _os.write((char*)&c, 4);
1025     uint32_t undef = 0xffffffff;
1026     _os.write((char*)&undef, 4);
1027     uint16_t item_beg[] = {0xfffe,0xe000};
1028     _os.write((char*)&item_beg, 4);
1029     _os.write((char*)&undef, 4);
1030     sqa.Write(_os);
1031     uint16_t item_end[] = {0xfffe,0xe00d};
1032     _os.write((char*)&item_end, 4);
1033     uint32_t zero = 0x0;
1034     _os.write((char*)&zero, 4);
1035     uint16_t seq_end[] = {0xfffe, 0xe0dd};
1036     _os.write((char*)&seq_end, 4);
1037     _os.write((char*)&zero, 4);
1038     }
1039 };
1040 */
1041 
1042 /**
1043  * \example PatchFile.cxx
1044  * This is a C++ example on how to use gdcm::Attribute
1045  */
1046 
1047 } // namespace gdcm_ns
1048 
1049 #endif //GDCMATTRIBUTE_H
1050