/*========================================================================= 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 "gdcmByteValue.h" #include // req C++11 #include // memcpy namespace gdcm_ns { void ByteValue::SetLength(VL vl) { VL l(vl); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // CompressedLossy.dcm if( l.IsUndefined() ) throw Exception( "Impossible" ); if ( l.IsOdd() ) { gdcmDebugMacro( "BUGGY HEADER: Your dicom contain odd length value field." ); ++l; } #else gdcmAssertAlwaysMacro( !l.IsUndefined() && !l.IsOdd() ); #endif // I cannot use reserve for now. I need to implement: // STL - vector<> and istream // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74 //#define SHORT_READ_HACK try { #ifdef SHORT_READ_HACK if( l <= 0xff ) #endif Internal.resize(l); //Internal.reserve(l); } catch(...) { //throw Exception("Impossible to allocate: " << l << " bytes." ); throw Exception("Impossible to allocate" ); } // Keep the exact length Length = vl; } void ByteValue::PrintASCII(std::ostream &os, VL maxlength ) const { VL length = std::min(maxlength, Length); // Special case for VR::UI, do not print the trailing \0 if( length && length == Length ) { if( Internal[length-1] == 0 ) { length = length - 1; } } // I cannot check IsPrintable some file contains \2 or \0 in a VR::LO element // See: acr_image_with_non_printable_in_0051_1010.acr //assert( IsPrintable(length) ); std::vector::const_iterator it = Internal.begin(); for(; it != Internal.begin()+length; ++it) { const char &c = *it; if ( !( isprint((unsigned char)c) || isspace((unsigned char)c) ) ) os << "."; else os << c; } } void ByteValue::PrintHex(std::ostream &os, VL maxlength ) const { VL length = std::min(maxlength, Length); // WARNING: Internal.end() != Internal.begin()+Length std::vector::const_iterator it = Internal.begin(); os << std::hex; for(; it != Internal.begin()+length; ++it) { //const char &c = *it; uint8_t v = *it; if( it != Internal.begin() ) os << "\\"; os << std::setw( 2 ) << std::setfill( '0' ) << (uint16_t)v; //++it; //os << std::setw( 1 ) << std::setfill( '0' ) << (int)*it; } os << std::dec; } bool ByteValue::GetBuffer(char *buffer, unsigned long length) const { // SIEMENS_GBS_III-16-ACR_NEMA_1.acr has a weird pixel length // so we need an inequality if( length <= Internal.size() ) { if(!Internal.empty()) memcpy(buffer, &Internal[0], length); return true; } gdcmDebugMacro( "Could not handle length= " << length ); return false; } void ByteValue::PrintPNXML(std::ostream &os) const { /* PersonName = element PersonName { Number, element SingleByte { NameComponents }?, element Ideographic { NameComponents }?, element Phonetic { NameComponents }? } NameComponents = element FamilyName {xsd:string}?, element GivenName {xsd:string}?, element MiddleName {xsd:string}?, element NamePrefix {xsd:string}?, element NameSuffix {xsd:string}? */ int count1 , count2; count1=count2=1; os << "\n" ; os << "\n " ; std::vector::const_iterator it = Internal.begin(); for(; it != (Internal.begin() + Length); ++it) { const char &c = *it; if ( c == '^' ) { if(count2==1) { os << "\n"; os << " "; count2++; } if(count2==2) { os << "\n"; os << " "; count2++; } else if(count2==3) { os << "\n"; os << " "; count2++; } else if(count2==4) { os << "\n"; os << " "; count2++; } else { //in the rare case there are more ^ characters assert("Name components exceeded"); } } else if ( c == '=' ) { if(count2==1) { os << "\n"; } if(count2==2) { os << "\n"; } else if(count2==3) { os << "\n"; } else if(count2==4) { os << "\n"; } else if(count2==5) { os << "\n"; } /*----------------------------------------------------------------*/ if(count1==1) { os << "\n"; os << " \n "; count1++; } else if(count1==2) { os << "\n"; os << " \n "; count1++; } else if(count1==3) { os << " \n \n"; count1++; } else { assert("Impossible - only 3 names allowed"); } count2=1; } else if ( !( isprint((unsigned char)c) ) ) os << "."; else if(c == '&') os << "&"; else if(c == '<') os << "<"; else if(c == '>') os << ">"; else if(c == '\'') os << "'"; else if(c == '\"') os << """; else os << c; } if(count2==1) { os << "\n"; } if(count2==2) { os << "\n"; } else if(count2==3) { os << "\n"; } else if(count2==4) { os << "\n"; } else if(count2==5) { os << "\n"; } if(count1==1) { os << "\n"; } else if(count1==2) { os << "\n"; } else if(count1==3) { os << "\n"; } os << ""; } void ByteValue::PrintASCIIXML(std::ostream &os) const { //VL length = std::min(maxlength, Length); // Special case for VR::UI, do not print the trailing \0 /*if(Length && Internal[Length-1] == 0 ) { Length = Length - 1; } */ // Check for non printable characters int count = 1; os << ""; std::vector::const_iterator it = Internal.begin(); for(; it != (Internal.begin() + Length); ++it) { const char &c = *it; if ( c == '\\' ) { count++; os << "\n"; os << ""; } else if ( !c ) { // \0 is found ... } else if(c == '&') os << "&"; else if(c == '<') os << "<"; else if(c == '>') os << ">"; else if(c == '\'') os << "'"; else if(c == '\"') os << """; else os << c; } os << "\n"; } void ByteValue::PrintHexXML(std::ostream &os ) const { //VL length = std::min(maxlength, Length); // WARNING: Internal.end() != Internal.begin()+Length std::vector::const_iterator it = Internal.begin(); os << std::hex; for(; it != Internal.begin() + Length; ++it) { //const char &c = *it; uint8_t v = *it; if( it != Internal.begin() ) os << "\\"; os << std::setw( 2 ) << std::setfill( '0' ) << (uint16_t)v; //++it; //os << std::setw( 1 ) << std::setfill( '0' ) << (int)*it; } os << std::dec; } void ByteValue::Append(ByteValue const & bv) { //Internal.resize( Length + bv.Length ); Internal.insert( Internal.end(), bv.Internal.begin(), bv.Internal.end()); Length += bv.Length; // post condition assert( Internal.size() % 2 == 0 && Internal.size() == Length ); } } // end namespace gdcm_ns