# MessageBuffer.cc

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // CERTI - HLA RunTime Infrastructure
    00003 // Copyright (C) 2002-2005 ONERA
    00004 //
    00005 // This program is free software ; you can redistribute it and/or
    00006 // modify it under the terms of the GNU Lesser General Public License
    00007 // as published by the Free Software Foundation ; either version 2 of
    00008 // the License, or (at your option) any later version.
    00009 //
    00010 // This program is distributed in the hope that it will be useful, but
    00011 // WITHOUT ANY WARRANTY ; without even the implied warranty of
    00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    00013 // Lesser General Public License for more details.
    00014 //
    00015 // You should have received a copy of the GNU Lesser General Public
    00016 // License along with this program ; if not, write to the Free Software
    00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    00018 // USA
    00019 //
    00020 // ----------------------------------------------------------------------------
    00021
    00022 #include "MessageBuffer.hh"
    00023 #include "Exception.hh"
    00024 #include "PrettyDebug.hh"
    00025 #include <cassert>
    00026 #include <sstream>
    00027 #include <iomanip>
    00028 #include <cstring>
    00029
    00030 namespace certi {
    00031
    00032 static PrettyDebug D("MB","MB::");
    00033
    00034 const bool
    00035 MessageBuffer::HostIsBigEndian() {
    00036 #ifdef HOST_IS_BIG_ENDIAN
    00037     return true;
    00038 #else
    00039     return false;
    00040 #endif
    00041 }
    00042
    00043 const bool
    00044 MessageBuffer::HostIsLittleEndian() {
    00045 #ifdef HOST_IS_BIG_ENDIAN
    00046     return false;
    00047 #else
    00048     return true;
    00049 #endif
    00050 }
    00051
    00052 void
    00053 MessageBuffer::show(const void* data, uint32_t n) {
    00054    uint32_t i;
    00055    const uint8_t* u8data = reinterpret_cast<const uint8_t*>(data);
    00056    for (i=0;i<n;++i) {
    00057        if ((0==(i%2))&&(i>0)) {
    00058                printf(" ");
    00059        }
    00060        printf("%02X",u8data[i]);
    00061    }
    00062 }
    00063
    00064 const uint8_t MessageBuffer::reservedBytes = 5;
    00065
    00066 void MessageBuffer::initialize() {
    00067     buffer = NULL;
    00068     bufferMaxSize = DEFAULT_MESSAGE_BUFFER_SIZE;
    00069     bufferHasMyEndianness = true;
    00070     writeOffset  = reservedBytes;
    00071     readOffset   = reservedBytes;
    00072 } /* end of MessageBuffer::initialize() */
    00073
    00074 MessageBuffer::MessageBuffer() {
    00075     initialize();
    00076     reallocate(DEFAULT_MESSAGE_BUFFER_SIZE);
    00077 } /* end of MessageBuffer::MessageBuffer() */
    00078
    00079 MessageBuffer::MessageBuffer(uint32_t n) {
    00080     initialize();
    00081     reallocate(n);
    00082 } /* end of MessageBuffer::MessageBuffer(uint32_t) */
    00083
    00084 /*
    00085  * FIXME we may put a COMPILED FLAG here in order
    00086  * to prevent reallocation beside the first one (when buffer==NULL)
    00087  */
    00088 void MessageBuffer::reallocate(uint32_t n) {
    00089     uint8_t* oldbuf = buffer;
    00090     /* (re)allocation is done iff
    00091      *  - buffer is NULL (never allocated)
    00092      *  or
    00093      *  - requested size exceed current bufferMaxSize
    00094      */
    00095     if ((NULL==buffer) || (n > bufferMaxSize)) {
    00096         // FIXME should try/catch for alloc error
    00097         // ands wrap-up inside RTIinternalError
    00098         buffer = new uint8_t[n];
    00099         bufferMaxSize = n;
    00100         /*
    00101          * If oldbuf wasn't null then copy
    00102          * oldbuf in the new buf
    00103          * the writeOffset should be valid.
    00104          */
    00105         if (NULL!=oldbuf) {
    00106             memcpy(buffer, oldbuf, writeOffset);
    00107             delete[] oldbuf;
    00108             oldbuf = NULL;
    00109         } else {
    00110             updateReservedBytes();
    00111         }
    00112     }
    00113 } /* end of MessageBuffer::MessageBuffer(uint32_t) */
    00114
    00115 MessageBuffer::~MessageBuffer() {
    00116     if (NULL!=buffer) {
    00117         delete[] buffer;
    00118     }
    00119 } /* end of MessageBuffer::~MessageBuffer() */
    00120
    00121 uint32_t MessageBuffer::size() const {
    00122     return writeOffset;
    00123 }
    00124
    00125 uint32_t MessageBuffer::maxSize() const {
    00126     return bufferMaxSize;
    00127 }
    00128
    00129 void MessageBuffer::assumeBufferIsBigEndian() {
    00130     this->bufferHasMyEndianness = HostIsBigEndian();
    00131     buffer[0] = 0x01;
    00132 } /* end of MessageBuffer::assumeBufferIsBigEndian() */
    00133
    00134 void MessageBuffer::assumeBufferIsLittleEndian() {
    00135     this->bufferHasMyEndianness = HostIsLittleEndian();
    00136     buffer[0] = 0x00;
    00137 } /* end of MessageBuffer::assumeBufferIsLittleEndian() */
    00138
    00139 void MessageBuffer::reset() {
    00140     bufferHasMyEndianness = true;
    00141     writeOffset           = reservedBytes;
    00142     readOffset            = reservedBytes;
    00143     updateReservedBytes();
    00144 } /* MessageBuffer::resetBuffer() */
    00145
    00146 uint32_t MessageBuffer::resize(uint32_t newSize) {
    00147     reallocate(newSize);
    00148     return bufferMaxSize;
    00149 }
    00150
    00151 void MessageBuffer::assumeSize(uint32_t size) {
    00152     /* This is done in order to overflow
    00153      * buffer max size but this may well be
    00154      * an error (FIXME should throw an exception ?)
    00155      */
    00156     if (size <= bufferMaxSize) {
    00157         writeOffset       = size;
    00158     } else {
    00159         writeOffset       = bufferMaxSize;
    00160     }
    00161 }
    00162
    00163 void MessageBuffer::assumeSizeFromReservedBytes() {
    00164     uint32_t toBeAssumedSize;
    00165     /* verify endianity from reserved byte 0 */
    00166     if (buffer[0]==0x01) {
    00167         assumeBufferIsBigEndian();
    00168     } else {
    00169         assumeBufferIsLittleEndian();
    00170     }
    00171     /* read size from reserved bytes 1..4 */
    00172     readOffset = 1;
    00173     toBeAssumedSize = this->read_uint32();
    00174     /* reallocation may be needed */
    00175     reallocate(toBeAssumedSize);
    00176     assumeSize(toBeAssumedSize);
    00177 } /* end of assumeSizeFromReservedBytes */
    00178
    00179 void MessageBuffer::setSizeInReservedBytes(uint32_t n) {
    00180     uint32_t oldWR_Offset;
    00181     /* backup write Offset */
    00182     oldWR_Offset = writeOffset;
    00183     /* update size in reserved bytes */
    00184     writeOffset  = 1;
    00185     D.Out(pdTrace,"setSizeInReservedBytes(%u)",n);
    00186     write_uint32(n);
    00187     /* restore writeOffset */
    00188     writeOffset  = oldWR_Offset;
    00189 } /* end of setSizeInReservedBytes */
    00190
    00191 int32_t MessageBuffer::write_uint8s(const uint8_t* data, uint32_t n) {
    00192     D.Out(pdTrace,"write_uint8s(%p = [%u ...] , %d)",data,n>0?data[0]:0,n);
    00193
    00194     if (n >= (bufferMaxSize - writeOffset)) {
    00195         /* reallocate buffer on-demand */
    00196         reallocate(bufferMaxSize+ (n-(bufferMaxSize-writeOffset))
    00197                 + DEFAULT_MESSAGE_BUFFER_SIZE);
    00198     }
    00199     /* copy data */
    00200     memcpy(buffer+writeOffset, data, n);
    00201     /* update write offset */
    00202     writeOffset += n;
    00203     return (writeOffset-n);
    00204 } /* end of MessageBuffer::write_uint8s(uint8_t*, uint32_t) */
    00205
    00206 int32_t MessageBuffer::read_uint8s(uint8_t* data, uint32_t n) {
    00207     if (n + readOffset > writeOffset) {
    00208         std::stringstream smsg;
    00209         smsg << "read_uint8s::invalid read of size <" << n
    00210                 << "> inside a buffer of readable size <"
    00211                 << (int32_t)writeOffset-readOffset << "> (writeOffset="
    00212                 <<writeOffset << ",readOffset="<<readOffset <<").";
    00213         throw RTIinternalError(smsg.str().c_str());
    00214     }
    00215
    00216     memcpy(data, buffer+readOffset, n);
    00217     readOffset += n;
    00218     D.Out(pdTrace,"read_uint8s(%p = [%u ...], %d)",data,n>0?data[0]:0,n);
    00219     return (readOffset-n);
    00220 } /* end of MessageBuffer::read_uint8s(uint8_t*, uint32_t) */
    00221
    00222 int32_t MessageBuffer::write_uint16s(const uint16_t* data, uint32_t n) {
    00223     uint32_t i;
    00224     uint16_t an_uint16;
    00225     D.Out(pdTrace,"write_uint16s(%p = [%u ...], %d)",data,n>0?data[0]:0,n);
    00226
    00227     if ((2*n) >= (bufferMaxSize - writeOffset)) {
    00228         /* reallocate buffer on-demand */
    00229         reallocate(bufferMaxSize+ (2*n)-(bufferMaxSize - writeOffset)
    00230                 + DEFAULT_MESSAGE_BUFFER_SIZE);
    00231     }
    00232
    00233     /* do not swap byte if it is not necessary */
    00234     if (bufferHasMyEndianness) {
    00235         memcpy(buffer+writeOffset, data, 2*n);
    00236         writeOffset += 2*n;
    00237     } else {
    00238         for (i=0; i<n; ++i) {
    00239             an_uint16 = CERTI_UINT16_SWAP_BYTES(data[i]);
    00240             memcpy(buffer+writeOffset, &an_uint16, 2);
    00241             writeOffset += 2;
    00242         }
    00243     }
    00244     return (writeOffset-2*n);
    00245 } /* end of MessageBuffer::write_uint16s(uint16_t*, uint32_t) */
    00246
    00247 int32_t MessageBuffer::read_uint16s(uint16_t* data, uint32_t n) {
    00248     uint32_t i;
    00249     uint16_t an_uint16;
    00250
    00251     if (2*n + readOffset > writeOffset) {
    00252         std::stringstream smsg;
    00253         smsg << "read_uint16s::invalid read of size <" << 2*n
    00254                 << "> inside a buffer of readable size <"
    00255                 << (int32_t)writeOffset-readOffset << "> (writeOffset="
    00256                 <<writeOffset << ",readOffset="<<readOffset <<").";
    00257         throw RTIinternalError(smsg.str().c_str());
    00258     }
    00259
    00260     /* do not swap byte if it is not necessary */
    00261     if (bufferHasMyEndianness) {
    00262         memcpy(data, buffer+readOffset, 2*n);
    00263         readOffset += 2*n;
    00264     } else {
    00265         for (i=0; i<n; ++i) {
    00266             memcpy(&an_uint16, buffer+readOffset,2);
    00267             data[i] = CERTI_UINT16_SWAP_BYTES(an_uint16);
    00268             readOffset += 2;
    00269         }
    00270     }
    00271
    00272     D.Out(pdTrace,"read_uint16s(%p = [%u ...], %d)",data,n>0?data[0]:0,n);
    00273     return (readOffset-2*n);
    00274 } /* end of MessageBuffer::read_uint16s(uint16_t*, uint32_t) */
    00275
    00276 int32_t MessageBuffer::write_uint32s(const uint32_t* data, uint32_t n) {
    00277     uint32_t i;
    00278     uint32_t an_uint32;
    00279     D.Out(pdTrace,"write_uint32s(%p = [%u ...] , %d)",data,n>0?data[0]:0,n);
    00280
    00281     if ((4*n) >= (bufferMaxSize - writeOffset)) {
    00282         /* reallocate buffer on-demand */
    00283         reallocate(bufferMaxSize+ (4*n)-(bufferMaxSize - writeOffset)
    00284                 + DEFAULT_MESSAGE_BUFFER_SIZE);
    00285     }
    00286
    00287     /* do not swap byte if it is not necessary */
    00288     if (bufferHasMyEndianness) {
    00289         memcpy(buffer+writeOffset, data, 4*n);
    00290         writeOffset += 4*n;
    00291     } else {
    00292         for (i=0; i<n; ++i) {
    00293             an_uint32 = CERTI_UINT32_SWAP_BYTES(data[i]);
    00294             memcpy(buffer+writeOffset,&an_uint32,4);
    00295             writeOffset += 4;
    00296         }
    00297     }
    00298     return (writeOffset-4*n);
    00299 } /* end of write_uint32s */
    00300
    00301 int32_t MessageBuffer::read_uint32s(uint32_t* data, uint32_t n) {
    00302     uint32_t i;
    00303     uint32_t an_uint32;
    00304
    00305     if (4*n + readOffset > writeOffset) {
    00306         std::stringstream smsg;
    00307         smsg << "read_uint32s::invalid read of size <" << 4*n
    00308                 << "> inside a buffer of readable size <"
    00309                 << (int32_t)writeOffset-readOffset << "> (writeOffset="
    00310                 <<writeOffset << ",readOffset="<<readOffset <<").";
    00311         throw RTIinternalError(smsg.str().c_str());
    00312     }
    00313
    00314     /* do not swap byte if it is not necessary */
    00315     if (bufferHasMyEndianness) {
    00316         memcpy(data, buffer+readOffset, 4*n);
    00317         readOffset += 4*n;
    00318     } else {
    00319         for (i=0; i<n; ++i) {
    00320             memcpy(&an_uint32,buffer+readOffset,4);
    00321             data[i] = CERTI_UINT32_SWAP_BYTES(an_uint32);
    00322             readOffset += 4;
    00323         }
    00324     }
    00325     D.Out(pdTrace,"read_uint32s(%p = [%u ...], %d)",data,n>0?data[0]:0,n);
    00326     return (readOffset-4*n);
    00327 } /* end of read_uint32s */
    00328
    00329 int32_t MessageBuffer::write_uint64s(const uint64_t* data, uint32_t n) {
    00330     uint32_t i;
    00331     union deux32 {
    00332         uint32_t    ui32[2];
    00333         uint64_t    ui64;
    00334     } a_deux32;
    00335     uint32_t an_uint32;
    00336
    00337     D.Out(pdTrace,"write_uint64s(%p , %d)",data,n);
    00338
    00339     if ((8*n) >= (bufferMaxSize - writeOffset)) {
    00340         /* reallocate buffer on-demand */
    00341         reallocate(bufferMaxSize+ (8*n)-(bufferMaxSize - writeOffset)
    00342                 + DEFAULT_MESSAGE_BUFFER_SIZE);
    00343     }
    00344
    00345     /* do not swap byte if it is not necessary */
    00346     if (bufferHasMyEndianness) {
    00347         memcpy(buffer+writeOffset, data, 8*n);
    00348         writeOffset += 8*n;
    00349     } else {
    00350         for (i=0; i<n; ++i) {
    00351             a_deux32.ui64 = data[i];
    00352             an_uint32 = CERTI_UINT32_SWAP_BYTES(a_deux32.ui32[1]);
    00353             memcpy(buffer+writeOffset,&an_uint32,4);
    00354             writeOffset += 4;
    00355             an_uint32 = CERTI_UINT32_SWAP_BYTES(a_deux32.ui32[0]);
    00356             memcpy(buffer+writeOffset,&an_uint32,4);
    00357             writeOffset += 4;
    00358         }
    00359     }
    00360     return (writeOffset-8*n);
    00361 } /* end of write_uint64s */
    00362
    00363 int32_t MessageBuffer::read_uint64s(uint64_t* data, uint32_t n) {
    00364     uint32_t i;
    00365     union deux32 {
    00366             uint32_t    ui32[2];
    00367             uint64_t    ui64;
    00368     } a_deux32;
    00369     uint32_t an_uint32;
    00370     D.Out(pdTrace,"read_uint64s(%p , %d)",data,n);
    00371
    00372     if (8*n + readOffset > writeOffset) {
    00373         std::stringstream smsg;
    00374         smsg << "read_uint64s::invalid read of size <" << 4*n
    00375                 << "> inside a buffer of readable size <"
    00376                 << (int32_t)writeOffset-readOffset << "> (writeOffset="
    00377                 <<writeOffset << ",readOffset="<<readOffset <<").";
    00378         throw RTIinternalError(smsg.str().c_str());
    00379     }
    00380
    00381     /* do not swap byte if it is not necessary */
    00382     if (bufferHasMyEndianness) {
    00383         memcpy(data, buffer+readOffset, 8*n);
    00384         readOffset += 8*n;
    00385     } else {
    00386         for (i=0; i<n; ++i) {
    00387             memcpy(&an_uint32,buffer+readOffset,4);
    00388             a_deux32.ui32[1] = CERTI_UINT32_SWAP_BYTES(an_uint32);
    00389             readOffset += 4;
    00390
    00391             memcpy(&an_uint32,buffer+readOffset,4);
    00392             a_deux32.ui32[0] = CERTI_UINT32_SWAP_BYTES(an_uint32);
    00393             readOffset += 4;
    00394
    00395             data[i] = a_deux32.ui64;
    00396         }
    00397     }
    00398     return (readOffset-8*n);
    00399 }
    00400
    00401 int32_t MessageBuffer::write_floats(const float* data, uint32_t n) {
    00402     const uint32_t* data32;
    00403     D.Out(pdTrace,"write_floats(%p = [%f ...], %d)",data,n>0?data[0]:0,n);
    00404     data32 = reinterpret_cast<const uint32_t*>(data);
    00405     return write_uint32s(data32,n);
    00406 }
    00407
    00408 int32_t MessageBuffer::read_floats(float* data, uint32_t n) {
    00409     uint32_t* data32;
    00410     D.Out(pdTrace,"read_floats(%p , %d)",data,n);
    00411     data32 = reinterpret_cast<uint32_t*>(data);
    00412     return read_uint32s(data32,n);
    00413 }
    00414
    00415 int32_t MessageBuffer::write_doubles(const double* data, uint32_t n) {
    00416     const uint64_t* data64;
    00417     D.Out(pdTrace,"write_doubles(%p = [%f ...], %d)",data,n>0?data[0]:0,n);
    00418     data64 = reinterpret_cast<const uint64_t*>(data);
    00419     return write_uint64s(data64,n);
    00420 }
    00421
    00422 int32_t MessageBuffer::read_doubles(double* data, uint32_t n) {
    00423     uint64_t* data64;
    00424     D.Out(pdTrace,"read_doubles(%p , %d)",data,n);
    00425     data64 = reinterpret_cast<uint64_t*>(data);
    00426     return read_uint64s(data64,n);
    00427 }
    00428
    00429 int32_t
    00430 MessageBuffer::write_string(const std::string& str) {
    00431     write_int32(str.length());
    00432     return write_chars(str.data(),str.length());
    00433 } /* end of write_string */
    00434
    00435 std::string
    00436 MessageBuffer::read_string() {
    00437     std::string retval;
    00438     int32_t len;
    00439     char* buf;
    00440
    00441     read_int32(&len);
    00442     buf = new char[len];
    00443     read_chars(buf,len);
    00444     retval.assign(buf,len);
    00445     delete[] buf;
    00446     return retval;
    00447 } /* end of read_string */
    00448
    00449 void MessageBuffer::updateReservedBytes() {
    00450     /* set up buffer endianess */
    00451     if ((HostIsBigEndian() && bufferHasMyEndianness) ||
    00452         (HostIsLittleEndian() && !bufferHasMyEndianness)) {
    00453        buffer[0] = 0x01;
    00454     } else {
    00455        buffer[0] = 0x00;
    00456     }
    00457     /* set up size */
    00458     setSizeInReservedBytes(size());
    00459 } /* end of updateReservedBytes */
    00460
    00461 void*
    00462 MessageBuffer::operator ()(uint32_t offset) {
    00463     return buffer+offset;
    00464 }
    00465
    00466 //MessageBuffer::operator const void*(){
    00467 //  return buffer;
    00468 //}
    00469 //
    00470 //MessageBuffer::operator void*() {
    00471 //  return buffer;
    00472 //}
    00473
    00474
    00475 } // certi
    00476