/export/leeloo1/users/build/gfcppsancout64/product/include/gfcpp/DataOutput.hpp

Go to the documentation of this file.
00001 #ifndef __GEMFIRE_DATAOUTPUT_H__
00002 #define __GEMFIRE_DATAOUTPUT_H__
00003 
00004 /*=========================================================================
00005  * (c) Copyright 2002-2007, GemStone Systems, Inc. All Rights Reserved.
00006  * 1260 NW Waterhouse Ave., Suite 200,  Beaverton, OR 97006
00007  *=========================================================================
00008  */
00009 
00010 #include "gfcpp_globals.hpp"
00011 #include "ExceptionTypes.hpp"
00012 #include "Log.hpp"
00013 #include "Serializable.hpp"
00014 #include "CacheableString.hpp"
00015 
00016 extern "C" {
00017 #include <string.h>
00018 #include <stdlib.h>
00019 }
00020 
00025 namespace gemfire {
00026 
00031 #define GF_ALLOC(v,t,s) \
00032 { \
00033   v = (t*)malloc((s) * sizeof(t)); \
00034   if ((v) == NULL) { \
00035     throw OutOfMemoryException( \
00036         "Out of Memory while allocating buffer for "#t" of size "#s); \
00037   } \
00038 }
00039 
00044 #define GF_RESIZE(v,t,s) \
00045 { \
00046   v = (t*)realloc(v, (s) * sizeof(t)); \
00047   if ((v) == NULL) { \
00048     throw OutOfMemoryException( \
00049         "Out of Memory while resizing buffer for "#t); \
00050   } \
00051 }
00052 
00053 #define GF_FREE(v) free(v)
00054 
00060 class CPPCACHE_EXPORT DataOutput
00061 {
00062 public:
00063 
00068   DataOutput();
00069 
00075   inline void write(uint8_t value)
00076   {
00077     ensureCapacity(1);
00078     writeNoCheck(value);
00079   }
00080 
00086   inline void write(int8_t value)
00087   {
00088     write((uint8_t)value);
00089   }
00090 
00096   inline void writeBoolean( bool value )
00097   {
00098     write( (uint8_t)value );
00099   }
00100 
00107   inline void writeBytes( const uint8_t* bytes, int32_t len )
00108   {
00109     if (len >= 0) {
00110       ensureCapacity( len + 5 );
00111       writeArrayLen( bytes==NULL ? 0 : len ); // length of bytes...
00112       if ( len > 0 && bytes != NULL) {
00113         memcpy( m_buf, bytes, len );
00114         m_buf += len;
00115       }
00116     } else {
00117       write((int8_t) -1 );
00118     }
00119   }
00120 
00127   inline void writeBytes( const int8_t* bytes, int32_t len )
00128   {
00129     writeBytes( (const uint8_t*)bytes, len );
00130   }
00131 
00143   inline void writeBytesOnly( const uint8_t* bytes, uint32_t len )
00144   {
00145     ensureCapacity( len );
00146     memcpy( m_buf, bytes, len );
00147     m_buf += len;
00148   }
00149 
00161   inline void writeBytesOnly( const int8_t* bytes, uint32_t len )
00162   {
00163     writeBytesOnly( (const uint8_t*)bytes, len );
00164   }
00165 
00171   inline void writeInt( uint16_t value )
00172   {
00173     ensureCapacity( 2 );
00174     *(m_buf++) = (uint8_t)(value >> 8);
00175     *(m_buf++) = (uint8_t)value;
00176   }
00177 
00183   inline void writeInt( uint32_t value )
00184   {
00185     ensureCapacity( 4 );
00186     *(m_buf++) = (uint8_t)(value >> 24);
00187     *(m_buf++) = (uint8_t)(value >> 16);
00188     *(m_buf++) = (uint8_t)(value >> 8);
00189     *(m_buf++) = (uint8_t)value;
00190   }
00191 
00197   inline void writeInt( uint64_t value )
00198   {
00199     ensureCapacity( 8 );
00200     // the defines are not reliable and can be changed by compiler options.
00201     // Hence using sizeof() test instead.
00202     //#if defined(_LP64) || ( defined(__WORDSIZE) && __WORDSIZE == 64 ) ||
00203     //( defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 )
00204     if ( sizeof( long ) == 8 ) {
00205       *(m_buf++) = (uint8_t)(value >> 56);
00206       *(m_buf++) = (uint8_t)(value >> 48);
00207       *(m_buf++) = (uint8_t)(value >> 40);
00208       *(m_buf++) = (uint8_t)(value >> 32);
00209       *(m_buf++) = (uint8_t)(value >> 24);
00210       *(m_buf++) = (uint8_t)(value >> 16);
00211       *(m_buf++) = (uint8_t)(value >> 8);
00212       *(m_buf++) = (uint8_t)value;
00213     } else {
00214       uint32_t hword = (uint32_t)(value >> 32);
00215       *(m_buf++) = (uint8_t)(hword >> 24);
00216       *(m_buf++) = (uint8_t)(hword >> 16);
00217       *(m_buf++) = (uint8_t)(hword >> 8);
00218       *(m_buf++) = (uint8_t)hword;
00219 
00220       hword = (uint32_t)value;
00221       *(m_buf++) = (uint8_t)(hword >> 24);
00222       *(m_buf++) = (uint8_t)(hword >> 16);
00223       *(m_buf++) = (uint8_t)(hword >> 8);
00224       *(m_buf++) = (uint8_t)hword;
00225     }
00226   }
00227 
00233   inline void writeInt( int16_t value )
00234   {
00235     writeInt( (uint16_t)value );
00236   }
00237 
00243   inline void writeInt( int32_t value )
00244   {
00245     writeInt( (uint32_t)value );
00246   }
00247 
00253   inline void writeInt( int64_t value )
00254   {
00255     writeInt( (uint64_t)value );
00256   }
00257 
00265   inline void writeArrayLen( int32_t len )
00266   {
00267     if (len == -1) {
00268       write((int8_t) -1);
00269     } else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF)
00270       write((uint8_t)len);
00271     } else if (len <= 0xFFFF) {
00272       write((int8_t) -2);
00273       writeInt((uint16_t)len);
00274     } else {
00275       write((int8_t) -3);
00276       writeInt(len);
00277     }
00278   }
00279 
00285   inline void writeFloat( float value )
00286   {
00287     union float_uint32_t
00288     {
00289         float f;
00290         uint32_t u;
00291     }v;
00292     v.f = value;
00293     writeInt( v.u );
00294   }
00295 
00301   inline void writeDouble( double value )
00302   {
00303     union double_uint64_t
00304     {
00305         double d;
00306         uint64_t        ll;
00307     }v;
00308     v.d =  value;
00309     writeInt( v.ll );
00310   }
00311 
00324   inline void writeASCII(const char* value, uint32_t length = 0)
00325   {
00326     if ( value != NULL ) {
00327       if ( length == 0 ) {
00328         length = (uint32_t)strlen( value );
00329       }
00330       uint16_t len = (uint16_t)( length > 0xFFFF ? 0xFFFF : length );
00331       writeInt( len );
00332       writeBytesOnly( (int8_t*)value, len ); // K64
00333     } else {
00334       writeInt( (uint16_t)0 );
00335     }
00336   }
00337 
00338   inline void writeNativeString(const char* value)
00339   {
00340     //create cacheable string
00341     //write typeid id.
00342     //call todata
00343     CacheableStringPtr csPtr = CacheableString::create(value);
00344     write(csPtr->typeId());
00345     csPtr->toData(*this);
00346   }
00347 
00359   inline void writeASCIIHuge(const char* value, uint32_t length = 0)
00360   {
00361     if ( value != NULL ) {
00362       if ( length == 0 ) {
00363         length = (uint32_t)strlen( value );
00364       }
00365       writeInt( (uint32_t) length );
00366       writeBytesOnly( (int8_t*)value, (uint32_t) length );
00367     } else {
00368       writeInt( (uint32_t)0 );
00369     }
00370   }
00371 
00383   inline void writeUTF(const char* value, uint32_t length = 0)
00384   {
00385     if ( value != NULL ) {
00386       int32_t len = getEncodedLength( value, length );
00387       uint16_t encodedLen = (uint16_t)( len > 0xFFFF ? 0xFFFF : len );
00388       writeInt( encodedLen );
00389       ensureCapacity( encodedLen );
00390       uint8_t* end = m_buf + encodedLen;
00391       while( m_buf < end ) {
00392         encodeChar( *value++ );
00393       }
00394       if ( m_buf > end ) m_buf = end;
00395     } else {
00396       writeInt( (uint16_t)0 );
00397     }
00398   }
00399 
00412   inline void writeUTFHuge(const char* value, uint32_t length = 0)
00413   {
00414     if (value != NULL) {
00415       if (length == 0) {
00416         length = (uint32_t)strlen(value);
00417       }
00418       writeInt(length);
00419       ensureCapacity(length * 2);
00420       for (uint32_t pos = 0; pos < length; pos++) {
00421         writeNoCheck((int8_t)0);
00422         writeNoCheck((int8_t)value[pos]);
00423       }
00424     }
00425     else {
00426       writeInt((uint32_t)0);
00427     }
00428   }
00429 
00441   inline void writeUTF(const wchar_t* value, uint32_t length = 0)
00442   {
00443     if ( value != NULL ) {
00444       int32_t len = getEncodedLength( value, length );
00445       uint16_t encodedLen = (uint16_t)( len > 0xFFFF ? 0xFFFF : len );
00446       writeInt( encodedLen );
00447       ensureCapacity( encodedLen );
00448       uint8_t* end = m_buf + encodedLen;
00449       while( m_buf < end ) {
00450         encodeChar( *value++ );
00451       }
00452       if ( m_buf > end ) m_buf = end;
00453     } else {
00454       writeInt( (uint16_t)0 );
00455     }
00456   }
00457 
00468   inline void writeUTFHuge(const wchar_t* value, uint32_t length = 0)
00469   {
00470     if (value != NULL) {
00471       if (length == 0) {
00472         length = (uint32_t)wcslen(value);
00473       }
00474       writeInt(length);
00475       ensureCapacity(length * 2);
00476       for (uint32_t pos = 0; pos < length; pos++) {
00477         uint16_t item = (uint16_t)value[pos];
00478         writeNoCheck((uint8_t)((item & 0xFF00) >> 8));
00479         writeNoCheck((uint8_t)(item & 0xFF));
00480       }
00481     }
00482     else {
00483       writeInt((uint32_t)0);
00484     }
00485   }
00486 
00497   inline static int32_t getEncodedLength( const char* value,
00498       int32_t length = 0, uint32_t* valLength = NULL )
00499   {
00500     if ( value == NULL ) return 0;
00501     uint8_t currentChar;
00502     int32_t encodedLen = 0;
00503     const char* start = value;
00504     if ( length == 0 ) {
00505       while ( (currentChar = *value) != '\0' ) {
00506         getEncodedLength( currentChar, encodedLen );
00507         value++;
00508       }
00509     } else {
00510       const char* end = value + length;
00511       while ( value < end ) {
00512         currentChar = *value;
00513         getEncodedLength( currentChar, encodedLen );
00514         value++;
00515       }
00516     }
00517     if ( valLength != NULL ) {
00518       *valLength = static_cast<uint32_t>(value - start);
00519     }
00520     return encodedLen;
00521   }
00522 
00533   inline static int32_t getEncodedLength( const wchar_t* value,
00534       int32_t length = 0, uint32_t* valLength = NULL )
00535   {
00536     if ( value == NULL ) return 0;
00537     uint16_t currentChar;
00538     int32_t encodedLen = 0;
00539     const wchar_t* start = value;
00540     if ( length == 0 ) {
00541       while ( (currentChar = *value) != 0 ) {
00542         getEncodedLength( currentChar, encodedLen );
00543         value++;
00544       }
00545     } else {
00546       const wchar_t* end = value + length;
00547       while ( value < end ) {
00548         currentChar = *value;
00549         getEncodedLength( currentChar, encodedLen );
00550         value++;
00551       }
00552     }
00553     if ( valLength != NULL ) {
00554       *valLength = static_cast<uint32_t>(value - start);
00555     }
00556     return encodedLen;
00557   }
00558 
00565   template< class PTR >
00566   void writeObject( const SharedPtr<PTR>& objptr, bool isDelta = false )
00567   {
00568     writeObjectInternal( objptr.ptr( ), isDelta );
00569   }
00570 
00577   void writeObject( const Serializable* objptr )
00578   {
00579     writeObjectInternal( objptr );
00580   }
00581 
00586   const uint8_t* getCursor()
00587   {
00588     return  m_buf;
00589   }
00590 
00596   void advanceCursor(uint32_t offset)
00597   {
00598     ensureCapacity(offset);
00599     m_buf += offset;
00600   }
00601 
00607   void rewindCursor(uint32_t offset)
00608   {
00609     m_buf -= offset;
00610   }
00611 
00613   ~DataOutput( )
00614   {
00615     reset();
00616     DataOutput::checkinBuffer(m_bytes, m_size);
00617   }
00618 
00622   inline const uint8_t* getBuffer( ) const
00623   {
00624     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00625     return m_bytes;
00626   }
00627 
00631   inline uint32_t getRemainingBufferLength( ) const
00632   {
00633     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00634     return m_size - getBufferLength();
00635   }
00636 
00643   inline const uint8_t* getBuffer( uint32_t* rsize ) const
00644   {
00645     *rsize = (uint32_t)( m_buf - m_bytes );
00646     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00647     return m_bytes;
00648   }
00649 
00650   inline uint8_t* getBufferCopy( )
00651   {
00652     uint32_t size = (uint32_t)( m_buf - m_bytes );
00653     uint8_t * result;
00654     GF_ALLOC(result, uint8_t, size);
00655     memcpy( result, m_bytes, size );
00656     return result;
00657   }
00658 
00663   inline uint32_t getBufferLength() const {
00664     return (uint32_t)( m_buf - m_bytes );
00665   }
00666 
00670   inline void reset()
00671   {
00672     if (m_haveBigBuffer) {
00673       // free existing buffer
00674       GF_FREE(m_bytes);
00675       // create smaller buffer
00676       GF_ALLOC(m_bytes, uint8_t, m_lowWaterMark);
00677       m_size = m_lowWaterMark;
00678       // reset the flag
00679       m_haveBigBuffer = false;
00680       // release the lock
00681       releaseLock();
00682     }
00683     m_buf = m_bytes;
00684   }
00685 
00686   // make sure there is room left for the requested size item.
00687   inline void ensureCapacity( uint32_t size )
00688   {
00689     uint32_t offset = (uint32_t)( m_buf - m_bytes );
00690     if ( (m_size - offset) < size ) {
00691       uint32_t newSize = m_size * 2 + (8192 * (size / 8192));
00692       if (newSize >= m_highWaterMark && !m_haveBigBuffer) {
00693         // acquire the lock
00694         acquireLock();
00695         // set flag
00696         m_haveBigBuffer = true;
00697       }
00698       m_size = newSize;
00699       GF_RESIZE( m_bytes, uint8_t, m_size );
00700       m_buf = m_bytes + offset;
00701     }
00702   }
00703 
00704    /*
00705    * This is for internal use
00706    */
00707   const char* getPoolName()
00708   {
00709     return m_poolName;
00710   }
00711 
00712   /*
00713    * This is for internal use
00714    */
00715   void setPoolName(const char* poolName)
00716   {
00717     m_poolName = poolName;
00718   }
00719 
00720   uint8_t * getBufferCopyFrom(const uint8_t *from, uint32_t length)
00721   {
00722     uint8_t * result;
00723     GF_NEW( result, uint8_t[ length ] );
00724     memcpy( result, from, length);
00725     
00726     return result;
00727   }
00728   
00729   static void safeDelete(uint8_t* src)
00730   {
00731     GF_SAFE_DELETE(src);
00732   }
00733 
00734   static DataOutput* getDataOutput()
00735   {
00736     return new DataOutput();
00737   }
00738   static void releaseDataOutput(DataOutput* dataOutput)
00739   {
00740     GF_SAFE_DELETE(dataOutput);
00741   }
00742 private:
00743 
00744   void writeObjectInternal( const Serializable* ptr, bool isDelta = false );
00745 
00746   static void acquireLock();
00747   static void releaseLock();
00748 
00749   
00750 
00751   const char* m_poolName;
00752   // memory m_buffer to encode to.
00753   uint8_t* m_bytes;
00754   // cursor.
00755   uint8_t* m_buf;
00756   // size of m_bytes.
00757   uint32_t m_size;
00758   // high and low water marks for buffer size
00759   static uint32_t m_lowWaterMark;
00760   static uint32_t m_highWaterMark;
00761   // flag to indicate we have a big buffer
00762   volatile bool m_haveBigBuffer;
00763 
00764   inline static void getEncodedLength( const uint8_t val, int32_t& encodedLen )
00765   {
00766     if ( (val == 0) || (val & 0x80) ) {
00767       // two byte.
00768       encodedLen += 2;
00769     } else {
00770       // one byte.
00771       encodedLen++;
00772     }
00773   }
00774 
00775   inline static void getEncodedLength( const uint16_t val, int32_t& encodedLen )
00776   {
00777     if( val == 0)
00778     {
00779       encodedLen += 2;
00780     }
00781     else if ( val < 0x80 )//ASCII character
00782     {
00783       encodedLen++;
00784     }
00785     else if ( val < 0x800 )
00786     {
00787       encodedLen += 2;
00788     }
00789     else
00790     {
00791        encodedLen += 3;
00792     }
00793   }
00794 
00795   inline void encodeChar( const char value )
00796   {
00797     uint8_t tmp = (uint8_t)value;
00798     if ( (tmp == 0) || (tmp & 0x80) ) {
00799       // two byte.
00800       *(m_buf++) = 0xc0 | ((tmp & 0xc0 ) >> 6);
00801       *(m_buf++) = 0x80 | (tmp & 0x3f );
00802     } else {
00803       // one byte.
00804       *(m_buf++) = tmp;
00805     }
00806   }
00807 
00808   // this will lose the character set encoding.
00809   inline void encodeChar( const wchar_t value )
00810   {
00811     uint16_t c = (uint16_t)value;
00812     if ( c == 0 ) {
00813       *(m_buf++) = 0xc0;
00814       *(m_buf++) = 0x80;
00815     }
00816     else if ( c < 0x80 ) {//ASCII character
00817       *(m_buf++) = (uint8_t)c;
00818     }
00819     else if ( c < 0x800 ) {
00820       *(m_buf++) = ( 0xC0 | c >> 6 );
00821       *(m_buf++) = ( 0x80 | c & 0x3F );
00822     }
00823     else {
00824       *(m_buf++) = ( 0xE0 | c >> 12 );
00825       *(m_buf++) = ( 0x80 | c >> 6 & 0x3F );
00826       *(m_buf++) = ( 0x80 | c & 0x3F );
00827     }
00828   }
00829 
00830   inline void writeNoCheck(uint8_t value)
00831   {
00832     *(m_buf++) = value;
00833   }
00834 
00835   inline void writeNoCheck(int8_t value)
00836   {
00837     writeNoCheck((uint8_t)value);
00838   }
00839 
00840 
00841   static uint8_t* checkoutBuffer( uint32_t* size );
00842   static void checkinBuffer( uint8_t* buffer, uint32_t size );
00843 
00844   // disable copy constructor and assignment
00845   DataOutput(const DataOutput&);
00846   DataOutput& operator =(const DataOutput&);
00847 };
00848 
00849 }
00850 
00851 #endif // __GEMFIRE_DATAOUTPUT_H__

GemFire C++ Cache API Documentation