GDCM
2.2.3
|
00001 /*========================================================================= 00002 00003 Program: GDCM (Grassroots DICOM). A DICOM library 00004 00005 Copyright (c) 2006-2011 Mathieu Malaterre 00006 All rights reserved. 00007 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. 00008 00009 This software is distributed WITHOUT ANY WARRANTY; without even 00010 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00011 PURPOSE. See the above copyright notice for more information. 00012 00013 =========================================================================*/ 00014 #ifndef GDCMBYTEVALUE_H 00015 #define GDCMBYTEVALUE_H 00016 00017 #include "gdcmValue.h" 00018 #include "gdcmTrace.h" 00019 #include "gdcmVL.h" 00020 00021 #include <vector> 00022 #include <iterator> 00023 #include <iomanip> 00024 00025 //#include <stdlib.h> // abort 00026 00027 namespace gdcm 00028 { 00033 class GDCM_EXPORT ByteValue : public Value 00034 { 00035 public: 00036 ByteValue(const char* array = 0, VL const &vl = 0): 00037 Internal(array, array+vl),Length(vl) { 00038 if( vl.IsOdd() ) 00039 { 00040 gdcmDebugMacro( "Odd length" ); 00041 Internal.resize(vl+1); 00042 Length++; 00043 } 00044 } 00045 00047 ByteValue(std::vector<char> &v):Internal(v),Length((uint32_t)v.size()) {} 00048 //ByteValue(std::ostringstream const &os) { 00049 // (void)os; 00050 // assert(0); // TODO 00051 //} 00052 ~ByteValue() { 00053 Internal.clear(); 00054 } 00055 00056 // When 'dumping' dicom file we still have some information from 00057 // Either the VR: eg LO (private tag) 00058 void PrintASCII(std::ostream &os, VL maxlength ) const; 00059 00060 void PrintHex(std::ostream &os, VL maxlength) const; 00061 00062 // Either from Element Number (== 0x0000) 00063 void PrintGroupLength(std::ostream &os) { 00064 assert( Length == 2 ); 00065 (void)os; 00066 } 00067 00068 bool IsEmpty() const { 00069 if( Internal.empty() ) assert( Length == 0 ); 00070 return Internal.empty(); 00071 } 00072 VL GetLength() const { return Length; } 00073 // Does a reallocation 00074 void SetLength(VL vl) { 00075 VL l(vl); 00076 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00077 // CompressedLossy.dcm 00078 if( l.IsUndefined() ) throw Exception( "Impossible" ); 00079 if ( l.IsOdd() ) { 00080 gdcmDebugMacro( 00081 "BUGGY HEADER: Your dicom contain odd length value field." ); 00082 ++l; 00083 } 00084 #else 00085 assert( !l.IsUndefined() && !l.IsOdd() ); 00086 #endif 00087 // I cannot use reserve for now. I need to implement: 00088 // STL - vector<> and istream 00089 // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74 00090 //#define SHORT_READ_HACK 00091 try 00092 { 00093 #ifdef SHORT_READ_HACK 00094 if( l <= 0xff ) 00095 #endif 00096 Internal.resize(l); 00097 //Internal.reserve(l); 00098 } 00099 catch(...) 00100 { 00101 //throw Exception("Impossible to allocate: " << l << " bytes." ); 00102 throw Exception("Impossible to allocate" ); 00103 } 00104 // Keep the exact length 00105 Length = vl; 00106 } 00107 00108 operator const std::vector<char>& () const { return Internal; } 00109 00110 ByteValue &operator=(const ByteValue &val) { 00111 Internal = val.Internal; 00112 Length = val.Length; 00113 return *this; 00114 } 00115 00116 bool operator==(const ByteValue &val) const { 00117 if( Length != val.Length ) 00118 return false; 00119 if( Internal == val.Internal ) 00120 return true; 00121 return false; 00122 } 00123 bool operator==(const Value &val) const 00124 { 00125 const ByteValue &bv = dynamic_cast<const ByteValue&>(val); 00126 return Length == bv.Length && Internal == bv.Internal; 00127 } 00128 00129 00130 void Clear() { 00131 Internal.clear(); 00132 } 00133 // Use that only if you understand what you are doing 00134 const char *GetPointer() const { 00135 if(!Internal.empty()) return &Internal[0]; 00136 return 0; 00137 } 00138 void Fill(char c) { 00139 //if( Internal.empty() ) return; 00140 std::vector<char>::iterator it = Internal.begin(); 00141 for(; it != Internal.end(); ++it) *it = c; 00142 } 00143 bool GetBuffer(char *buffer, unsigned long length) const; 00144 bool WriteBuffer(std::ostream &os) const { 00145 if( Length ) { 00146 //assert( Internal.size() <= Length ); 00147 assert( !(Internal.size() % 2) ); 00148 os.write(&Internal[0], Internal.size() ); 00149 } 00150 return true; 00151 } 00152 00153 template <typename TSwap, typename TType> 00154 std::istream &Read(std::istream &is) { 00155 // If Length is odd we have detected that in SetLength 00156 // and calling std::vector::resize make sure to allocate *AND* 00157 // initialize values to 0 so we are sure to have a \0 at the end 00158 // even in this case 00159 if(Length) 00160 { 00161 is.read(&Internal[0], Length); 00162 assert( Internal.size() == Length || Internal.size() == Length + 1 ); 00163 TSwap::SwapArray((TType*)&Internal[0], Internal.size() / sizeof(TType) ); 00164 } 00165 return is; 00166 } 00167 00168 template <typename TSwap> 00169 std::istream &Read(std::istream &is) { 00170 return Read<TSwap,uint8_t>(is); 00171 } 00172 00173 00174 template <typename TSwap, typename TType> 00175 std::ostream const &Write(std::ostream &os) const { 00176 assert( !(Internal.size() % 2) ); 00177 if( !Internal.empty() ) { 00178 //os.write(&Internal[0], Internal.size()); 00179 std::vector<char> copy = Internal; 00180 TSwap::SwapArray((TType*)©[0], Internal.size() / sizeof(TType) ); 00181 os.write(©[0], copy.size()); 00182 } 00183 return os; 00184 } 00185 00186 template <typename TSwap> 00187 std::ostream const &Write(std::ostream &os) const { 00188 return Write<TSwap,uint8_t>(os); 00189 } 00190 00197 bool IsPrintable(VL length) const { 00198 assert( length <= Length ); 00199 for(unsigned int i=0; i<length; i++) 00200 { 00201 if ( i == (length-1) && Internal[i] == '\0') continue; 00202 if ( !( isprint((unsigned char)Internal[i]) || isspace((unsigned char)Internal[i]) ) ) 00203 { 00204 //gdcmWarningMacro( "Cannot print :" << i ); 00205 return false; 00206 } 00207 } 00208 return true; 00209 } 00210 00211 protected: 00212 void Print(std::ostream &os) const { 00213 // This is perfectly valid to have a Length = 0 , so we cannot check 00214 // the length for printing 00215 if( !Internal.empty() ) 00216 { 00217 if( IsPrintable(Length) ) 00218 { 00219 // WARNING: Internal.end() != Internal.begin()+Length 00220 std::vector<char>::size_type length = Length; 00221 if( Internal.back() == 0 ) --length; 00222 std::copy(Internal.begin(), Internal.begin()+length, 00223 std::ostream_iterator<char>(os)); 00224 } 00225 else 00226 os << "Loaded:" << Internal.size(); 00227 } 00228 else 00229 { 00230 //os << "Not Loaded"; 00231 os << "(no value available)"; 00232 } 00233 } 00234 00235 00236 private: 00237 std::vector<char> Internal; 00238 00239 // WARNING Length IS NOT Internal.size() some *featured* DICOM 00240 // implementation define odd length, we always load them as even number 00241 // of byte, so we need to keep the right Length 00242 VL Length; 00243 }; 00244 00245 } // end namespace gdcm 00246 00247 #endif //GDCMBYTEVALUE_H