#ifndef AlpsEncoded_h #define AlpsEncoded_h #include #include #include #include #include "CoinError.hpp" #include "Alps.h" // AlpsEncoded is modified from BCP_buffer and CoinEncoded //############################################################################# /** This data structure is to contain the packed form of an encodable * knowledge. It servers two purposes: *
    *
  • used as a buffer when passing messages *
  • allow Alps to manipulate the user derived knowledge *
*/ //############################################################################# class AlpsEncoded { private: /** Disable copy constructor and assignment operator */ ///@{ AlpsEncoded(const AlpsEncoded&); AlpsEncoded& operator=(const AlpsEncoded&); ///@} private: /** The next read/write position in the representation. */ size_t pos_; /** The amount of memory allocated for the representation. */ size_t maxSize_; /** Represent the type of the object. We might use RTTI to point this into the static data of the executable :-) Can only be initialized during constructing. User take care of memory.*/ //std::string type_; int type_; /** The size of the packed representation. */ int size_; /** The encoded/compressed representation of the object. */ // const char* representation_; //why const ??? XY char* representation_; public: /**@name Constructors and destructor */ /*@{*/ /** The default constructor creates a buffer of size 16 Kbytes with no message in it. */ AlpsEncoded() : pos_(0), maxSize_(0x4000/*16K*/), type_(0), size_(0), representation_(new char[maxSize_]) {} /** Useful constructor. */ AlpsEncoded(int t) : pos_(0), maxSize_(0), type_(t), size_(0), representation_(0) {} /** Useful constructor. Take over ownership of r. */ AlpsEncoded(int t, int s, char*& r) : pos_(0), maxSize_(s + 4), type_(t), size_(s), representation_(r) { r = NULL; } /** Destructor. */ ~AlpsEncoded() { if (representation_) { delete [] representation_; representation_ = 0; } } /*@}*/ /**@name Query methods */ ///@{ int type() const { return type_; } int size() const { return size_; } const char* representation() const { return representation_; } ///@} inline void setPosition(const int pos) { if (pos < 0 || pos >= size()) { // const char msg [100] = "Incorrest position setting."; //throw AlpsException(__FILE__, __LINE__, msg); throw CoinError("Incorrest position setting.", "setPosition", "AlpsEncoded"); } pos_ = pos; } inline void setRepresentation(char*& buf) { //> 0x4000/*16K*/ ? (strlen(buf)+1) : 0x4000; maxSize_ = strlen(buf) + 1; representation_ = buf; buf = 0; } /** Reallocate the size of encoded if necessary so that at least addsize_ number of additional bytes will fit into the encoded. */ inline void make_fit(const int addSize){ assert(addSize > 0); size_t addSize1 = static_cast(addSize); if (maxSize_ < size_ + addSize1){ maxSize_ = 4 * (size_ + addSize1 + 0x1000/*4K*/); char* newRep = new char[maxSize_]; if (size_) memcpy(newRep, representation_, size_); delete[] representation_; representation_ = newRep; } } /** Completely clear the encoded. Delete and zero out type_, size_, pos_. */ inline void clear(){ size_ = 0; pos_ = 0; type_ = 0; if (representation_ != 0) { delete representation_; representation_ = 0; } } //------------------------------------------------------ // Following functiosn are used in parallel code only. //------------------------------------------------------ /** Write a single object of type T in repsentation_ . Copies sizeof(T) bytes from the address of the object. */ template AlpsEncoded& writeRep(const T& value) { make_fit( sizeof(T) ); memcpy(representation_ + size_, &value, sizeof(T)); size_ += sizeof(T); return *this; } /** Read a single object of type T from repsentation_ . Copies sizeof(T) bytes to the address of the object. */ template AlpsEncoded& readRep(T& value){ #ifdef PARANOID if (pos_ + sizeof(T) > size_) { throw CoinError("Reading over the end of buffer.", "readRep(const T& value)", "AlpsEncoded"); } #endif memcpy(&value, representation_ + pos_, sizeof(T)); pos_ += sizeof(T); return *this; } /** Write a C style array of objects of type T in repsentation_. First write the length, then write the content of the array */ template AlpsEncoded& writeRep(const T* const values, const int length){ make_fit( sizeof(int) + sizeof(T) * length ); memcpy(representation_ + size_, &length, sizeof(int)); size_ += sizeof(int); if (length > 0){ memcpy(representation_ + size_, values, sizeof(T) * length); size_ += sizeof(T) * length; } return *this; } /** Read an array of objects of type T from repsentation_, where T must be a built-in type (ar at least something that can be copied with memcpy). If the third argument is true then memory is allocated for the array and the array pointer and the length of the array are returned in the arguments. If the third argument is false then the arriving array's length is compared to length and an exception is thrown if they are not the same. Also, the array passed as the first argument will be filled with the arriving array. */ template AlpsEncoded& readRep(T*& values, int& length, bool needAllocateMemory = true) { if (needAllocateMemory) { // Need allocate memeory for arrary "values". #ifdef PARANOID if (pos_ + sizeof(int) > size_) { throw CoinError("Reading over the end of buffer.", "readRep(T*& values, int& length,...", "AlpsEncoded"); } #endif memcpy(&length, representation_ + pos_, sizeof(int)); pos_ += sizeof(int); if (length > 0){ #ifdef PARANOID if (pos_ + sizeof(T)*length > size_) { throw CoinError("Reading over the end of buffer.", "readRep(T*& values, int& length,...", "AlpsEncoded"); } #endif values = new T[length]; memcpy(values, representation_ + pos_, sizeof(T)*length); pos_ += sizeof(T) * length; } } else { /* values has been allocated memory. */ int l; #ifdef PARANOID if (pos_ + sizeof(int) > size_) { throw CoinError("Reading over the end of buffer.", "readRep(T*& values, int& length,...", "AlpsEncoded"); } #endif memcpy(&l, representation_ + pos_, sizeof(int)); pos_ += sizeof(int); if (l != length) { throw CoinError("Reading over the end of buffer.", "readRep(T*& values, int& length,...", "AlpsEncoded"); } if (length > 0){ #ifdef PARANOID if (pos_ + sizeof(T)*length > size_) { throw CoinError("Reading over the end of buffer.", "readRep(T*& values, int& length,...", "AlpsEncoded"); } #endif memcpy(values, representation_ + pos_, sizeof(T)*length); pos_ += sizeof(T) * length; } } return *this; } /** Read a std::string in repsentation_ . */ AlpsEncoded& writeRep(std::string& value){ // must define here, 'cos in *_message.C we have only templated members const int len = static_cast (value.length()); make_fit( sizeof(int) + len ); memcpy(representation_ + size_, &len, sizeof(int)); size_ += sizeof(int); if (len > 0){ memcpy(representation_ + size_, value.c_str(), len); size_ += len; } return *this; } /** Read a std::string from repsentation_ . */ AlpsEncoded& readRep(std::string& value){ int len; readRep(len); value.assign(representation_ + pos_, len); pos_ += len; return *this; } /** Write a std::vector into repsentation_ . */ template AlpsEncoded& writeRep(const std::vector& vec) { int objnum = vec.size(); int new_bytes = objnum * sizeof(T); make_fit( sizeof(int) + new_bytes ); memcpy(representation_ + size_, &objnum, sizeof(int)); size_ += sizeof(int); if (objnum > 0){ memcpy(representation_ + size_, &vec[0], new_bytes); size_ += new_bytes; } return *this; } /** Read a std::vector from repsentation_ . */ template AlpsEncoded& readRep(std::vector& vec) { int objnum; #ifdef PARANOID if (pos_ + sizeof(int) > size_) throw CoinError("Reading over the end of buffer.", "AlpsEncoded", "readRep(std::vector& vec"); #endif memcpy(&objnum, representation_ + pos_, sizeof(int)); pos_ += sizeof(int); vec.clear(); if (objnum > 0){ #ifdef PARANOID if (pos_ + sizeof(T)*objnum > size_) throw CoinError("Reading over the end of buffer.", "AlpsEncoded", "readRep(std::vector& vec"); #endif vec.insert(vec.end(), objnum, T()); memcpy(&vec[0], representation_ + pos_, objnum * sizeof(T)); pos_ += objnum * sizeof(T); } return *this; } /*@}*/ }; #endif