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 GDCMELEMENT_H
15 #define GDCMELEMENT_H
16
17 #include "gdcmTypes.h"
18 #include "gdcmVR.h"
19 #include "gdcmTag.h"
20 #include "gdcmVM.h"
21 #include "gdcmByteValue.h"
22 #include "gdcmDataElement.h"
23 #include "gdcmSwapper.h"
24
25 #include <string>
26 #include <vector>
27 #include <sstream>
28 #include <limits>
29 #include <cmath>
30 #include <cstring>
31
32 namespace gdcm_ns
33 {
34
35 // Forward declaration
36 /**
37 * \brief EncodingImplementation
38 *
39 * \note TODO
40 */
41 template<long long T> class EncodingImplementation;
42
43
44 /**
45 * \brief A class which is used to produce compile errors for an
46 * invalid combination of template parameters.
47 *
48 * Invalid combinations have specialized declarations with no
49 * definition.
50 */
51 template <long long TVR, int TVM>
52 class ElementDisableCombinations {};
53 template <>
54 class ElementDisableCombinations<VR::OB, VM::VM1_n> {};
55 template <>
56 class ElementDisableCombinations<VR::OW, VM::VM1_n> {};
57 // Make it impossible to compile these other cases
58 template <int TVM>
59 class ElementDisableCombinations<VR::OB, TVM>;
60 template <int TVM>
61 class ElementDisableCombinations<VR::OW, TVM>;
62
63 /**
64 * \brief Element class
65 *
66 * \note TODO
67 */
68 template<long long TVR, int TVM>
69 class Element
70 {
71 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, TVM> ) };
72 public:
73 typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length];
74 typedef typename VRToType<TVR>::Type Type;
75
GetVR()76 static VR GetVR() { return (VR::VRType)TVR; }
GetVM()77 static VM GetVM() { return (VM::VMType)TVM; }
78
GetLength()79 unsigned long GetLength() const {
80 return VMToLength<TVM>::Length;
81 }
82 // Implementation of Print is common to all Mode (ASCII/Binary)
83 // TODO: Can we print a \ when in ASCII...well I don't think so
84 // it would mean we used a bad VM then, right?
Print(std::ostream & _os)85 void Print(std::ostream &_os) const {
86 _os << Internal[0]; // VM is at least guarantee to be one
87 for(int i=1; i<VMToLength<TVM>::Length; ++i)
88 _os << "," << Internal[i];
89 }
90
GetValues()91 const typename VRToType<TVR>::Type *GetValues() const {
92 return Internal;
93 }
94 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
95 assert( idx < VMToLength<TVM>::Length );
96 return Internal[idx];
97 }
98 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
99 assert( idx < VMToLength<TVM>::Length );
100 return Internal[idx];
101 }
102 typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
103 return GetValue(idx);
104 }
105 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
106 assert( idx < VMToLength<TVM>::Length );
107 Internal[idx] = v;
108 }
109
SetFromDataElement(DataElement const & de)110 void SetFromDataElement(DataElement const &de) {
111 const ByteValue *bv = de.GetByteValue();
112 if( !bv ) return;
113 #ifdef GDCM_WORDS_BIGENDIAN
114 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
115 #else
116 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
117 #endif
118 {
119 Set(de.GetValue());
120 }
121 else
122 {
123 SetNoSwap(de.GetValue());
124 }
125 }
126
GetAsDataElement()127 DataElement GetAsDataElement() const {
128 DataElement ret;
129 std::ostringstream os;
130 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
131 GetLength(),os);
132 ret.SetVR( (VR::VRType)TVR );
133 assert( ret.GetVR() != VR::SQ );
134 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
135 {
136 if( GetVR() != VR::UI )
137 {
138 if( os.str().size() % 2 )
139 {
140 os << " ";
141 }
142 }
143 }
144 VL::Type osStrSize = (VL::Type)os.str().size();
145 ret.SetByteValue( os.str().c_str(), osStrSize );
146
147 return ret;
148 }
149
Read(std::istream & _is)150 void Read(std::istream &_is) {
151 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
152 GetLength(),_is);
153 }
Write(std::ostream & _os)154 void Write(std::ostream &_os) const {
155 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
156 GetLength(),_os);
157 }
158
159 // FIXME: remove this function
160 // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
Set(Value const & v)161 void Set(Value const &v) {
162 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
163 if( bv ) {
164 //memcpy(Internal, bv->GetPointer(), bv->GetLength());
165 std::stringstream ss;
166 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
167 ss.str( s );
168 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
169 GetLength(),ss);
170 }
171 }
172 protected:
SetNoSwap(Value const & v)173 void SetNoSwap(Value const &v) {
174 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
175 assert( bv ); // That would be bad...
176 //memcpy(Internal, bv->GetPointer(), bv->GetLength());
177 std::stringstream ss;
178 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
179 ss.str( s );
180 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
181 GetLength(),ss);
182 }
183 };
184
185 struct ignore_char {
ignore_charignore_char186 ignore_char(char c): m_char(c) {}
187 char m_char;
188 };
189 ignore_char const backslash('\\');
190
191 inline std::istream& operator>> (std::istream& in, ignore_char const& ic) {
192 if (!in.eof())
193 in.clear(in.rdstate() & ~std::ios_base::failbit);
194 if (in.get() != ic.m_char)
195 in.setstate(std::ios_base::failbit);
196 return in;
197 }
198
199
200 // Implementation to perform formatted read and write
201 template<> class EncodingImplementation<VR::VRASCII> {
202 public:
203 template<typename T> // FIXME this should be VRToType<TVR>::Type
ReadComputeLength(T * data,unsigned int & length,std::istream & _is)204 static inline void ReadComputeLength(T* data, unsigned int &length,
205 std::istream &_is) {
206 assert( data );
207 //assert( length ); // != 0
208 length = 0;
209 assert( _is );
210 #if 0
211 char sep;
212 while( _is >> data[length++] )
213 {
214 // Get the separator in between the values
215 assert( _is );
216 _is.get(sep);
217 assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert
218 if( sep == ' ' ) length--; // FIXME
219 }
220 #else
221 while( _is >> std::ws >> data[length++] >> std::ws >> backslash )
222 {
223 }
224 #endif
225 }
226
227 template<typename T> // FIXME this should be VRToType<TVR>::Type
Read(T * data,unsigned long length,std::istream & _is)228 static inline void Read(T* data, unsigned long length,
229 std::istream &_is) {
230 assert( data );
231 assert( length ); // != 0
232 assert( _is );
233 // FIXME BUG: what if >> operation fails ?
234 // gdcmData/MR00010001.dcm / SpacingBetweenSlices
235 _is >> std::ws >> data[0];
236 char sep;
237 //std::cout << "GetLength: " << af->GetLength() << std::endl;
238 for(unsigned long i=1; i<length;++i) {
239 //assert( _is );
240 // Get the separator in between the values
241 _is >> std::ws >> sep; //_is.get(sep);
242 //assert( sep == '\\' ); // FIXME: Bad use of assert
243 _is >> std::ws >> data[i];
244 }
245 }
246
247 template<typename T>
ReadNoSwap(T * data,unsigned long length,std::istream & _is)248 static inline void ReadNoSwap(T* data, unsigned long length,
249 std::istream &_is) {
250 Read(data,length,_is);
251 }
252 template<typename T>
Write(const T * data,unsigned long length,std::ostream & _os)253 static inline void Write(const T* data, unsigned long length,
254 std::ostream &_os) {
255 assert( data );
256 assert( length );
257 assert( _os );
258 _os << data[0];
259 for(unsigned long i=1; i<length; ++i) {
260 assert( _os );
261 _os << "\\" << data[i];
262 }
263 }
264 };
265
266 //#define VRDS16ILLEGAL
267
268 #ifdef VRDS16ILLEGAL
269 template < typename Float >
to_string(Float data)270 std::string to_string ( Float data ) {
271 std::stringstream in;
272 // in.imbue(std::locale::classic()); // This is not required AFAIK
273 int const digits =
274 static_cast< int >(
275 - std::log( std::numeric_limits<Float>::epsilon() )
276 / static_cast< Float >( std::log( 10.0 ) ) );
277 if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) {
278 return ( in.str() );
279 } else {
280 throw "Impossible Conversion"; // should not happen ...
281 }
282 }
283 #else
284 // http://stackoverflow.com/questions/32631178/writing-ieee-754-1985-double-as-ascii-on-a-limited-16-bytes-string
285
clean(char * mant)286 static inline void clean(char *mant) {
287 char *ix = mant + strlen(mant) - 1;
288 while(('0' == *ix) && (ix > mant)) {
289 *ix-- = '\0';
290 }
291 if ('.' == *ix) {
292 *ix = '\0';
293 }
294 }
295
add1(char * buf,int n)296 static int add1(char *buf, int n) {
297 if (n < 0) return 1;
298 if (buf[n] == '9') {
299 buf[n] = '0';
300 return add1(buf, n-1);
301 }
302 else {
303 buf[n] = (char)(buf[n] + 1);
304 }
305 return 0;
306 }
307
doround(char * buf,unsigned int n)308 static int doround(char *buf, unsigned int n) {
309 char c;
310 if (n >= strlen(buf)) return 0;
311 c = buf[n];
312 buf[n] = 0;
313 if ((c >= '5') && (c <= '9')) return add1(buf, n-1);
314 return 0;
315 }
316
roundat(char * buf,unsigned int i,int iexp)317 static int roundat(char *buf, unsigned int i, int iexp) {
318 if (doround(buf, i) != 0) {
319 iexp += 1;
320 switch(iexp) {
321 case -2:
322 strcpy(buf, ".01");
323 break;
324 case -1:
325 strcpy(buf, ".1");
326 break;
327 case 0:
328 strcpy(buf, "1.");
329 break;
330 case 1:
331 strcpy(buf, "10");
332 break;
333 case 2:
334 strcpy(buf, "100");
335 break;
336 default:
337 sprintf(buf, "1e%d", iexp);
338 }
339 return 1;
340 }
341 return 0;
342 }
343
344 template < typename Float >
x16printf(char * buf,int size,Float f)345 static void x16printf(char *buf, int size, Float f) {
346 char line[40];
347 char *mant = line + 1;
348 int iexp, lexp, i;
349 char exp[6];
350
351 if (f < 0) {
352 f = -f;
353 size -= 1;
354 *buf++ = '-';
355 }
356 sprintf(line, "%1.16e", f);
357 if (line[0] == '-') {
358 f = -f;
359 size -= 1;
360 *buf++ = '-';
361 sprintf(line, "%1.16e", f);
362 }
363 *mant = line[0];
364 i = (int)strcspn(mant, "eE");
365 mant[i] = '\0';
366 iexp = (int)strtol(mant + i + 1, nullptr, 10);
367 lexp = sprintf(exp, "e%d", iexp);
368 if ((iexp >= size) || (iexp < -3)) {
369 i = roundat(mant, size - 1 -lexp, iexp);
370 if(i == 1) {
371 strcpy(buf, mant);
372 return;
373 }
374 buf[0] = mant[0];
375 buf[1] = '.';
376 strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
377 buf[size-lexp] = 0;
378 clean(buf);
379 strcat(buf, exp);
380 }
381 else if (iexp >= size - 2) {
382 roundat(mant, iexp + 1, iexp);
383 strcpy(buf, mant);
384 }
385 else if (iexp >= 0) {
386 i = roundat(mant, size - 1, iexp);
387 if (i == 1) {
388 strcpy(buf, mant);
389 return;
390 }
391 strncpy(buf, mant, iexp + 1);
392 buf[iexp + 1] = '.';
393 strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
394 buf[size] = 0;
395 clean(buf);
396 }
397 else {
398 int j;
399 i = roundat(mant, size + 1 + iexp, iexp);
400 if (i == 1) {
401 strcpy(buf, mant);
402 return;
403 }
404 buf[0] = '.';
405 for(j=0; j< -1 - iexp; j++) {
406 buf[j+1] = '0';
407 }
408 if ((i == 1) && (iexp != -1)) {
409 buf[-iexp] = '1';
410 buf++;
411 }
412 strncpy(buf - iexp, mant, size + 1 + iexp);
413 buf[size] = 0;
414 clean(buf);
415 }
416 }
417 #endif
418
Write(const double * data,unsigned long length,std::ostream & _os)419 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) {
420 assert( data );
421 assert( length );
422 assert( _os );
423 #ifdef VRDS16ILLEGAL
424 _os << to_string(data[0]);
425 #else
426 char buf[16+1];
427 x16printf(buf, 16, data[0]);
428 _os << buf;
429 #endif
430 for(unsigned long i=1; i<length; ++i) {
431 assert( _os );
432 #ifdef VRDS16ILLEGAL
433 _os << "\\" << to_string(data[i]);
434 #else
435 x16printf(buf, 16, data[i]);
436 _os << "\\" << buf;
437 #endif
438 }
439 }
440
441
442 // Implementation to perform binary read and write
443 // TODO rewrite operation so that either:
444 // #1. dummy implementation use a pointer to Internal and do ++p (faster)
445 // #2. Actually do some meta programming to unroll the loop
446 // (no notion of order in VM ...)
447 template<> class EncodingImplementation<VR::VRBINARY> {
448 public:
449 template<typename T> // FIXME this should be VRToType<TVR>::Type
ReadComputeLength(T * data,unsigned int & length,std::istream & _is)450 static inline void ReadComputeLength(T* data, unsigned int &length,
451 std::istream &_is) {
452 const unsigned int type_size = sizeof(T);
453 assert( data ); // Can we read from pointer ?
454 //assert( length );
455 length /= type_size;
456 assert( _is ); // Is stream valid ?
457 _is.read( reinterpret_cast<char*>(data+0), type_size);
458 for(unsigned long i=1; i<length; ++i) {
459 assert( _is );
460 _is.read( reinterpret_cast<char*>(data+i), type_size );
461 }
462 }
463 template<typename T>
ReadNoSwap(T * data,unsigned long length,std::istream & _is)464 static inline void ReadNoSwap(T* data, unsigned long length,
465 std::istream &_is) {
466 const unsigned int type_size = sizeof(T);
467 assert( data ); // Can we read from pointer ?
468 assert( length );
469 assert( _is ); // Is stream valid ?
470 _is.read( reinterpret_cast<char*>(data+0), type_size);
471 for(unsigned long i=1; i<length; ++i) {
472 assert( _is );
473 _is.read( reinterpret_cast<char*>(data+i), type_size );
474 }
475 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
476 // _is.GetSwapCode(), length);
477 //SwapperNoOp::SwapArray(data,length);
478 }
479 template<typename T>
Read(T * data,unsigned long length,std::istream & _is)480 static inline void Read(T* data, unsigned long length,
481 std::istream &_is) {
482 const unsigned int type_size = sizeof(T);
483 assert( data ); // Can we read from pointer ?
484 assert( length );
485 assert( _is ); // Is stream valid ?
486 _is.read( reinterpret_cast<char*>(data+0), type_size);
487 for(unsigned long i=1; i<length; ++i) {
488 assert( _is );
489 _is.read( reinterpret_cast<char*>(data+i), type_size );
490 }
491 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
492 // _is.GetSwapCode(), length);
493 SwapperNoOp::SwapArray(data,length);
494 }
495 template<typename T>
Write(const T * data,unsigned long length,std::ostream & _os)496 static inline void Write(const T* data, unsigned long length,
497 std::ostream &_os) {
498 const unsigned int type_size = sizeof(T);
499 assert( data ); // Can we write into pointer ?
500 assert( length );
501 assert( _os ); // Is stream valid ?
502 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
503 // _os.GetSwapCode(), length);
504 T swappedData = SwapperNoOp::Swap(data[0]);
505 _os.write( reinterpret_cast<const char*>(&swappedData), type_size);
506 for(unsigned long i=1; i<length;++i) {
507 assert( _os );
508 swappedData = SwapperNoOp::Swap(data[i]);
509 _os.write( reinterpret_cast<const char*>(&swappedData), type_size );
510 }
511 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
512 // _os.GetSwapCode(), length);
513 }
514 };
515
516 // For particular case for ASCII string
517 // WARNING: This template explicitly instantiates a particular
518 // EncodingImplementation THEREFORE it is required to be declared after the
519 // EncodingImplementation is needs (doh!)
520 #if 0
521 template<int TVM>
522 class Element<TVM>
523 {
524 public:
525 Element(const char array[])
526 {
527 unsigned int i = 0;
528 const char sep = '\\';
529 std::string sarray = array;
530 std::string::size_type pos1 = 0;
531 std::string::size_type pos2 = sarray.find(sep, pos1+1);
532 while(pos2 != std::string::npos)
533 {
534 Internal[i++] = sarray.substr(pos1, pos2-pos1);
535 pos1 = pos2+1;
536 pos2 = sarray.find(sep, pos1+1);
537 }
538 Internal[i] = sarray.substr(pos1, pos2-pos1);
539 // Shouldn't we do the contrary, since we know how many separators
540 // (and default behavior is to discard anything after the VM declared
541 assert( GetLength()-1 == i );
542 }
543
544 unsigned long GetLength() const {
545 return VMToLength<TVM>::Length;
546 }
547 // Implementation of Print is common to all Mode (ASCII/Binary)
548 void Print(std::ostream &_os) const {
549 _os << Internal[0]; // VM is at least guarantee to be one
550 for(int i=1; i<VMToLength<TVM>::Length; ++i)
551 _os << "," << Internal[i];
552 }
553
554 void Read(std::istream &_is) {
555 EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
556 }
557 void Write(std::ostream &_os) const {
558 EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
559 }
560 private:
561 typename String Internal[VMToLength<TVM>::Length];
562 };
563
564 template< int TVM>
565 class Element<VR::PN, TVM> : public StringElement<TVM>
566 {
567 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::PN, TVM> ) };
568 };
569 #endif
570
571 // Implementation for the undefined length (dynamically allocated array)
572 template<long long TVR>
573 class Element<TVR, VM::VM1_n>
574 {
575 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM1_n> ) };
576 public:
577 // This the way to prevent default initialization
Element()578 explicit Element() { Internal=nullptr; Length=0; Save = false; }
~Element()579 ~Element() {
580 if( Save ) {
581 delete[] Internal;
582 }
583 Internal = nullptr;
584 }
585
GetVR()586 static VR GetVR() { return (VR::VRType)TVR; }
GetVM()587 static VM GetVM() { return VM::VM1_n; }
588
589 // Length manipulation
590 // SetLength should really be protected anyway...all operation
591 // should go through SetArray
GetLength()592 unsigned long GetLength() const { return Length; }
593 typedef typename VRToType<TVR>::Type Type;
594
SetLength(unsigned long len)595 void SetLength(unsigned long len) {
596 const unsigned int size = sizeof(Type);
597 if( len ) {
598 if( len > Length ) {
599 // perform realloc
600 assert( (len / size) * size == len );
601 Type *internal = new Type[len / size];
602 assert( Save == false );
603 Save = true; // ????
604 if( Internal )
605 {
606 memcpy(internal, Internal, len);
607 delete[] Internal;
608 }
609 Internal = internal;
610 }
611 }
612 Length = len / size;
613 }
614
615 // If save is set to zero user should not delete the pointer
616 //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
617 void SetArray(const Type *array, unsigned long len,
618 bool save = false) {
619 if( save ) {
620 SetLength(len); // realloc
621 memcpy(Internal, array, len/*/sizeof(Type)*/);
622 assert( Save == false );
623 }
624 else {
625 // TODO rewrite this stupid code:
626 assert( Length == 0 );
627 assert( Internal == nullptr );
628 assert( Save == false );
629 Length = len / sizeof(Type);
630 //assert( (len / sizeof(Type)) * sizeof(Type) == len );
631 // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
632 // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
633 if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = nullptr; Length = 0; }
634 else Internal = const_cast<Type*>(array);
635 }
636 Save = save;
637 }
638 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
639 assert( idx < Length );
640 Internal[idx] = v;
641 }
642 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
643 assert( idx < Length );
644 return Internal[idx];
645 }
646 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
647 //assert( idx < Length );
648 return Internal[idx];
649 }
650 typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
651 return GetValue(idx);
652 }
Set(Value const & v)653 void Set(Value const &v) {
654 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
655 assert( bv ); // That would be bad...
656 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
657 {
658 const Type* array = (const Type*)bv->GetVoidPointer();
659 if( array ) {
660 assert( array ); // That would be bad...
661 assert( Internal == nullptr );
662 SetArray(array, bv->GetLength() ); }
663 }
664 else
665 {
666 std::stringstream ss;
667 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
668 ss.str( s );
669 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
670 GetLength(),ss);
671 }
672 }
SetFromDataElement(DataElement const & de)673 void SetFromDataElement(DataElement const &de) {
674 const ByteValue *bv = de.GetByteValue();
675 if( !bv ) return;
676 #ifdef GDCM_WORDS_BIGENDIAN
677 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
678 #else
679 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
680 #endif
681 {
682 Set(de.GetValue());
683 }
684 else
685 {
686 SetNoSwap(de.GetValue());
687 }
688 }
689
690
691 // Need to be placed after definition of EncodingImplementation<VR::VRASCII>
WriteASCII(std::ostream & os)692 void WriteASCII(std::ostream &os) const {
693 return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os);
694 }
695
696 // Implementation of Print is common to all Mode (ASCII/Binary)
Print(std::ostream & _os)697 void Print(std::ostream &_os) const {
698 assert( Length );
699 assert( Internal );
700 _os << Internal[0]; // VM is at least guarantee to be one
701 const unsigned long length = GetLength() < 25 ? GetLength() : 25;
702 for(unsigned long i=1; i<length; ++i)
703 _os << "," << Internal[i];
704 }
Read(std::istream & _is)705 void Read(std::istream &_is) {
706 if( !Internal ) return;
707 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
708 GetLength(),_is);
709 }
710 //void ReadComputeLength(std::istream &_is) {
711 // if( !Internal ) return;
712 // EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
713 // Length,_is);
714 // }
Write(std::ostream & _os)715 void Write(std::ostream &_os) const {
716 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
717 GetLength(),_os);
718 }
719
GetAsDataElement()720 DataElement GetAsDataElement() const {
721 DataElement ret;
722 ret.SetVR( (VR::VRType)TVR );
723 assert( ret.GetVR() != VR::SQ );
724 if( Internal )
725 {
726 std::ostringstream os;
727 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
728 GetLength(),os);
729 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
730 {
731 if( GetVR() != VR::UI )
732 {
733 if( os.str().size() % 2 )
734 {
735 os << " ";
736 }
737 }
738 }
739 VL::Type osStrSize = (VL::Type)os.str().size();
740 ret.SetByteValue( os.str().c_str(), osStrSize );
741 }
742 return ret;
743 }
744
Element(const Element & _val)745 Element(const Element&_val) {
746 if( this != &_val) {
747 *this = _val;
748 }
749 }
750
751 Element &operator=(const Element &_val) {
752 Length = 0; // SYITF
753 Internal = 0;
754 SetArray(_val.Internal, _val.Length, true);
755 return *this;
756 }
757 protected:
SetNoSwap(Value const & v)758 void SetNoSwap(Value const &v) {
759 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
760 assert( bv ); // That would be bad...
761 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
762 {
763 const Type* array = (const Type*)bv->GetPointer();
764 if( array ) {
765 assert( array ); // That would be bad...
766 assert( Internal == nullptr );
767 SetArray(array, bv->GetLength() ); }
768 }
769 else
770 {
771 std::stringstream ss;
772 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
773 ss.str( s );
774 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
775 GetLength(),ss);
776 }
777 }
778
779 private:
780 typename VRToType<TVR>::Type *Internal;
781 unsigned long Length; // unsigned int ??
782 bool Save;
783 };
784
785 //template <int TVM = VM::VM1_n>
786 //class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
787
788 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
789 template<long long TVR>
790 class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n>
791 {
792 public:
793 typedef Element<TVR, VM::VM1_n> Parent;
SetLength(int len)794 void SetLength(int len) {
795 if( len != 1 && len != 2 ) return;
796 Parent::SetLength(len);
797 }
798 };
799 template<long long TVR>
800 class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
801 {
802 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_n> ) };
803 public:
804 typedef Element<TVR, VM::VM1_n> Parent;
SetLength(int len)805 void SetLength(int len) {
806 if( len <= 1 ) return;
807 Parent::SetLength(len);
808 }
809 };
810 template<long long TVR>
811 class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
812 {
813 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_2n> ) };
814 public:
815 typedef Element<TVR, VM::VM2_n> Parent;
SetLength(int len)816 void SetLength(int len) {
817 if( len % 2 ) return;
818 Parent::SetLength(len);
819 }
820 };
821 template<long long TVR>
822 class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
823 {
824 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_n> ) };
825 public:
826 typedef Element<TVR, VM::VM1_n> Parent;
SetLength(int len)827 void SetLength(int len) {
828 if( len <= 2 ) return;
829 Parent::SetLength(len);
830 }
831 };
832 template<long long TVR>
833 class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
834 {
835 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_3n> ) };
836 public:
837 typedef Element<TVR, VM::VM3_n> Parent;
SetLength(int len)838 void SetLength(int len) {
839 if( len % 3 ) return;
840 Parent::SetLength(len);
841 }
842 };
843 template<long long TVR>
844 class Element<TVR, VM::VM3_4> : public Element<TVR, VM::VM1_n>
845 {
846 public:
847 typedef Element<TVR, VM::VM1_n> Parent;
SetLength(int len)848 void SetLength(int len) {
849 if( len != 3 && len != 4 ) return;
850 Parent::SetLength(len);
851 }
852 };
853
854
855 //template<int T> struct VRToLength;
856 //template <> struct VRToLength<VR::AS>
857 //{ enum { Length = VM::VM1 }; }
858 //template<>
859 //class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
860
861 // only 0010 1010 AS 1 Patient's Age
862 template<>
863 class Element<VR::AS, VM::VM5>
864 {
865 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::AS, VM::VM5> ) };
866 public:
867 char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )];
Print(std::ostream & _os)868 void Print(std::ostream &_os) const {
869 _os << Internal;
870 }
GetLength()871 unsigned long GetLength() const {
872 return VMToLength<VM::VM5>::Length;
873 }
874 };
875
876
877 template <>
878 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
879
880 // Same for OW:
881 template <>
882 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
883
884
885 } // namespace gdcm_ns
886
887 #endif //GDCMELEMENT_H
888