/*========================================================================= 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. =========================================================================*/ #ifndef GDCMBYTEVALUE_H #define GDCMBYTEVALUE_H #include "gdcmValue.h" #include "gdcmTrace.h" #include "gdcmVL.h" #include #include #include #include namespace gdcm_ns { #if !defined(SWIGPYTHON) && !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPHP) using namespace gdcm; #endif /** * \brief Class to represent binary value (array of bytes) * \note */ class GDCM_EXPORT ByteValue : public Value { public: ByteValue(const char* array = nullptr, VL const &vl = 0): Internal(array, array+vl),Length(vl) { if( vl.IsOdd() ) { gdcmDebugMacro( "Odd length" ); Internal.resize(vl+1); ++Length; } } /// \warning casting to uint32_t ByteValue(std::vector &v):Internal(v),Length((uint32_t)v.size()) {} //ByteValue(std::ostringstream const &os) { // (void)os; // assert(0); // TODO //} ~ByteValue() override { Internal.clear(); } // When 'dumping' dicom file we still have some information from // Either the VR: eg LO (private tag) void PrintASCII(std::ostream &os, VL maxlength ) const; void PrintHex(std::ostream &os, VL maxlength) const; // Either from Element Number (== 0x0000) void PrintGroupLength(std::ostream &os) { assert( Length == 2 ); (void)os; } bool IsEmpty() const { #if 0 if( Internal.empty() ) assert( Length == 0 ); return Internal.empty(); #else return Length == 0; #endif } VL GetLength() const override { return Length; } VL ComputeLength() const { return Length + Length % 2; } // Does a reallocation void SetLength(VL vl) override; operator const std::vector& () const { return Internal; } ByteValue &operator=(const ByteValue &val) { Internal = val.Internal; Length = val.Length; return *this; } bool operator==(const ByteValue &val) const { if( Length != val.Length ) return false; if( Internal == val.Internal ) return true; return false; } bool operator==(const Value &val) const override { const ByteValue &bv = dynamic_cast(val); return Length == bv.Length && Internal == bv.Internal; } void Append(ByteValue const & bv); void Clear() override { Internal.clear(); } // Use that only if you understand what you are doing const char *GetPointer() const { if(!Internal.empty()) return &Internal[0]; return nullptr; } // Use that only if you really understand what you are doing const void *GetVoidPointer() const { if(!Internal.empty()) return &Internal[0]; return nullptr; } void *GetVoidPointer() { if(!Internal.empty()) return &Internal[0]; return nullptr; } void Fill(char c) { //if( Internal.empty() ) return; std::vector::iterator it = Internal.begin(); for(; it != Internal.end(); ++it) *it = c; } bool GetBuffer(char *buffer, unsigned long length) const; bool WriteBuffer(std::ostream &os) const { if( Length ) { //assert( Internal.size() <= Length ); assert( !(Internal.size() % 2) ); os.write(&Internal[0], Internal.size() ); } return true; } template std::istream &Read(std::istream &is, bool readvalues = true) { // If Length is odd we have detected that in SetLength // and calling std::vector::resize make sure to allocate *AND* // initialize values to 0 so we are sure to have a \0 at the end // even in this case if(Length) { if( readvalues ) { is.read(&Internal[0], Length); assert( Internal.size() == Length || Internal.size() == Length + 1 ); TSwap::SwapArray((TType*)GetVoidPointer(), Internal.size() / sizeof(TType) ); } else { is.seekg(Length, std::ios::cur); } } return is; } template std::istream &Read(std::istream &is) { return Read(is); } template std::ostream const &Write(std::ostream &os) const { assert( !(Internal.size() % 2) ); if( !Internal.empty() ) { //os.write(&Internal[0], Internal.size()); std::vector copy = Internal; TSwap::SwapArray((TType*)(void*)©[0], Internal.size() / sizeof(TType) ); os.write(©[0], copy.size()); } return os; } template std::ostream const &Write(std::ostream &os) const { return Write(os); } /** * \brief Checks whether a 'ByteValue' is printable or not (in order * to avoid corrupting the terminal of invocation when printing) * I don't think this function is working since it does not handle * UNICODE or character set... */ bool IsPrintable(VL length) const { assert( length <= Length ); for(unsigned int i=0; i::size_type length = Length; if( Internal.back() == 0 ) --length; std::copy(Internal.begin(), Internal.begin()+length, std::ostream_iterator(os)); } else os << "Loaded:" << Internal.size(); } else { //os << "Not Loaded"; os << "(no value available)"; } } /* //Introduce check for invalid XML characters friend std::ostream& operator<<(std::ostream &os,const char c); */ void SetLengthOnly(VL vl) override { Length = vl; } private: std::vector Internal; // WARNING Length IS NOT Internal.size() some *featured* DICOM // implementation define odd length, we always load them as even number // of byte, so we need to keep the right Length VL Length; }; } // end namespace gdcm_ns #endif //GDCMBYTEVALUE_H