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 garantee 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 instanciates 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 garantee 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 == 0 );
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->GetPointer();
659       if( array ) {
660         assert( array ); // That would be bad...
661         assert( Internal == 0 );
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 garantee 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 == 0 );
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 
844 
845 //template<int T> struct VRToLength;
846 //template <> struct VRToLength<VR::AS>
847 //{ enum { Length  = VM::VM1 }; }
848 //template<>
849 //class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
850 
851 // only 0010 1010 AS 1 Patient's Age
852 template<>
853 class Element<VR::AS, VM::VM5>
854 {
855   enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::AS, VM::VM5> ) };
856 public:
857   char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )];
Print(std::ostream & _os)858   void Print(std::ostream &_os) const {
859     _os << Internal;
860     }
GetLength()861   unsigned long GetLength() const {
862     return VMToLength<VM::VM5>::Length;
863   }
864 };
865 
866 
867 template <>
868 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
869 
870 // Same for OW:
871 template <>
872 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
873 
874 
875 } // namespace gdcm_ns
876 
877 #endif //GDCMELEMENT_H
878