GDCM 2.2.1

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

- File List
- File Members

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
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
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) {
227 SetFromDataElement( ds.GetDataElement( GetTag() ) );
228 }
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:
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 }
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, 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];
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
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
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
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
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
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) {
462 SetFromDataElement( ds.GetDataElement( GetTag() ) );
463 }
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:
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 }
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, 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; }
575 ~Attribute() {
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
647 DataElement GetAsDataElement() const {
648 DataElement ret( GetTag() );
649 std::ostringstream os;
650 if( Internal )
651 {
652 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
653 GetNumberOfValues(),os);
654 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
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:
708 ArrayType *Internal;
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 {
785 return VMToLength<TVM>::Length;
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) {
869 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
870 GetLength(),_is);
871 }
872 void Write(std::ostream &_os) const {
873 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
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