# gdcmByteValue.h

Go to the documentation of this file.

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