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_ns 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: Read(std::istream & _is)41 static inline uint16_t Read(std::istream &_is) { 42 uint16_t l; 43 _is.read((char*)&l, 2); 44 return l; 45 } 46 Write(std::ostream & os)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: Read(std::istream & _is)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 Write(std::ostream & os)62 static inline void Write(std::ostream &os) { (void)os; 63 } 64 }; 65 66 /** 67 * \brief Attribute class 68 * This class use template metaprograming tricks to let the user know when the template 69 * instanciation does not match the public dictionary. 70 * 71 * Typical example that compile is: 72 * Attribute<0x0008,0x9007> a = {"ORIGINAL","PRIMARY","T1","NONE"}; 73 * 74 * Examples that will NOT compile are: 75 * 76 * Attribute<0x0018,0x1182, VR::IS, VM::VM1> fd1 = {}; // not enough parameters 77 * Attribute<0x0018,0x1182, VR::IS, VM::VM2> fd2 = {0,1,2}; // too many initializers 78 * Attribute<0x0018,0x1182, VR::IS, VM::VM3> fd3 = {0,1,2}; // VM3 is not valid 79 * Attribute<0x0018,0x1182, VR::UL, VM::VM2> fd3 = {0,1}; // UL is not valid VR 80 */ 81 template<uint16_t Group, uint16_t Element, 82 long long 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 GetTag()98 static Tag GetTag() { return Tag(Group,Element); } GetVR()99 static VR GetVR() { return (VR::VRType)TVR; } GetVM()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) GetDictVR()105 static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); } GetDictVM()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 GetNumberOfValues()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 ? Print(std::ostream & os)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 } GetValues()178 const ArrayType* GetValues() const { 179 return Internal; 180 } 181 182 // API to talk to the run-time layer: gdcm::DataElement GetAsDataElement()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 SetFromDataElement(DataElement const & de)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 } Set(DataSet const & ds)226 void Set(DataSet const &ds) { 227 SetFromDataElement( ds.GetDataElement( GetTag() ) ); 228 } SetFromDataSet(DataSet const & ds)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: SetByteValueNoSwap(const ByteValue * bv)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 } SetByteValue(const ByteValue * bv)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, long long 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 GetTag()333 static Tag GetTag() { return Tag(Group,Element); } GetVR()334 static VR GetVR() { return (VR::VRType)TVR; } GetVM()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) GetDictVR()340 static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); } GetDictVM()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 GetNumberOfValues()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 ? Print(std::ostream & os)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 GetValue()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 GetValue()394 ArrayType const &GetValue() const { 395 //assert( idx < GetNumberOfValues() ); 396 return Internal; 397 } 398 //ArrayType const & operator[] () const { 399 // return GetValue(); 400 //} SetValue(ArrayType v)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 ? GetValues()413 const ArrayType* GetValues() const { 414 return &Internal; 415 } 416 417 // API to talk to the run-time layer: gdcm::DataElement GetAsDataElement()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 SetFromDataElement(DataElement const & de)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 } Set(DataSet const & ds)461 void Set(DataSet const &ds) { 462 SetFromDataElement( ds.GetDataElement( GetTag() ) ); 463 } SetFromDataSet(DataSet const & ds)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: SetByteValueNoSwap(const ByteValue * bv)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 } SetByteValue(const ByteValue * bv)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, long long 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 GetTag()566 static Tag GetTag() { return Tag(Group,Element); } GetVR()567 static VR GetVR() { return (VR::VRType)TVR; } GetVM()568 static VM GetVM() { return VM::VM1_n; } 569 GetDictVR()570 static VR GetDictVR() { return (VR::VRType)(TagToType<Group, Element>::VRType); } GetDictVM()571 static VM GetDictVM() { return GetVM(); } 572 573 // This the way to prevent default initialization Attribute()574 explicit Attribute() { Internal=nullptr; Length=0; Own = true; } ~Attribute()575 ~Attribute() { 576 if( Own ) { 577 delete[] Internal; 578 } 579 Internal = nullptr; // paranoid 580 } 581 GetNumberOfValues()582 unsigned int GetNumberOfValues() const { return Length; } 583 SetNumberOfValues(unsigned int numel)584 void SetNumberOfValues(unsigned int numel) 585 { 586 SetValues(nullptr, numel, true); 587 } 588 GetValues()589 const ArrayType* GetValues() const { 590 return Internal; 591 } Print(std::ostream & os)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 } SetValue(unsigned int idx,ArrayType v)615 void SetValue(unsigned int idx, ArrayType v) { 616 assert( idx < GetNumberOfValues() ); 617 Internal[idx] = v; 618 } SetValue(ArrayType v)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 = nullptr; 628 } 629 Own = own; 630 Length = numel; 631 assert( Internal == 0 ); 632 if( own ) // make a copy: 633 { 634 Internal = new ArrayType[numel]; 635 if( array && numel ) 636 std::copy(array, array+numel, Internal); 637 } 638 else // pass pointer 639 { 640 Internal = const_cast<ArrayType*>(array); 641 } 642 // postcondition 643 assert( numel == GetNumberOfValues() ); 644 } 645 GetAsDataElement()646 DataElement GetAsDataElement() const { 647 DataElement ret( GetTag() ); 648 std::ostringstream os; 649 if( Internal ) 650 { 651 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 652 GetNumberOfValues(),os); 653 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII ) 654 { 655 if( GetVR() != VR::UI ) 656 { 657 if( os.str().size() % 2 ) 658 { 659 os << " "; 660 } 661 } 662 } 663 } 664 ret.SetVR( GetVR() ); 665 assert( ret.GetVR() != VR::SQ ); 666 VL::Type osStrSize = (VL::Type) os.str().size(); 667 ret.SetByteValue( os.str().c_str(), osStrSize); 668 return ret; 669 } SetFromDataElement(DataElement const & de)670 void SetFromDataElement(DataElement const &de) { 671 // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok: 672 assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 673 || GetTag().GetGroup() == 0x5000 ); 674 assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator 675 assert( !de.IsEmpty() ); 676 const ByteValue *bv = de.GetByteValue(); 677 SetByteValue(bv); 678 } Set(DataSet const & ds)679 void Set(DataSet const &ds) { 680 SetFromDataElement( ds.GetDataElement( GetTag() ) ); 681 } SetFromDataSet(DataSet const & ds)682 void SetFromDataSet(DataSet const &ds) { 683 if( ds.FindDataElement( GetTag() ) && 684 !ds.GetDataElement( GetTag() ).IsEmpty() ) 685 { 686 SetFromDataElement( ds.GetDataElement( GetTag() ) ); 687 } 688 } 689 protected: SetByteValue(const ByteValue * bv)690 void SetByteValue(const ByteValue *bv) { 691 assert( bv ); // FIXME 692 std::stringstream ss; 693 std::string s = std::string( bv->GetPointer(), bv->GetLength() ); 694 Length = bv->GetLength(); // HACK FIXME 695 ss.str( s ); 696 ArrayType *internal; 697 ArrayType buffer[256]; 698 if( bv->GetLength() < 256 ) 699 { 700 internal = buffer; 701 } 702 else 703 { 704 internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation 705 } 706 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(internal, Length, ss); 707 SetValues( internal, Length, true ); 708 if( !(bv->GetLength() < 256) ) 709 { 710 delete[] internal; 711 } 712 //EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 713 // GetNumberOfValues(),ss); 714 } 715 716 private: 717 ArrayType *Internal; 718 unsigned int Length; 719 bool Own : 1; 720 }; 721 722 template<uint16_t Group, uint16_t Element, long long TVR> 723 class Attribute<Group,Element,TVR,VM::VM1_3> : public Attribute<Group,Element,TVR,VM::VM1_n> 724 { 725 public: GetVM()726 VM GetVM() const { return VM::VM1_3; } 727 }; 728 729 template<uint16_t Group, uint16_t Element, long long TVR> 730 class Attribute<Group,Element,TVR,VM::VM1_8> : public Attribute<Group,Element,TVR,VM::VM1_n> 731 { 732 public: GetVM()733 VM GetVM() const { return VM::VM1_8; } 734 }; 735 736 template<uint16_t Group, uint16_t Element, long long TVR> 737 class Attribute<Group,Element,TVR,VM::VM2_n> : public Attribute<Group,Element,TVR,VM::VM1_n> 738 { 739 public: GetVM()740 VM GetVM() const { return VM::VM2_n; } 741 }; 742 743 template<uint16_t Group, uint16_t Element, long long TVR> 744 class Attribute<Group,Element,TVR,VM::VM2_2n> : public Attribute<Group,Element,TVR,VM::VM2_n> 745 { 746 public: GetVM()747 static VM GetVM() { return VM::VM2_2n; } 748 }; 749 750 template<uint16_t Group, uint16_t Element, long long TVR> 751 class Attribute<Group,Element,TVR,VM::VM3_n> : public Attribute<Group,Element,TVR,VM::VM1_n> 752 { 753 public: GetVM()754 static VM GetVM() { return VM::VM3_n; } 755 }; 756 757 template<uint16_t Group, uint16_t Element, long long TVR> 758 class Attribute<Group,Element,TVR,VM::VM3_3n> : public Attribute<Group,Element,TVR,VM::VM3_n> 759 { 760 public: GetVM()761 static VM GetVM() { return VM::VM3_3n; } 762 }; 763 764 765 // For particular case for ASCII string 766 // WARNING: This template explicitly instanciates a particular 767 // EncodingImplementation THEREFORE it is required to be declared after the 768 // EncodingImplementation is needs (doh!) 769 #if 0 770 template<int TVM> 771 class Attribute<TVM> 772 { 773 public: 774 Attribute(const char array[]) 775 { 776 unsigned int i = 0; 777 const char sep = '\\'; 778 std::string sarray = array; 779 std::string::size_type pos1 = 0; 780 std::string::size_type pos2 = sarray.find(sep, pos1+1); 781 while(pos2 != std::string::npos) 782 { 783 Internal[i++] = sarray.substr(pos1, pos2-pos1); 784 pos1 = pos2+1; 785 pos2 = sarray.find(sep, pos1+1); 786 } 787 Internal[i] = sarray.substr(pos1, pos2-pos1); 788 // Shouldn't we do the contrary, since we know how many separators 789 // (and default behavior is to discard anything after the VM declared 790 assert( GetLength()-1 == i ); 791 } 792 793 unsigned long GetLength() const { 794 return VMToLength<TVM>::Length; 795 } 796 // Implementation of Print is common to all Mode (ASCII/Binary) 797 void Print(std::ostream &_os) const { 798 _os << Internal[0]; // VM is at least garantee to be one 799 for(int i=1; i<VMToLength<TVM>::Length; ++i) 800 _os << "," << Internal[i]; 801 } 802 803 void Read(std::istream &_is) { 804 EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is); 805 } 806 void Write(std::ostream &_os) const { 807 EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os); 808 } 809 private: 810 typename String Internal[VMToLength<TVM>::Length]; 811 }; 812 813 template< int TVM> 814 class Attribute<VR::PN, TVM> : public StringAttribute<TVM> 815 { 816 }; 817 #endif 818 819 #if 0 820 821 // Implementation for the undefined length (dynamically allocated array) 822 template<int TVR> 823 class Attribute<TVR, VM::VM1_n> 824 { 825 public: 826 // This the way to prevent default initialization 827 explicit Attribute() { Internal=0; Length=0; } 828 ~Attribute() { 829 delete[] Internal; 830 Internal = 0; 831 } 832 833 // Length manipulation 834 // SetLength should really be protected anyway...all operation 835 // should go through SetArray 836 unsigned long GetLength() const { return Length; } 837 typedef typename VRToType<TVR>::Type ArrayType; 838 void SetLength(unsigned long len) { 839 const unsigned int size = sizeof(ArrayType); 840 if( len ) { 841 if( len > Length ) { 842 // perform realloc 843 assert( (len / size) * size == len ); 844 ArrayType *internal = new ArrayType[len / size]; 845 memcpy(internal, Internal, Length * size); 846 delete[] Internal; 847 Internal = internal; 848 } 849 } 850 Length = len / size; 851 } 852 853 // If save is set to zero user should not delete the pointer 854 //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false) 855 void SetArray(const ArrayType *array, unsigned long len, 856 bool save = false) { 857 if( save ) { 858 SetLength(len); // realloc 859 memcpy(Internal, array, len/*/sizeof(ArrayType)*/); 860 } 861 else { 862 // TODO rewrite this stupid code: 863 Length = len; 864 //Internal = array; 865 assert(0); 866 } 867 } 868 // Implementation of Print is common to all Mode (ASCII/Binary) 869 void Print(std::ostream &_os) const { 870 assert( Length ); 871 assert( Internal ); 872 _os << Internal[0]; // VM is at least garantee to be one 873 const unsigned long length = GetLength() < 25 ? GetLength() : 25; 874 for(unsigned long i=1; i<length; ++i) 875 _os << "," << Internal[i]; 876 } 877 void Read(std::istream &_is) { 878 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 879 GetLength(),_is); 880 } 881 void Write(std::ostream &_os) const { 882 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 883 GetLength(),_os); 884 } 885 886 Attribute(const Attribute&_val) { 887 if( this != &_val) { 888 *this = _val; 889 } 890 } 891 892 Attribute &operator=(const Attribute &_val) { 893 Length = 0; // SYITF 894 Internal = 0; 895 SetArray(_val.Internal, _val.Length, true); 896 return *this; 897 } 898 899 private: 900 typename VRToType<TVR>::Type *Internal; 901 unsigned long Length; // unsigned int ?? 902 }; 903 904 //template <int TVM = VM::VM1_n> 905 //class Attribute<VR::OB, TVM > : public Attribute<VR::OB, VM::VM1_n> {}; 906 907 // Partial specialization for derivatives of 1-n : 2-n, 3-n ... 908 template<int TVR> 909 class Attribute<TVR, VM::VM2_n> : public Attribute<TVR, VM::VM1_n> 910 { 911 public: 912 typedef Attribute<TVR, VM::VM1_n> Parent; 913 void SetLength(int len) { 914 if( len <= 1 ) return; 915 Parent::SetLength(len); 916 } 917 }; 918 template<int TVR> 919 class Attribute<TVR, VM::VM2_2n> : public Attribute<TVR, VM::VM2_n> 920 { 921 public: 922 typedef Attribute<TVR, VM::VM2_n> Parent; 923 void SetLength(int len) { 924 if( len % 2 ) return; 925 Parent::SetLength(len); 926 } 927 }; 928 template<int TVR> 929 class Attribute<TVR, VM::VM3_n> : public Attribute<TVR, VM::VM1_n> 930 { 931 public: 932 typedef Attribute<TVR, VM::VM1_n> Parent; 933 void SetLength(int len) { 934 if( len <= 2 ) return; 935 Parent::SetLength(len); 936 } 937 }; 938 template<int TVR> 939 class Attribute<TVR, VM::VM3_3n> : public Attribute<TVR, VM::VM3_n> 940 { 941 public: 942 typedef Attribute<TVR, VM::VM3_n> Parent; 943 void SetLength(int len) { 944 if( len % 3 ) return; 945 Parent::SetLength(len); 946 } 947 }; 948 949 950 //template<int T> struct VRToLength; 951 //template <> struct VRToLength<VR::AS> 952 //{ enum { Length = VM::VM1 }; } 953 //template<> 954 //class Attribute<VR::AS> : public Attribute<VR::AS, VRToLength<VR::AS>::Length > 955 956 // only 0010 1010 AS 1 Patient's Age 957 template<> 958 class Attribute<VR::AS, VM::VM5> 959 { 960 public: 961 char Internal[VMToLength<VM::VM5>::Length]; 962 void Print(std::ostream &_os) const { 963 _os << Internal; 964 } 965 }; 966 967 template <> 968 class Attribute<VR::OB, VM::VM1> : public Attribute<VR::OB, VM::VM1_n> {}; 969 // Make it impossible to compile any other cases: 970 template <int TVM> class Attribute<VR::OB, TVM>; 971 972 // Same for OW: 973 template <> 974 class Attribute<VR::OW, VM::VM1> : public Attribute<VR::OW, VM::VM1_n> {}; 975 // Make it impossible to compile any other cases: 976 template <int TVM> class Attribute<VR::OW, TVM>; 977 #endif 978 979 #if 0 980 template<> 981 class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1> 982 { 983 public: 984 char *Internal; 985 unsigned long Length; // unsigned int ?? 986 987 void Print(std::ostream &_os) const { 988 _os << Internal[0]; 989 } 990 void SetBytes(char *bytes, unsigned long length) { 991 Internal = bytes; 992 Length = length; 993 } 994 void Read(std::istream &_is) { 995 uint16_t c[2]; 996 _is.read((char*)&c, 4); 997 uint32_t l; 998 _is.read((char*)&l, 4); 999 Length = l; 1000 _is.read( Internal, Length ); 1001 } 1002 void Write(std::ostream &_os) const { 1003 uint16_t c[] = {0x7fe0, 0x0010}; 1004 _os.write((char*)&c, 4); 1005 _os.write((char*)&Length, 4); 1006 _os.write( Internal, Length ); 1007 } 1008 }; 1009 #endif 1010 1011 /* 1012 // Removing Attribute for SQ for now... 1013 template<uint16_t Group, uint16_t Element, typename SQA> 1014 class Attribute<Group,Element, VR::SQ, VM::VM1, SQA> 1015 { 1016 public: 1017 SQA sqa; 1018 void Print(std::ostream &_os) const { 1019 _os << Tag(Group,Element); 1020 sqa.Print(_os << std::endl << '\t'); 1021 } 1022 void Write(std::ostream &_os) const { 1023 uint16_t c[] = {Group, Element}; 1024 _os.write((char*)&c, 4); 1025 uint32_t undef = 0xffffffff; 1026 _os.write((char*)&undef, 4); 1027 uint16_t item_beg[] = {0xfffe,0xe000}; 1028 _os.write((char*)&item_beg, 4); 1029 _os.write((char*)&undef, 4); 1030 sqa.Write(_os); 1031 uint16_t item_end[] = {0xfffe,0xe00d}; 1032 _os.write((char*)&item_end, 4); 1033 uint32_t zero = 0x0; 1034 _os.write((char*)&zero, 4); 1035 uint16_t seq_end[] = {0xfffe, 0xe0dd}; 1036 _os.write((char*)&seq_end, 4); 1037 _os.write((char*)&zero, 4); 1038 } 1039 }; 1040 */ 1041 1042 /** 1043 * \example PatchFile.cxx 1044 * This is a C++ example on how to use gdcm::Attribute 1045 */ 1046 1047 } // namespace gdcm_ns 1048 1049 #endif //GDCMATTRIBUTE_H 1050