# HLAbuffer.hh

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // HLAbuffer.hh - IEEE 1516.2 compliant datatypes
    00003 // Copyright (C) 2008  Petr Gotthard <petr.gotthard@centrum.cz>
    00004 //
    00005 // This library is free software; you can redistribute it and/or
    00006 // modify it under the terms of the GNU Lesser General Public
    00007 // License version 2.1, as published by the Free Software Foundation.
    00008 //
    00009 // This library is distributed in the hope that it will be useful,
    00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012 // Lesser General Public License for more details.
    00013 //
    00014 // $Id: HLAbuffer.hh,v 1.9 2009/04/02 19:58:10 erk Exp $
    00015 // ----------------------------------------------------------------------------
    00016
    00017 #ifndef _HLATYPES_BUFFER_HH
    00018 #define _HLATYPES_BUFFER_HH
    00019
    00020 #include <iostream>
    00021 #include <map>
    00022 #include <stdexcept>
    00023 #include <cstdlib>
    00024
    00025 #ifdef _MSC_VER
    00026 typedef unsigned __int64  uint64_t;
    00027 typedef __int64           int64_t;
    00028 typedef unsigned __int32  uint32_t;
    00029 typedef __int32           int32_t;
    00030 typedef unsigned __int16  uint16_t;
    00031 typedef __int16           int16_t;
    00032 typedef unsigned __int8   uint8_t;
    00033 typedef __int8            int8_t;
    00034 #else
    00035 #include <inttypes.h>
    00036 #endif
    00037
    00038 #if defined(_WIN32)
    00039     #pragma warning(disable: 4251)
    00040     #if defined(HLA_EXPORTS)
    00041         #define HLA_EXPORT __declspec(dllexport)
    00042     #else
    00043         #define HLA_EXPORT __declspec(dllimport)
    00044     #endif
    00045 #else
    00046     #define HLA_EXPORT
    00047 #endif
    00048
    00049 namespace libhla {
    00050
    00051 HLA_EXPORT std::ostream& __print_buffer(std::ostream& stream, const void *buffer, size_t length);
    00052
    00053 /* Caution:
    00054  * This implementation assumes that there are no compiler-generated data in
    00055  * the heap memory allocated for the __HLAbuffer struct.
    00056  * All structures must have no virtual functions and no non-static members.
    00057  */
    00058
    00059 class HLA_EXPORT __HLAbuffer
    00060 {
    00061 private:
    00062     // static buffer for all instantiations of the HLAdata template
    00063     // indexed by "last pointers", i.e. pointers to the last byte in the buffer
    00064     typedef std::map<char*,__HLAbuffer*> BufferList;
    00065     static BufferList gBuffers;
    00066
    00067     // used to verify that user set correct endianess
    00068     static const bool __is_big_endian();
    00069     static const bool __is_little_endian();
    00070
    00071     void __assert_endianess()
    00072     {
    00073 #ifdef HOST_IS_BIG_ENDIAN
    00074         if (!__is_big_endian())
    00075             throw std::runtime_error("compile without -DHOST_IS_BIG_ENDIAN");
    00076 #else
    00077         if (!__is_little_endian())
    00078             throw std::runtime_error("compile with -DHOST_IS_BIG_ENDIAN");
    00079 #endif
    00080     }
    00081
    00082 public:
    00083     char *mBegin;
    00084     size_t mCapacity;
    00085     // no automatic free() and realloc() for user allocated memory
    00086     bool mUserAllocated;
    00087     // parameters used during dynamic resizing
    00088     const void* mShakeThat;
    00089     int mShakeValue;
    00090
    00091     __HLAbuffer(size_t capacity)
    00092      : mUserAllocated(false), mShakeThat(NULL)
    00093     {
    00094         __assert_endianess();
    00095         // exponential growth: capacity *= 1.5
    00096         mCapacity = (size_t)(capacity*1.5);
    00097         mBegin = (char*)calloc(1, mCapacity);
    00098         // store "this" to a global table
    00099         gBuffers[mBegin + mCapacity-1] = this;
    00100     }
    00101
    00102     __HLAbuffer(void *begin, size_t capacity)
    00103       : mBegin((char*)begin), mCapacity(capacity), mUserAllocated(true), mShakeThat(NULL)
    00104     {
    00105         __assert_endianess();
    00106         // store "this" to a global table
    00107         gBuffers[mBegin + mCapacity-1] = this;
    00108     }
    00109
    00110     virtual ~__HLAbuffer()
    00111     {
    00112         if (!mUserAllocated)
    00113             free(mBegin);
    00114         // remove "this" from the global table
    00115         gBuffers.erase(__buffer_iterator(mBegin));
    00116     }
    00117
    00118     void __exchange_buffers(__HLAbuffer& newBuffer)
    00119     {
    00120         char* oldBegin = mBegin;
    00121         size_t oldCapacity = mCapacity;
    00122
    00123         mBegin = newBuffer.mBegin;
    00124         mCapacity = newBuffer.mCapacity;
    00125         gBuffers[mBegin + mCapacity-1] = this; // update
    00126
    00127         newBuffer.mBegin = oldBegin;
    00128         newBuffer.mCapacity = oldCapacity;
    00129         gBuffers[oldBegin + oldCapacity-1] = &newBuffer; // update
    00130     }
    00131
    00132     static BufferList::iterator __buffer_iterator(const void* __this)
    00133     {
    00134         // find the first pointer not less than "this", the last pointer
    00135         BufferList::iterator result = gBuffers.lower_bound((char*)__this);
    00136         if (result == gBuffers.end())
    00137             throw std::runtime_error("HLAdata: bad pointer");
    00138         return result;
    00139     }
    00140
    00141     static __HLAbuffer& __buffer(const void* __this)
    00142     { return *(__buffer_iterator(__this)->second); }
    00143
    00144 #ifndef NDEBUG
    00145     static void __check_memory(const void* __this, size_t size)
    00146     {
    00147         const __HLAbuffer& buffer = __buffer(__this);
    00148         if ((char*)__this + size > (char*)buffer.mBegin + buffer.mCapacity)
    00149             throw std::length_error("HLAdata: data buffer overflow");
    00150     }
    00151 #endif
    00152
    00153     virtual const size_t size() const = 0;
    00154     virtual void __shake(const void* __that, int value, long resize) = 0;
    00155
    00156     static void shake(const void* __that, int value, long resize)
    00157     { __buffer(__that).__shake(__that, value, resize); }
    00158
    00159     const char* data() const
    00160     { return mBegin; }
    00161
    00162     std::ostream& print(std::ostream& stream)
    00163     {
    00164 #ifndef NDEBUG
    00165         __check_memory(mBegin, size());
    00166 #endif
    00167         return __print_buffer(stream, mBegin, size());
    00168     }
    00169 };
    00170
    00171 #ifndef MAX
    00172 #define MAX(a,b) (((a)>(b))?(a):(b))
    00173 #endif
    00174
    00175 /* Calculate the smallest nonnegative value of P that satisfies the following
    00176  * formula: (offset+size+P) mod boundary = 0
    00177  */
    00178 inline size_t __padding(size_t size, size_t boundary)
    00179 { return boundary - ((size-1)%boundary + 1); }
    00180
    00181 } // namespace libhla
    00182
    00183 #endif // _HLATYPES_BUFFER_HH
    00184
    00185 // $Id: HLAbuffer.hh,v 1.9 2009/04/02 19:58:10 erk Exp $
    00186