GDCM  2.2.1
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;
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 {
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;
323  //ArrayType Internal[VMToLength<TVM>::Length];
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 {
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  || GetTag().GetGroup() == 0x5000 );
675  assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator
676  assert( !de.IsEmpty() );
677  const ByteValue *bv = de.GetByteValue();
678  SetByteValue(bv);
679  }
680 protected:
681  void SetByteValue(const ByteValue *bv) {
682  assert( bv ); // FIXME
683  std::stringstream ss;
684  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
685  Length = bv->GetLength(); // HACK FIXME
686  ss.str( s );
687  ArrayType *internal;
688  ArrayType buffer[256];
689  if( bv->GetLength() < 256 )
690  {
691  internal = buffer;
692  }
693  else
694  {
695  internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation
696  }
697  EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss);
698  SetValues( internal, Length, true );
699  if( !(bv->GetLength() < 256) )
700  {
701  delete[] internal;
702  }
703  //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
704  // GetNumberOfValues(),ss);
705  }
706 
707 private:
709  unsigned int Length;
710  bool Own : 1;
711 };
712 
713 template<uint16_t Group, uint16_t Element, int TVR>
714 class Attribute<Group,Element,TVR,VM::VM1_3> : public Attribute<Group,Element,TVR,VM::VM1_n>
715 {
716 public:
717  VM GetVM() const { return VM::VM1_3; }
718 };
719 
720 template<uint16_t Group, uint16_t Element, int TVR>
721 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n>
722 {
723 public:
724  VM GetVM() const { return VM::VM1_8; }
725 };
726 
727 template<uint16_t Group, uint16_t Element, int TVR>
728 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
729 {
730 public:
731  VM GetVM() const { return VM::VM2_n; }
732 };
733 
734 template<uint16_t Group, uint16_t Element, int TVR>
735 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n>
736 {
737 public:
738  static VM GetVM() { return VM::VM2_2n; }
739 };
740 
741 template<uint16_t Group, uint16_t Element, int TVR>
742 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n>
743 {
744 public:
745  static VM GetVM() { return VM::VM3_n; }
746 };
747 
748 template<uint16_t Group, uint16_t Element, int TVR>
749 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n>
750 {
751 public:
752  static VM GetVM() { return VM::VM3_3n; }
753 };
754 
755 
756 // For particular case for ASCII string
757 // WARNING: This template explicitely instanciates a particular
758 // EncodingImplementation THEREFORE it is required to be declared after the
759 // EncodingImplementation is needs (doh!)
760 #if 0
761 template<int TVM>
762 class Attribute<TVM>
763 {
764 public:
765  Attribute(const char array[])
766  {
767  unsigned int i = 0;
768  const char sep = '\\';
769  std::string sarray = array;
770  std::string::size_type pos1 = 0;
771  std::string::size_type pos2 = sarray.find(sep, pos1+1);
772  while(pos2 != std::string::npos)
773  {
774  Internal[i++] = sarray.substr(pos1, pos2-pos1);
775  pos1 = pos2+1;
776  pos2 = sarray.find(sep, pos1+1);
777  }
778  Internal[i] = sarray.substr(pos1, pos2-pos1);
779  // Shouldn't we do the contrary, since we know how many separators
780  // (and default behavior is to discard anything after the VM declared
781  assert( GetLength()-1 == i );
782  }
783 
784  unsigned long GetLength() const {
786  }
787  // Implementation of Print is common to all Mode (ASCII/Binary)
788  void Print(std::ostream &_os) const {
789  _os << Internal[0]; // VM is at least garantee to be one
790  for(int i=1; i<VMToLength<TVM>::Length; ++i)
791  _os << "," << Internal[i];
792  }
793 
794  void Read(std::istream &_is) {
795  EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
796  }
797  void Write(std::ostream &_os) const {
798  EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
799  }
800 private:
801  typename String Internal[VMToLength<TVM>::Length];
802 };
803 
804 template< int TVM>
805 class Attribute<VR::PN, TVM> : public StringAttribute<TVM>
806 {
807 };
808 #endif
809 
810 #if 0
811 
812 // Implementation for the undefined length (dynamically allocated array)
813 template<int TVR>
814 class Attribute<TVR, VM::VM1_n>
815 {
816 public:
817  // This the way to prevent default initialization
818  explicit Attribute() { Internal=0; Length=0; }
819  ~Attribute() {
820  delete[] Internal;
821  Internal = 0;
822  }
823 
824  // Length manipulation
825  // SetLength should really be protected anyway...all operation
826  // should go through SetArray
827  unsigned long GetLength() const { return Length; }
828  typedef typename VRToType<TVR>::Type ArrayType;
829  void SetLength(unsigned long len) {
830  const unsigned int size = sizeof(ArrayType);
831  if( len ) {
832  if( len > Length ) {
833  // perform realloc
834  assert( (len / size) * size == len );
835  ArrayType *internal = new ArrayType[len / size];
836  memcpy(internal, Internal, Length * size);
837  delete[] Internal;
838  Internal = internal;
839  }
840  }
841  Length = len / size;
842  }
843 
844  // If save is set to zero user should not delete the pointer
845  //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
846  void SetArray(const ArrayType *array, unsigned long len,
847  bool save = false) {
848  if( save ) {
849  SetLength(len); // realloc
850  memcpy(Internal, array, len/*/sizeof(ArrayType)*/);
851  }
852  else {
853  // TODO rewrite this stupid code:
854  Length = len;
855  //Internal = array;
856  assert(0);
857  }
858  }
859  // Implementation of Print is common to all Mode (ASCII/Binary)
860  void Print(std::ostream &_os) const {
861  assert( Length );
862  assert( Internal );
863  _os << Internal[0]; // VM is at least garantee to be one
864  const unsigned long length = GetLength() < 25 ? GetLength() : 25;
865  for(unsigned long i=1; i<length; ++i)
866  _os << "," << Internal[i];
867  }
868  void Read(std::istream &_is) {
870  GetLength(),_is);
871  }
872  void Write(std::ostream &_os) const {
874  GetLength(),_os);
875  }
876 
877  Attribute(const Attribute&_val) {
878  if( this != &_val) {
879  *this = _val;
880  }
881  }
882 
883  Attribute &operator=(const Attribute &_val) {
884  Length = 0; // SYITF
885  Internal = 0;
886  SetArray(_val.Internal, _val.Length, true);
887  return *this;
888  }
889 
890 private:
891  typename VRToType<TVR>::Type *Internal;
892  unsigned long Length; // unsigned int ??
893 };
894 
895 //template <int TVM = VM::VM1_n>
896 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {};
897 
898 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
899 template<int TVR>
900 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n>
901 {
902 public:
903  typedef Attribute<TVR, VM::VM1_n> Parent;
904  void SetLength(int len) {
905  if( len <= 1 ) return;
906  Parent::SetLength(len);
907  }
908 };
909 template<int TVR>
910 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n>
911 {
912 public:
913  typedef Attribute<TVR, VM::VM2_n> Parent;
914  void SetLength(int len) {
915  if( len % 2 ) return;
916  Parent::SetLength(len);
917  }
918 };
919 template<int TVR>
920 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n>
921 {
922 public:
923  typedef Attribute<TVR, VM::VM1_n> Parent;
924  void SetLength(int len) {
925  if( len <= 2 ) return;
926  Parent::SetLength(len);
927  }
928 };
929 template<int TVR>
930 class Attribute<TVR, VM::VM3_3n> : public Attribute<TVR, VM::VM3_n>
931 {
932 public:
933  typedef Attribute<TVR, VM::VM3_n> Parent;
934  void SetLength(int len) {
935  if( len % 3 ) return;
936  Parent::SetLength(len);
937  }
938 };
939 
940 
941 //template<int T> struct VRToLength;
942 //template <> struct VRToLength<VR::AS>
943 //{ enum { Length = VM::VM1 }; }
944 //template<>
945 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length >
946 
947 // only 0010 1010 AS 1 Patient’s Age
948 template<>
949 class Attribute<VR::AS, VM::VM5>
950 {
951 public:
952  char Internal[VMToLength<VM::VM5>::Length];
953  void Print(std::ostream &_os) const {
954  _os << Internal;
955  }
956 };
957 
958 template <>
959 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {};
960 // Make it impossible to compile any other cases:
961 template <int TVM> class Attribute<VR::OB, TVM>;
962 
963 // Same for OW:
964 template <>
965 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {};
966 // Make it impossible to compile any other cases:
967 template <int TVM> class Attribute<VR::OW, TVM>;
968 #endif
969 
970 #if 0
971 template<>
972 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1>
973 {
974 public:
975  char *Internal;
976  unsigned long Length; // unsigned int ??
977 
978  void Print(std::ostream &_os) const {
979  _os << Internal[0];
980  }
981  void SetBytes(char *bytes, unsigned long length) {
982  Internal = bytes;
983  Length = length;
984  }
985  void Read(std::istream &_is) {
986  uint16_t c[2];
987  _is.read((char*)&c, 4);
988  uint32_t l;
989  _is.read((char*)&l, 4);
990  Length = l;
991  _is.read( Internal, Length );
992  }
993  void Write(std::ostream &_os) const {
994  uint16_t c[] = {0x7fe0, 0x0010};
995  _os.write((char*)&c, 4);
996  _os.write((char*)&Length, 4);
997  _os.write( Internal, Length );
998  }
999 };
1000 #endif
1001 
1002 /*
1003 // Removing Attribute for SQ for now...
1004 template<uint16_t Group, uint16_t Element, typename SQA>
1005 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA>
1006 {
1007 public:
1008  SQA sqa;
1009  void Print(std::ostream &_os) const {
1010  _os << Tag(Group,Element);
1011  sqa.Print(_os << std::endl << '\t');
1012  }
1013  void Write(std::ostream &_os) const {
1014  uint16_t c[] = {Group, Element};
1015  _os.write((char*)&c, 4);
1016  uint32_t undef = 0xffffffff;
1017  _os.write((char*)&undef, 4);
1018  uint16_t item_beg[] = {0xfffe,0xe000};
1019  _os.write((char*)&item_beg, 4);
1020  _os.write((char*)&undef, 4);
1021  sqa.Write(_os);
1022  uint16_t item_end[] = {0xfffe,0xe00d};
1023  _os.write((char*)&item_end, 4);
1024  uint32_t zero = 0x0;
1025  _os.write((char*)&zero, 4);
1026  uint16_t seq_end[] = {0xfffe, 0xe0dd};
1027  _os.write((char*)&seq_end, 4);
1028  _os.write((char*)&zero, 4);
1029  }
1030 };
1031 */
1032 
1038 } // namespace gdcm
1039 
1040 #endif //GDCMATTRIBUTE_H

Generated on Wed Apr 10 2013 04:43:09 for GDCM by doxygen 1.8.2
SourceForge.net Logo