GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

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