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 

Generated on Thu Apr 30 15:53:49 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5