/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "gdcmVM.h" #include #include // abort #include // strcmp namespace gdcm { static const char *VMStrings[] = { "INVALID", "1", "2", "3", "4", "5", "6", "8", "9", "10", "12", "16", "18", "24", "28", "32", "35", "99", "256", "1-2", "1-3", "1-4", "1-5", "1-8", "1-32", "1-99", "1-n", "2-2n", "2-n", "3-4", "3-3n", "3-n", "4-4n", "6-6n", "7-7n", "30-30n", "47-47n", nullptr }; unsigned int VM::GetLength() const { unsigned int len; switch(VMField) { case VM::VM1: len = VMToLength::Length; break; case VM::VM2: len = VMToLength::Length; break; case VM::VM3: len = VMToLength::Length; break; case VM::VM4: len = VMToLength::Length; break; case VM::VM5: len = VMToLength::Length; break; case VM::VM6: len = VMToLength::Length; break; case VM::VM8: len = VMToLength::Length; break; case VM::VM9: len = VMToLength::Length; break; case VM::VM10: len = VMToLength::Length; break; case VM::VM12: len = VMToLength::Length; break; case VM::VM16: len = VMToLength::Length; break; case VM::VM18: len = VMToLength::Length; break; case VM::VM24: len = VMToLength::Length; break; case VM::VM28: len = VMToLength::Length; break; case VM::VM32: len = VMToLength::Length; break; case VM::VM35: len = VMToLength::Length; break; case VM::VM99: len = VMToLength::Length; break; case VM::VM256: len = VMToLength::Length; break; case VM::VM0: case VM::VM1_2: case VM::VM1_3: case VM::VM1_4: case VM::VM1_5: case VM::VM1_8: case VM::VM1_32: case VM::VM1_99: case VM::VM1_n: case VM::VM2_2n: case VM::VM2_n: case VM::VM3_4: case VM::VM3_3n: case VM::VM3_n: case VM::VM4_4n: case VM::VM6_6n: case VM::VM7_7n: return 0; default: len = 0; assert(0); } assert( len ); return len; } unsigned int VM::GetIndex(VMType vm) { assert( vm <= VM_END ); unsigned int l; switch(vm) { case VM0: l = 0; break; case VM1_2: l = 19; break; case VM1_3: l = 20; break; case VM1_4: l = 21; break; case VM1_5: l = 22; break; case VM1_8: l = 23; break; case VM1_32: l = 24; break; case VM1_99: l = 25; break; case VM1_n: l = 26; break; case VM2_2n: l = 27; break; case VM2_n: l = 28; break; case VM3_4: l = 29; break; case VM3_3n: l = 30; break; case VM3_n: l = 31; break; case VM4_4n: l = 32; break; case VM6_6n: l = 33; break; case VM7_7n: l = 34; break; case VM30_30n: l = 35; break; case VM47_47n: l = 36; break; case VM_END: l = 37; break; default: { unsigned int a = (unsigned int)vm; for (l = 0; a > 1; ++l) a >>= 1; l++; } } return l; } const char *VM::GetVMString(VMType vm) { unsigned int idx = GetIndex(vm); assert( idx < sizeof(VMStrings) / sizeof(VMStrings[0]) ); //assert( idx ); return VMStrings[idx]; } VM::VMType VM::GetVMType(const char *vm) { if(!vm) return VM::VM_END; if(!*vm) return VM::VM0; // ?? for (int i = 0; VMStrings[i] != nullptr; i++) { //if (strncmp(VMStrings[i],vm,strlen(VMStrings[i])) == 0) if (strcmp(VMStrings[i],vm) == 0) { return (VM::VMType)(i); } } return VM::VM_END; } // FIXME IsValid will only work for VM defined in public dict... bool VM::IsValid(int vm1, VMType vm2) { bool r = false; assert( vm1 >= 0 ); // Still need to check Part 3 // If you update the VMType, you need to update this code. Hopefully a compiler is // able to tell when a case is missing switch(vm2) { case VM1: r = vm1 == 1; break; case VM2: r = vm1 == 2; break; case VM3: r = vm1 == 3; break; case VM4: r = vm1 == 4; break; case VM5: r = vm1 == 5; break; case VM6: r = vm1 == 6; break; case VM8: r = vm1 == 8; break; case VM16: r = vm1 == 16; break; case VM24: r = vm1 == 24; break; case VM1_2: r = (vm1 == 1 || vm1 == 2); break; case VM1_3: r = (vm1 >= 1 && vm1 <= 3); break; case VM1_8: r = (vm1 >= 1 && vm1 <= 8); break; case VM1_32: r = (vm1 >= 1 && vm1 <= 32); break; case VM1_99: r = (vm1 >= 1 && vm1 <= 99); break; case VM1_n: r = (vm1 >= 1); break; case VM2_2n: r = (vm1 >= 2 && !(vm1%2) ); break; case VM2_n: r = (vm1 >= 2); break; case VM3_3n: r = (vm1 >= 3 && !(vm1%3) ); break; case VM3_n: r = (vm1 >= 3); break; default: assert(0); // should not happen } return r; } // TODO write some ugly macro to expand the template //int VM::GetLength() //{ //} // This function should not be used in production code. // Indeed this only return a 'guess' at the VM (ie. a lower bound) VM::VMType VM::GetVMTypeFromLength(size_t length, unsigned int size) { // Check first of length is a indeed a multiple of size and that length is != 0 if ( !length || length % size ) return VM::VM0; const unsigned int ratio = (unsigned int)(length / size); //std::cerr << "RATIO=" << ratio << std::endl; switch( ratio ) { case 1: return VM::VM1; case 2: return VM::VM2; case 3: return VM::VM3; case 4: return VM::VM4; case 5: return VM::VM5; case 6: return VM::VM6; case 8: return VM::VM8; case 9: return VM::VM9; case 16: return VM::VM16; case 24: return VM::VM24; case 32: return VM::VM32; default: return VM::VM1_n; } } size_t VM::GetNumberOfElementsFromArray(const char *array, size_t length) { size_t c=0; if( !length || !array ) return 0; const char *parray = array; const char *end = array + length; bool valuefound = false; for(; parray != end; ++parray) { if( *parray == ' ' ) { // space char do not count } else if( *parray == '\\' ) { if( valuefound ) { ++c; valuefound = false; // reset counter } } else { valuefound = true; } } if( valuefound ) ++c; return c; } bool VM::Compatible(VM const &vm) const { // make sure that vm is a numeric value //assert( vm.VMField <= VM256 ); if ( VMField == VM::VM0 ) return false; // nothing was found in the dict if ( vm == VM::VM0 ) return true; // the user was not able to compute the vm from the empty bytevalue // let's start with the easy case: if ( VMField == vm.VMField ) return true; bool r; switch(VMField) { case VM1_2: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM2; break; case VM1_3: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM3; break; case VM1_8: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM8; break; case VM1_32: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM32; break; case VM1_99: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM99; break; case VM1_n: r = vm.VMField >= VM::VM1; break; case VM2_2n: { if( vm == VM1_n ) r = true; // FIXME else r = vm.VMField >= VM::VM2 && !(vm.GetLength() % 2); } break; case VM2_n: r = vm.VMField >= VM::VM2; break; case VM3_4: r = vm.VMField == VM::VM3 || vm.VMField == VM::VM4; break; case VM3_3n: r = vm.VMField >= VM::VM3 && !(vm.GetLength() % 3); break; case VM3_n: r = vm.VMField >= VM::VM3; break; default: r = VMField == vm.VMField; } if( r ) { assert( VMField & vm.VMField ); } return r; } } // end namespace gdcm