GDCM  2.2.0
gdcmByteValue.h
Go to the documentation of this file.
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*)&copy[0], Internal.size() / sizeof(TType) );
00181       os.write(&copy[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

Generated on Fri May 25 2012 13:12:38 for GDCM by doxygen 1.8.0
SourceForge.net Logo