GDCM 3.0.24
gdcmElement.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 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
32namespace gdcm_ns
33{
34
35// Forward declaration
41template<long long T> class EncodingImplementation;
42
43
51template <long long TVR, int TVM>
53template <>
54class ElementDisableCombinations<VR::OB, VM::VM1_n> {};
55template <>
56class ElementDisableCombinations<VR::OW, VM::VM1_n> {};
57// Make it impossible to compile these other cases
58template <int TVM>
59class ElementDisableCombinations<VR::OB, TVM>;
60template <int TVM>
61class ElementDisableCombinations<VR::OW, TVM>;
62
68template<long long TVR, int TVM>
70{
71 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, TVM> ) };
72public:
74 typedef typename VRToType<TVR>::Type Type;
75
76 static VR GetVR() { return (VR::VRType)TVR; }
77 static VM GetVM() { return (VM::VMType)TVM; }
78
79 unsigned long GetLength() const {
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?
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
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
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
128 DataElement ret;
129 std::ostringstream os;
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
150 void Read(std::istream &_is) {
152 GetLength(),_is);
153 }
154 void Write(std::ostream &_os) const {
156 GetLength(),_os);
157 }
158
159 // FIXME: remove this function
160 // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
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 );
169 GetLength(),ss);
170 }
171 }
172protected:
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 );
181 GetLength(),ss);
182 }
183};
184
186 ignore_char(char c): m_char(c) {}
187 char m_char;
188};
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
201template<> class EncodingImplementation<VR::VRASCII> {
202public:
203 template<typename T> // FIXME this should be VRToType<TVR>::Type
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
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>
248 static inline void ReadNoSwap(T* data, unsigned long length,
249 std::istream &_is) {
250 Read(data,length,_is);
251}
252 template<typename T>
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
269template < typename Float >
270std::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
286static 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
296static 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
308static 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
317#if defined(_MSC_VER) && (_MSC_VER < 1900)
318#define snprintf _snprintf
319#endif
320
321static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp) {
322 if (doround(buf, i) != 0) {
323 iexp += 1;
324 switch(iexp) {
325 case -2:
326 strcpy(buf, ".01");
327 break;
328 case -1:
329 strcpy(buf, ".1");
330 break;
331 case 0:
332 strcpy(buf, "1.");
333 break;
334 case 1:
335 strcpy(buf, "10");
336 break;
337 case 2:
338 strcpy(buf, "100");
339 break;
340 default:
341 snprintf(buf, bufLen, "1e%d", iexp);
342 }
343 return 1;
344 }
345 return 0;
346}
347
348template < typename Float >
349static void x16printf(char *buf, int size, Float f) {
350 char line[40];
351 char *mant = line + 1;
352 int iexp, lexp, i;
353 char exp[6];
354
355 if (f < 0) {
356 f = -f;
357 size -= 1;
358 *buf++ = '-';
359 }
360 snprintf(line, sizeof(line), "%1.16e", f);
361 if (line[0] == '-') {
362 f = -f;
363 size -= 1;
364 *buf++ = '-';
365 snprintf(line, sizeof(line), "%1.16e", f);
366 }
367 *mant = line[0];
368 i = (int)strcspn(mant, "eE");
369 mant[i] = '\0';
370 iexp = (int)strtol(mant + i + 1, nullptr, 10);
371 lexp = snprintf(exp, sizeof(exp), "e%d", iexp);
372 if ((iexp >= size) || (iexp < -3)) {
373 i = roundat(mant, sizeof(line) - 1, size - 1 -lexp, iexp);
374 if(i == 1) {
375 strcpy(buf, mant);
376 return;
377 }
378 buf[0] = mant[0];
379 buf[1] = '.';
380 strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
381 buf[size-lexp] = 0;
382 clean(buf);
383 strcat(buf, exp);
384 }
385 else if (iexp >= size - 2) {
386 roundat(mant, sizeof(line) - 1, iexp + 1, iexp);
387 strcpy(buf, mant);
388 }
389 else if (iexp >= 0) {
390 i = roundat(mant, sizeof(line) - 1, size - 1, iexp);
391 if (i == 1) {
392 strcpy(buf, mant);
393 return;
394 }
395 strncpy(buf, mant, iexp + 1);
396 buf[iexp + 1] = '.';
397 strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
398 buf[size] = 0;
399 clean(buf);
400 }
401 else {
402 int j;
403 i = roundat(mant, sizeof(line) - 1, size + 1 + iexp, iexp);
404 if (i == 1) {
405 strcpy(buf, mant);
406 return;
407 }
408 buf[0] = '.';
409 for(j=0; j< -1 - iexp; j++) {
410 buf[j+1] = '0';
411 }
412 strncpy(buf - iexp, mant, size + 1 + iexp);
413 buf[size] = 0;
414 clean(buf);
415 }
416}
417#if defined(_MSC_VER) && (_MSC_VER < 1900)
418#undef snprintf
419#endif
420
421#endif
422
423template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) {
424 assert( data );
425 assert( length );
426 assert( _os );
427#ifdef VRDS16ILLEGAL
428 _os << to_string(data[0]);
429#else
430 char buf[16+1];
431 x16printf(buf, 16, data[0]);
432 _os << buf;
433#endif
434 for(unsigned long i=1; i<length; ++i) {
435 assert( _os );
436#ifdef VRDS16ILLEGAL
437 _os << "\\" << to_string(data[i]);
438#else
439 x16printf(buf, 16, data[i]);
440 _os << "\\" << buf;
441#endif
442 }
443 }
444
445
446// Implementation to perform binary read and write
447// TODO rewrite operation so that either:
448// #1. dummy implementation use a pointer to Internal and do ++p (faster)
449// #2. Actually do some meta programming to unroll the loop
450// (no notion of order in VM ...)
451template<> class EncodingImplementation<VR::VRBINARY> {
452public:
453 template<typename T> // FIXME this should be VRToType<TVR>::Type
454 static inline void ReadComputeLength(T* data, unsigned int &length,
455 std::istream &_is) {
456 const unsigned int type_size = sizeof(T);
457 assert( data ); // Can we read from pointer ?
458 //assert( length );
459 length /= type_size;
460 assert( _is ); // Is stream valid ?
461 _is.read( reinterpret_cast<char*>(data+0), type_size);
462 for(unsigned long i=1; i<length; ++i) {
463 assert( _is );
464 _is.read( reinterpret_cast<char*>(data+i), type_size );
465 }
466 }
467 template<typename T>
468 static inline void ReadNoSwap(T* data, unsigned long length,
469 std::istream &_is) {
470 const unsigned int type_size = sizeof(T);
471 assert( data ); // Can we read from pointer ?
472 assert( length );
473 assert( _is ); // Is stream valid ?
474 _is.read( reinterpret_cast<char*>(data+0), type_size);
475 for(unsigned long i=1; i<length; ++i) {
476 if( _is )
477 _is.read( reinterpret_cast<char*>(data+i), type_size );
478 }
479 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
480 // _is.GetSwapCode(), length);
481 //SwapperNoOp::SwapArray(data,length);
482 }
483 template<typename T>
484 static inline void Read(T* data, unsigned long length,
485 std::istream &_is) {
486 const unsigned int type_size = sizeof(T);
487 assert( data ); // Can we read from pointer ?
488 assert( length );
489 assert( _is ); // Is stream valid ?
490 _is.read( reinterpret_cast<char*>(data+0), type_size);
491 for(unsigned long i=1; i<length; ++i) {
492 if( _is )
493 _is.read( reinterpret_cast<char*>(data+i), type_size );
494 }
495 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
496 // _is.GetSwapCode(), length);
497 SwapperNoOp::SwapArray(data,length);
498 }
499 template<typename T>
500 static inline void Write(const T* data, unsigned long length,
501 std::ostream &_os) {
502 const unsigned int type_size = sizeof(T);
503 assert( data ); // Can we write into pointer ?
504 assert( length );
505 assert( _os ); // Is stream valid ?
506 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
507 // _os.GetSwapCode(), length);
508 T swappedData = SwapperNoOp::Swap(data[0]);
509 _os.write( reinterpret_cast<const char*>(&swappedData), type_size);
510 for(unsigned long i=1; i<length;++i) {
511 assert( _os );
512 swappedData = SwapperNoOp::Swap(data[i]);
513 _os.write( reinterpret_cast<const char*>(&swappedData), type_size );
514 }
515 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
516 // _os.GetSwapCode(), length);
517 }
518};
519
520// For particular case for ASCII string
521// WARNING: This template explicitly instantiates a particular
522// EncodingImplementation THEREFORE it is required to be declared after the
523// EncodingImplementation is needs (doh!)
524#if 0
525template<int TVM>
526class Element<TVM>
527{
528public:
529 Element(const char array[])
530 {
531 unsigned int i = 0;
532 const char sep = '\\';
533 std::string sarray = array;
534 std::string::size_type pos1 = 0;
535 std::string::size_type pos2 = sarray.find(sep, pos1+1);
536 while(pos2 != std::string::npos)
537 {
538 Internal[i++] = sarray.substr(pos1, pos2-pos1);
539 pos1 = pos2+1;
540 pos2 = sarray.find(sep, pos1+1);
541 }
542 Internal[i] = sarray.substr(pos1, pos2-pos1);
543 // Shouldn't we do the contrary, since we know how many separators
544 // (and default behavior is to discard anything after the VM declared
545 assert( GetLength()-1 == i );
546 }
547
548 unsigned long GetLength() const {
549 return VMToLength<TVM>::Length;
550 }
551 // Implementation of Print is common to all Mode (ASCII/Binary)
552 void Print(std::ostream &_os) const {
553 _os << Internal[0]; // VM is at least guarantee to be one
554 for(int i=1; i<VMToLength<TVM>::Length; ++i)
555 _os << "," << Internal[i];
556 }
557
558 void Read(std::istream &_is) {
559 EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
560 }
561 void Write(std::ostream &_os) const {
562 EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
563 }
564private:
565 typename String Internal[VMToLength<TVM>::Length];
566};
567
568template< int TVM>
569class Element<VR::PN, TVM> : public StringElement<TVM>
570{
571 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::PN, TVM> ) };
572};
573#endif
574
575// Implementation for the undefined length (dynamically allocated array)
576template<long long TVR>
577class Element<TVR, VM::VM1_n>
578{
579 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM1_n> ) };
580public:
581 // This the way to prevent default initialization
582 explicit Element() { Internal=nullptr; Length=0; Save = false; }
584 if( Save ) {
585 delete[] Internal;
586 }
587 Internal = nullptr;
588 }
589
590 static VR GetVR() { return (VR::VRType)TVR; }
591 static VM GetVM() { return VM::VM1_n; }
592
593 // Length manipulation
594 // SetLength should really be protected anyway...all operation
595 // should go through SetArray
596 unsigned long GetLength() const { return Length; }
597 typedef typename VRToType<TVR>::Type Type;
598
599 void SetLength(unsigned long len) {
600 const unsigned int size = sizeof(Type);
601 if( len ) {
602 if( len > Length ) {
603 // perform realloc
604 assert( (len / size) * size == len );
605 Type *internal = new Type[len / size];
606 assert( Save == false );
607 Save = true; // ????
608 if( Internal )
609 {
610 memcpy(internal, Internal, len);
611 delete[] Internal;
612 }
613 Internal = internal;
614 }
615 }
616 Length = len / size;
617 }
618
619 // If save is set to zero user should not delete the pointer
620 //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
621 void SetArray(const Type *array, unsigned long len,
622 bool save = false) {
623 if( save ) {
624 SetLength(len); // realloc
625 memcpy(Internal, array, len/*/sizeof(Type)*/);
626 assert( Save == false );
627 }
628 else {
629 // TODO rewrite this stupid code:
630 assert( Length == 0 );
631 assert( Internal == nullptr );
632 assert( Save == false );
633 Length = len / sizeof(Type);
634 //assert( (len / sizeof(Type)) * sizeof(Type) == len );
635 // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
636 // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
637 if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = nullptr; Length = 0; }
638 else Internal = const_cast<Type*>(array);
639 }
640 Save = save;
641 }
642 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
643 assert( idx < Length );
644 Internal[idx] = v;
645 }
646 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
647 assert( idx < Length );
648 return Internal[idx];
649 }
650 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
651 //assert( idx < Length );
652 return Internal[idx];
653 }
654 typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
655 return GetValue(idx);
656 }
657 void Set(Value const &v) {
658 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
659 assert( bv ); // That would be bad...
660 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
661 {
662 const Type* array = (const Type*)bv->GetVoidPointer();
663 if( array ) {
664 assert( array ); // That would be bad...
665 assert( Internal == nullptr );
666 SetArray(array, bv->GetLength() ); }
667 }
668 else
669 {
670 std::stringstream ss;
671 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
672 ss.str( s );
674 GetLength(),ss);
675 }
676 }
678 const ByteValue *bv = de.GetByteValue();
679 if( !bv ) return;
680#ifdef GDCM_WORDS_BIGENDIAN
681 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
682#else
683 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
684#endif
685 {
686 Set(de.GetValue());
687 }
688 else
689 {
690 SetNoSwap(de.GetValue());
691 }
692 }
693
694
695 // Need to be placed after definition of EncodingImplementation<VR::VRASCII>
696 void WriteASCII(std::ostream &os) const {
697 return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os);
698 }
699
700 // Implementation of Print is common to all Mode (ASCII/Binary)
701 void Print(std::ostream &_os) const {
702 assert( Length );
703 assert( Internal );
704 _os << Internal[0]; // VM is at least guarantee to be one
705 const unsigned long length = GetLength() < 25 ? GetLength() : 25;
706 for(unsigned long i=1; i<length; ++i)
707 _os << "," << Internal[i];
708 }
709 void Read(std::istream &_is) {
710 if( !Internal ) return;
712 GetLength(),_is);
713 }
714 //void ReadComputeLength(std::istream &_is) {
715 // if( !Internal ) return;
716 // EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
717 // Length,_is);
718 // }
719 void Write(std::ostream &_os) const {
721 GetLength(),_os);
722 }
723
725 DataElement ret;
726 ret.SetVR( (VR::VRType)TVR );
727 assert( ret.GetVR() != VR::SQ );
728 if( Internal )
729 {
730 std::ostringstream os;
732 GetLength(),os);
733 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
734 {
735 if( GetVR() != VR::UI )
736 {
737 if( os.str().size() % 2 )
738 {
739 os << " ";
740 }
741 }
742 }
743 VL::Type osStrSize = (VL::Type)os.str().size();
744 ret.SetByteValue( os.str().c_str(), osStrSize );
745 }
746 return ret;
747 }
748
749 Element(const Element&_val) {
750 if( this != &_val) {
751 *this = _val;
752 }
753 }
754
755 Element &operator=(const Element &_val) {
756 Length = 0; // SYITF
757 Internal = 0;
758 SetArray(_val.Internal, _val.Length, true);
759 return *this;
760 }
761protected:
762 void SetNoSwap(Value const &v) {
763 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
764 assert( bv ); // That would be bad...
765 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
766 {
767 const Type* array = (const Type*)bv->GetPointer();
768 if( array ) {
769 assert( array ); // That would be bad...
770 assert( Internal == nullptr );
771 SetArray(array, bv->GetLength() ); }
772 }
773 else
774 {
775 std::stringstream ss;
776 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
777 ss.str( s );
779 GetLength(),ss);
780 }
781 }
782
783private:
784 typename VRToType<TVR>::Type *Internal;
785 unsigned long Length; // unsigned int ??
786 bool Save;
787};
788
789//template <int TVM = VM::VM1_n>
790//class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
791
792// Partial specialization for derivatives of 1-n : 2-n, 3-n ...
793template<long long TVR>
794class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n>
795{
796public:
798 void SetLength(int len) {
799 if( len != 1 && len != 2 ) return;
800 Parent::SetLength(len);
801 }
802};
803template<long long TVR>
804class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
805{
806 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_n> ) };
807public:
809 void SetLength(int len) {
810 if( len <= 1 ) return;
811 Parent::SetLength(len);
812 }
813};
814template<long long TVR>
815class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
816{
817 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_2n> ) };
818public:
820 void SetLength(int len) {
821 if( len % 2 ) return;
822 Parent::SetLength(len);
823 }
824};
825template<long long TVR>
826class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
827{
828 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_n> ) };
829public:
831 void SetLength(int len) {
832 if( len <= 2 ) return;
833 Parent::SetLength(len);
834 }
835};
836template<long long TVR>
837class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
838{
839 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_3n> ) };
840public:
842 void SetLength(int len) {
843 if( len % 3 ) return;
844 Parent::SetLength(len);
845 }
846};
847template<long long TVR>
848class Element<TVR, VM::VM3_4> : public Element<TVR, VM::VM1_n>
849{
850public:
852 void SetLength(int len) {
853 if( len != 3 && len != 4 ) return;
854 Parent::SetLength(len);
855 }
856};
857
858
859//template<int T> struct VRToLength;
860//template <> struct VRToLength<VR::AS>
861//{ enum { Length = VM::VM1 }; }
862//template<>
863//class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
864
865// only 0010 1010 AS 1 Patient's Age
866template<>
867class Element<VR::AS, VM::VM5>
868{
869 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::AS, VM::VM5> ) };
870public:
872 void Print(std::ostream &_os) const {
873 _os << Internal;
874 }
875 unsigned long GetLength() const {
877 }
878};
879
880
881template <>
882class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
883
884// Same for OW:
885template <>
886class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
887
888
889} // namespace gdcm_ns
890
891#endif //GDCMELEMENT_H
Class to represent binary value (array of bytes)
Definition gdcmByteValue.h:35
const void * GetVoidPointer() const
Definition gdcmByteValue.h:115
const char * GetPointer() const
Definition gdcmByteValue.h:110
VL GetLength() const override
Definition gdcmByteValue.h:77
Class to represent a Data Element either Implicit or Explicit.
Definition gdcmDataElement.h:59
VR const & GetVR() const
Definition gdcmDataElement.h:84
const ByteValue * GetByteValue() const
Definition gdcmDataElement.h:133
Value const & GetValue() const
Set/Get Value (bytes array, SQ of items, SQ of fragments):
Definition gdcmDataElement.h:94
void SetByteValue(const char *array, VL length)
Definition gdcmDataElement.h:126
void SetVR(VR const &vr)
Definition gdcmDataElement.h:88
A class which is used to produce compile errors for an invalid combination of template parameters.
Definition gdcmElement.h:52
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:797
void SetLength(int len)
Definition gdcmElement.h:798
Element()
Definition gdcmElement.h:582
void Read(std::istream &_is)
Definition gdcmElement.h:709
void SetNoSwap(Value const &v)
Definition gdcmElement.h:762
void SetLength(unsigned long len)
Definition gdcmElement.h:599
void WriteASCII(std::ostream &os) const
Definition gdcmElement.h:696
static VR GetVR()
Definition gdcmElement.h:590
VRToType< TVR >::Type & GetValue(unsigned int idx=0)
Definition gdcmElement.h:650
void Set(Value const &v)
Definition gdcmElement.h:657
static VM GetVM()
Definition gdcmElement.h:591
void SetFromDataElement(DataElement const &de)
Definition gdcmElement.h:677
void SetArray(const Type *array, unsigned long len, bool save=false)
Definition gdcmElement.h:621
Element & operator=(const Element &_val)
Definition gdcmElement.h:755
void Print(std::ostream &_os) const
Definition gdcmElement.h:701
unsigned long GetLength() const
Definition gdcmElement.h:596
DataElement GetAsDataElement() const
Definition gdcmElement.h:724
void SetValue(typename VRToType< TVR >::Type v, unsigned int idx=0)
Definition gdcmElement.h:642
VRToType< TVR >::Type Type
Definition gdcmElement.h:597
const VRToType< TVR >::Type & GetValue(unsigned int idx=0) const
Definition gdcmElement.h:646
~Element()
Definition gdcmElement.h:583
void Write(std::ostream &_os) const
Definition gdcmElement.h:719
Element(const Element &_val)
Definition gdcmElement.h:749
Element< TVR, VM::VM2_n > Parent
Definition gdcmElement.h:819
void SetLength(int len)
Definition gdcmElement.h:820
void SetLength(int len)
Definition gdcmElement.h:809
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:808
void SetLength(int len)
Definition gdcmElement.h:842
Element< TVR, VM::VM3_n > Parent
Definition gdcmElement.h:841
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:851
void SetLength(int len)
Definition gdcmElement.h:852
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:830
void SetLength(int len)
Definition gdcmElement.h:831
unsigned long GetLength() const
Definition gdcmElement.h:875
void Print(std::ostream &_os) const
Definition gdcmElement.h:872
Element class.
Definition gdcmElement.h:70
static VM GetVM()
Definition gdcmElement.h:77
DataElement GetAsDataElement() const
Definition gdcmElement.h:127
VRToType< TVR >::Type & GetValue(unsigned int idx=0)
Definition gdcmElement.h:98
VRToType< TVR >::Type Type
Definition gdcmElement.h:74
void Read(std::istream &_is)
Definition gdcmElement.h:150
unsigned long GetLength() const
Definition gdcmElement.h:79
void SetValue(typename VRToType< TVR >::Type v, unsigned int idx=0)
Definition gdcmElement.h:105
const VRToType< TVR >::Type & GetValue(unsigned int idx=0) const
Definition gdcmElement.h:94
const VRToType< TVR >::Type * GetValues() const
Definition gdcmElement.h:91
void Write(std::ostream &_os) const
Definition gdcmElement.h:154
void SetNoSwap(Value const &v)
Definition gdcmElement.h:173
static VR GetVR()
Definition gdcmElement.h:76
void Print(std::ostream &_os) const
Definition gdcmElement.h:85
void Set(Value const &v)
Definition gdcmElement.h:161
void SetFromDataElement(DataElement const &de)
Definition gdcmElement.h:110
static void ReadComputeLength(T *data, unsigned int &length, std::istream &_is)
Definition gdcmElement.h:204
static void ReadNoSwap(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:248
static void Write(const T *data, unsigned long length, std::ostream &_os)
Definition gdcmElement.h:253
static void Read(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:228
static void ReadNoSwap(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:468
static void Read(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:484
static void Write(const T *data, unsigned long length, std::ostream &_os)
Definition gdcmElement.h:500
static void ReadComputeLength(T *data, unsigned int &length, std::istream &_is)
Definition gdcmElement.h:454
EncodingImplementation.
Definition gdcmElement.h:41
uint32_t Type
Definition gdcmVL.h:32
Value Multiplicity Looking at the DICOMV3 dict only there is very few cases: 1 2 3 4 5 6 8 16 24 1-2 ...
Definition gdcmVM.h:68
VMType
Definition gdcmVM.h:70
VR class.
Definition gdcmVR.h:55
VRType
Definition gdcmVR.h:57
Class to represent the value of a Data Element.
Definition gdcmValue.h:32
static int add1(char *buf, int n)
Definition gdcmElement.h:296
static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp)
Definition gdcmElement.h:321
static int doround(char *buf, unsigned int n)
Definition gdcmElement.h:308
static void clean(char *mant)
Definition gdcmElement.h:286
static void x16printf(char *buf, int size, Float f)
Definition gdcmElement.h:349
ignore_char const backslash('\\')
Definition gdcmVM.h:155
Definition gdcmVR.h:242
Definition gdcmVR.h:244
Definition gdcmElement.h:185
char m_char
Definition gdcmElement.h:187
ignore_char(char c)
Definition gdcmElement.h:186