GDCM  2.2.0
gdcmAttribute.h
Go to the documentation of this file.
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
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:
41  static inline uint16_t Read(std::istream &_is) {
42  uint16_t l;
43  _is.read((char*)&l, 2);
44  return l;
45  }
46 
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:
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 
62  static inline void Write(std::ostream &os) { (void)os;
63  }
64 };
65 
81 template<uint16_t Group, uint16_t Element,
82  int 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 
98  static Tag GetTag() { return Tag(Group,Element); }
99  static VR GetVR() { return (VR::VRType)TVR; }
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)
105  static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
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 
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 ?
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  }
178  const ArrayType* GetValues() const {
179  return Internal;
180  }
181 
182  // API to talk to the run-time layer: gdcm::DataElement
184  DataElement ret( GetTag() );
185  std::ostringstream os;
186  // os.imbue(std::locale::classic()); // This is not required AFAIK
188  GetNumberOfValues(),os);
189  ret.SetVR( GetVR() );
190  assert( ret.GetVR() != VR::SQ );
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 
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  }
226  void Set(DataSet const &ds) {
228  }
229  void SetFromDataSet(DataSet const &ds) {
230  if( ds.FindDataElement( GetTag() ) &&
231  !ds.GetDataElement( GetTag() ).IsEmpty() )
232  {
234  }
235  }
236 protected:
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 );
251  GetNumberOfValues(),ss);
252  }
253  }
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 );
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 );
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);
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 );
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);
311  GetLength(),_os);
312  }
313 #endif
314 
315 };
316 
317 template<uint16_t Group, uint16_t Element, int 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];
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 
333  static Tag GetTag() { return Tag(Group,Element); }
334  static VR GetVR() { return (VR::VRType)TVR; }
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)
340  static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
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 
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 ?
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 
387 // assert( idx < GetNumberOfValues() );
388  return Internal;
389  }
390 // ArrayType & operator[] (unsigned int idx) {
391 // return GetValue(idx);
392 // }
393  // const reference
394  ArrayType const &GetValue() const {
395  //assert( idx < GetNumberOfValues() );
396  return Internal;
397  }
398  //ArrayType const & operator[] () const {
399  // return GetValue();
400  //}
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 ?
413  const ArrayType* GetValues() const {
414  return &Internal;
415  }
416 
417  // API to talk to the run-time layer: gdcm::DataElement
419  DataElement ret( GetTag() );
420  std::ostringstream os;
421  // os.imbue(std::locale::classic()); // This is not required AFAIK
423  GetNumberOfValues(),os);
424  ret.SetVR( GetVR() );
425  assert( ret.GetVR() != VR::SQ );
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 
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  }
461  void Set(DataSet const &ds) {
463  }
464  void SetFromDataSet(DataSet const &ds) {
465  if( ds.FindDataElement( GetTag() ) &&
466  !ds.GetDataElement( GetTag() ).IsEmpty() )
467  {
469  }
470  }
471 protected:
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 );
486  GetNumberOfValues(),ss);
487  }
488  }
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 );
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 );
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);
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 );
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);
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, int 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 
566  static Tag GetTag() { return Tag(Group,Element); }
567  static VR GetVR() { return (VR::VRType)TVR; }
568  static VM GetVM() { return VM::VM1_n; }
569 
570  static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); }
571  static VM GetDictVM() { return GetVM(); }
572 
573  // This the way to prevent default initialization
574  explicit Attribute() { Internal=0; Length=0; Own = true; }
576  if( Own ) {
577  delete[] Internal;
578  }
579  Internal = 0; // paranoid
580  }
581 
582  unsigned int GetNumberOfValues() const { return Length; }
583 
584  void SetNumberOfValues(unsigned int numel)
585  {
586  SetValues(NULL, numel, true);
587  }
588 
589  const ArrayType* GetValues() const {
590  return Internal;
591  }
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  }
615  void SetValue(unsigned int idx, ArrayType v) {
616  assert( idx < GetNumberOfValues() );
617  Internal[idx] = v;
618  }
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 = 0;
628  }
629  Own = own;
630  Length = numel;
631  assert( Internal == 0 );
632  if( own ) // make a copy:
633  {
634  assert( /*array &&*/ numel );
635  Internal = new ArrayType[numel];
636  if( array && numel )
637  std::copy(array, array+numel, Internal);
638  }
639  else // pass pointer
640  {
641  Internal = const_cast<ArrayType*>(array);
642  }
643  // postcondition
644  assert( numel == GetNumberOfValues() );
645  }
646 
648  DataElement ret( GetTag() );
649  std::ostringstream os;
650  if( Internal )
651  {
653  GetNumberOfValues(),os);
655  {
656  if( GetVR() != VR::UI )
657  {
658  if( os.str().size() % 2 )
659  {
660  os << " ";
661  }
662  }
663  }
664  }
665  ret.SetVR( GetVR() );
666  assert( ret.GetVR() != VR::SQ );
667  VL::Type osStrSize = (VL::Type) os.str().size();
668  ret.SetByteValue( os.str().c_str(), osStrSize);
669  return ret;
670  }
671  void SetFromDataElement(DataElement const &de) {
672  // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok:
673  assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 );
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  }
679 protected:
680  void SetByteValue(const ByteValue *bv) {
681  assert( bv ); // FIXME
682  std::stringstream ss;
683  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
684  Length = bv->GetLength(); // HACK FIXME
685  ss.str( s );
686  ArrayType *internal;
687  ArrayType buffer[256];
688  if( bv->GetLength() < 256 )
689  {
690  internal = buffer;
691  }
692  else
693  {
694  internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation
695  }
696  EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss);
697  SetValues( internal, Length, true );
698  if( !(bv->GetLength() < 256) )
699  {
700  delete[] internal;
701  }
702  //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
703  // GetNumberOfValues(),ss);
704  }
705 
706 private:
708  unsigned int Length;
709  bool Own : 1;
710 };
711 
712 template<uint16_t Group, uint16_t Element, int TVR>
713 class Attribute<Group,Element,TVR,VM::VM1_3> : public Attribute<Group,Element,TVR,VM::VM1_n>
714 {
715 public:
716  VM GetVM() const { return VM::VM1_3; }
717 };
718 
719 template<uint16_t Group, uint16_t Element, int TVR>
720 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n>
721 {
722 public:
723  VM GetVM() const { return VM::VM1_8; }
724 };
725 
726 template<uint16_t Group, uint16_t Element, int TVR>
727 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
728 {
729 public:
730  VM GetVM() const { return VM::VM2_n; }
731 };
732 
733 template<uint16_t Group, uint16_t Element, int TVR>
734 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n>
735 {
736 public:
737  static VM GetVM() { return VM::VM2_2n; }
738 };
739 
740 template<uint16_t Group, uint16_t Element, int TVR>
741 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
742 {
743 public:
744  static VM GetVM() { return VM::VM3_n; }
745 };
746 
747 template<uint16_t Group, uint16_t Element, int TVR>
748 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n>
749 {
750 public:
751  static VM GetVM() { return VM::VM3_3n; }
752 };
753 
754 
755 // For particular case for ASCII string
756 // WARNING: This template explicitely instanciates a particular
757 // EncodingImplementation THEREFORE it is required to be declared after the
758 // EncodingImplementation is needs (doh!)
759 #if 0
760 template<int TVM>
761 class Attribute<TVM>
762 {
763 public:
764  Attribute(const char array[])
765  {
766  unsigned int i = 0;
767  const char sep = '\\';
768  std::string sarray = array;
769  std::string::size_type pos1 = 0;
770  std::string::size_type pos2 = sarray.find(sep, pos1+1);
771  while(pos2 != std::string::npos)
772  {
773  Internal[i++] = sarray.substr(pos1, pos2-pos1);
774  pos1 = pos2+1;
775  pos2 = sarray.find(sep, pos1+1);
776  }
777  Internal[i] = sarray.substr(pos1, pos2-pos1);
778  // Shouldn't we do the contrary, since we know how many separators
779  // (and default behavior is to discard anything after the VM declared
780  assert( GetLength()-1 == i );
781  }
782 
783  unsigned long GetLength() const {
784  return VMToLength<TVM>::Length;
785  }
786  // Implementation of Print is common to all Mode (ASCII/Binary)
787  void Print(std::ostream &_os) const {
788  _os << Internal[0]; // VM is at least garantee to be one
789  for(int i=1; i<VMToLength<TVM>::Length; ++i)
790  _os << "," << Internal[i];
791  }
792 
793  void Read(std::istream &_is) {
794  EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
795  }
796  void Write(std::ostream &_os) const {
797  EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
798  }
799 private:
800  typename String Internal[VMToLength<TVM>::Length];
801 };
802 
803 template< int TVM>
804 class Attribute<VR::PN, TVM> : public StringAttribute<TVM>
805 {
806 };
807 #endif
808 
809 #if 0
810 
811 // Implementation for the undefined length (dynamically allocated array)
812 template<int TVR>
813 class Attribute<TVR, VM::VM1_n>
814 {
815 public:
816  // This the way to prevent default initialization
817  explicit Attribute() { Internal=0; Length=0; }
818  ~Attribute() {
819  delete[] Internal;
820  Internal = 0;
821  }
822 
823  // Length manipulation
824  // SetLength should really be protected anyway...all operation
825  // should go through SetArray
826  unsigned long GetLength() const { return Length; }
827  typedef typename VRToType<TVR>::Type ArrayType;
828  void SetLength(unsigned long len) {
829  const unsigned int size = sizeof(ArrayType);
830  if( len ) {
831  if( len > Length ) {
832  // perform realloc
833  assert( (len / size) * size == len );
834  ArrayType *internal = new ArrayType[len / size];
835  memcpy(internal, Internal, Length * size);
836  delete[] Internal;
837  Internal = internal;
838  }
839  }
840  Length = len / size;
841  }
842 
843  // If save is set to zero user should not delete the pointer
844  //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
845  void SetArray(const ArrayType *array, unsigned long len,
846  bool save = false) {
847  if( save ) {
848  SetLength(len); // realloc
849  memcpy(Internal, array, len/*/sizeof(ArrayType)*/);
850  }
851  else {
852  // TODO rewrite this stupid code:
853  Length = len;
854  //Internal = array;
855  assert(0);
856  }
857  }
858  // Implementation of Print is common to all Mode (ASCII/Binary)
859  void Print(std::ostream &_os) const {
860  assert( Length );
861  assert( Internal );
862  _os << Internal[0]; // VM is at least garantee to be one
863  const unsigned long length = GetLength() < 25 ? GetLength() : 25;
864  for(unsigned long i=1; i<length; ++i)
865  _os << "," << Internal[i];
866  }
867  void Read(std::istream &_is) {
869  GetLength(),_is);
870  }
871  void Write(std::ostream &_os) const {
873  GetLength(),_os);
874  }
875 
876  Attribute(const Attribute&_val) {
877  if( this != &_val) {
878  *this = _val;
879  }
880  }
881 
882  Attribute &operator=(const Attribute &_val) {
883  Length = 0; // SYITF
884  Internal = 0;
885  SetArray(_val.Internal, _val.Length, true);
886  return *this;
887  }
888 
889 private:
890  typename VRToType<TVR>::Type *Internal;
891  unsigned long Length; // unsigned int ??
892 };
893 
894 //template <int TVM = VM::VM1_n>
895 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {};
896 
897 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
898 template<int TVR>
899 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n>
900 {
901 public:
902  typedef Attribute<TVR, VM::VM1_n> Parent;
903  void SetLength(int len) {
904  if( len <= 1 ) return;
905  Parent::SetLength(len);
906  }
907 };
908 template<int TVR>
909 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n>
910 {
911 public:
912  typedef Attribute<TVR, VM::VM2_n> Parent;
913  void SetLength(int len) {
914  if( len % 2 ) return;
915  Parent::SetLength(len);
916  }
917 };
918 template<int TVR>
919 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n>
920 {
921 public:
922  typedef Attribute<TVR, VM::VM1_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_3n> : public Attribute<TVR, VM::VM3_n>
930 {
931 public:
932  typedef Attribute<TVR, VM::VM3_n> Parent;
933  void SetLength(int len) {
934  if( len % 3 ) return;
935  Parent::SetLength(len);
936  }
937 };
938 
939 
940 //template<int T> struct VRToLength;
941 //template <> struct VRToLength<VR::AS>
942 //{ enum { Length = VM::VM1 }; }
943 //template<>
944 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length >
945 
946 // only 0010 1010 AS 1 Patient’s Age
947 template<>
948 class Attribute<VR::AS, VM::VM5>
949 {
950 public:
951  char Internal[VMToLength<VM::VM5>::Length];
952  void Print(std::ostream &_os) const {
953  _os << Internal;
954  }
955 };
956 
957 template <>
958 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {};
959 // Make it impossible to compile any other cases:
960 template <int TVM> class Attribute<VR::OB, TVM>;
961 
962 // Same for OW:
963 template <>
964 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {};
965 // Make it impossible to compile any other cases:
966 template <int TVM> class Attribute<VR::OW, TVM>;
967 #endif
968 
969 #if 0
970 template<>
971 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1>
972 {
973 public:
974  char *Internal;
975  unsigned long Length; // unsigned int ??
976 
977  void Print(std::ostream &_os) const {
978  _os << Internal[0];
979  }
980  void SetBytes(char *bytes, unsigned long length) {
981  Internal = bytes;
982  Length = length;
983  }
984  void Read(std::istream &_is) {
985  uint16_t c[2];
986  _is.read((char*)&c, 4);
987  uint32_t l;
988  _is.read((char*)&l, 4);
989  Length = l;
990  _is.read( Internal, Length );
991  }
992  void Write(std::ostream &_os) const {
993  uint16_t c[] = {0x7fe0, 0x0010};
994  _os.write((char*)&c, 4);
995  _os.write((char*)&Length, 4);
996  _os.write( Internal, Length );
997  }
998 };
999 #endif
1000 
1001 /*
1002 // Removing Attribute for SQ for now...
1003 template<uint16_t Group, uint16_t Element, typename SQA>
1004 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA>
1005 {
1006 public:
1007  SQA sqa;
1008  void Print(std::ostream &_os) const {
1009  _os << Tag(Group,Element);
1010  sqa.Print(_os << std::endl << '\t');
1011  }
1012  void Write(std::ostream &_os) const {
1013  uint16_t c[] = {Group, Element};
1014  _os.write((char*)&c, 4);
1015  uint32_t undef = 0xffffffff;
1016  _os.write((char*)&undef, 4);
1017  uint16_t item_beg[] = {0xfffe,0xe000};
1018  _os.write((char*)&item_beg, 4);
1019  _os.write((char*)&undef, 4);
1020  sqa.Write(_os);
1021  uint16_t item_end[] = {0xfffe,0xe00d};
1022  _os.write((char*)&item_end, 4);
1023  uint32_t zero = 0x0;
1024  _os.write((char*)&zero, 4);
1025  uint16_t seq_end[] = {0xfffe, 0xe0dd};
1026  _os.write((char*)&seq_end, 4);
1027  _os.write((char*)&zero, 4);
1028  }
1029 };
1030 */
1031 
1037 } // namespace gdcm
1038 
1039 #endif //GDCMATTRIBUTE_H

Generated on Wed Jun 13 2012 20:40:37 for GDCM by doxygen 1.8.1
SourceForge.net Logo