build-artifacts/win/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  * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
00006  * This product is protected by U.S. and international copyright
00007  * and intellectual property laws. Pivotal products are covered by
00008  * more patents listed at http://www.pivotal.io/patents.
00009  *=========================================================================
00010  */
00011 
00012 #include "gfcpp_globals.hpp"
00013 #include "ExceptionTypes.hpp"
00014 #include "Log.hpp"
00015 #include "Serializable.hpp"
00016 #include "CacheableString.hpp"
00017 
00018 extern "C" {
00019 #include <string.h>
00020 #include <stdlib.h>
00021 }
00022 
00027 namespace gemfire {
00028 
00033 #define GF_ALLOC(v,t,s) \
00034 { \
00035   v = (t*)malloc((s) * sizeof(t)); \
00036   if ((v) == NULL) { \
00037     throw OutOfMemoryException( \
00038         "Out of Memory while allocating buffer for "#t" of size "#s); \
00039   } \
00040 }
00041 
00046 #define GF_RESIZE(v,t,s) \
00047 { \
00048   v = (t*)realloc(v, (s) * sizeof(t)); \
00049   if ((v) == NULL) { \
00050     throw OutOfMemoryException( \
00051         "Out of Memory while resizing buffer for "#t); \
00052   } \
00053 }
00054 
00055 #define GF_FREE(v) free(v)
00056 
00062 class CPPCACHE_EXPORT DataOutput
00063 {
00064 public:
00065 
00070   DataOutput();
00071 
00077   inline void write(uint8_t value)
00078   {
00079     ensureCapacity(1);
00080     writeNoCheck(value);
00081   }
00082 
00088   inline void write(int8_t value)
00089   {
00090     write((uint8_t)value);
00091   }
00092 
00098   inline void writeBoolean( bool value )
00099   {
00100     write( (uint8_t)value );
00101   }
00102 
00109   inline void writeBytes( const uint8_t* bytes, int32_t len )
00110   {
00111     if (len >= 0) {
00112       ensureCapacity( len + 5 );
00113       writeArrayLen( bytes==NULL ? 0 : len ); // length of bytes...
00114       if ( len > 0 && bytes != NULL) {
00115         memcpy( m_buf, bytes, len );
00116         m_buf += len;
00117       }
00118     } else {
00119       write((int8_t) -1 );
00120     }
00121   }
00122 
00129   inline void writeBytes( const int8_t* bytes, int32_t len )
00130   {
00131     writeBytes( (const uint8_t*)bytes, len );
00132   }
00133 
00145   inline void writeBytesOnly( const uint8_t* bytes, uint32_t len )
00146   {
00147     ensureCapacity( len );
00148     memcpy( m_buf, bytes, len );
00149     m_buf += len;
00150   }
00151 
00163   inline void writeBytesOnly( const int8_t* bytes, uint32_t len )
00164   {
00165     writeBytesOnly( (const uint8_t*)bytes, len );
00166   }
00167 
00173   inline void writeInt( uint16_t value )
00174   {
00175     ensureCapacity( 2 );
00176     *(m_buf++) = (uint8_t)(value >> 8);
00177     *(m_buf++) = (uint8_t)value;
00178   }
00179 
00185   inline void writeChar( uint16_t value )
00186   {
00187     ensureCapacity( 2 );
00188     *(m_buf++) = (uint8_t)(value >> 8);
00189     *(m_buf++) = (uint8_t)value;
00190   }
00191 
00197   inline void writeInt( uint32_t value )
00198   {
00199     ensureCapacity( 4 );
00200     *(m_buf++) = (uint8_t)(value >> 24);
00201     *(m_buf++) = (uint8_t)(value >> 16);
00202     *(m_buf++) = (uint8_t)(value >> 8);
00203     *(m_buf++) = (uint8_t)value;
00204   }
00205 
00211   inline void writeInt( uint64_t value )
00212   {
00213     ensureCapacity( 8 );
00214     // the defines are not reliable and can be changed by compiler options.
00215     // Hence using sizeof() test instead.
00216     //#if defined(_LP64) || ( defined(__WORDSIZE) && __WORDSIZE == 64 ) ||
00217     //( defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 )
00218     if ( sizeof( long ) == 8 ) {
00219       *(m_buf++) = (uint8_t)(value >> 56);
00220       *(m_buf++) = (uint8_t)(value >> 48);
00221       *(m_buf++) = (uint8_t)(value >> 40);
00222       *(m_buf++) = (uint8_t)(value >> 32);
00223       *(m_buf++) = (uint8_t)(value >> 24);
00224       *(m_buf++) = (uint8_t)(value >> 16);
00225       *(m_buf++) = (uint8_t)(value >> 8);
00226       *(m_buf++) = (uint8_t)value;
00227     } else {
00228       uint32_t hword = (uint32_t)(value >> 32);
00229       *(m_buf++) = (uint8_t)(hword >> 24);
00230       *(m_buf++) = (uint8_t)(hword >> 16);
00231       *(m_buf++) = (uint8_t)(hword >> 8);
00232       *(m_buf++) = (uint8_t)hword;
00233 
00234       hword = (uint32_t)value;
00235       *(m_buf++) = (uint8_t)(hword >> 24);
00236       *(m_buf++) = (uint8_t)(hword >> 16);
00237       *(m_buf++) = (uint8_t)(hword >> 8);
00238       *(m_buf++) = (uint8_t)hword;
00239     }
00240   }
00241 
00247   inline void writeInt( int16_t value )
00248   {
00249     writeInt( (uint16_t)value );
00250   }
00251 
00257   inline void writeInt( int32_t value )
00258   {
00259     writeInt( (uint32_t)value );
00260   }
00261 
00267   inline void writeInt( int64_t value )
00268   {
00269     writeInt( (uint64_t)value );
00270   }
00271 
00279   inline void writeArrayLen( int32_t len )
00280   {
00281     if (len == -1) {
00282       write((int8_t) -1);
00283     } else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF)
00284       write((uint8_t)len);
00285     } else if (len <= 0xFFFF) {
00286       write((int8_t) -2);
00287       writeInt((uint16_t)len);
00288     } else {
00289       write((int8_t) -3);
00290       writeInt(len);
00291     }
00292   }
00293 
00299   inline void writeFloat( float value )
00300   {
00301     union float_uint32_t
00302     {
00303         float f;
00304         uint32_t u;
00305     }v;
00306     v.f = value;
00307     writeInt( v.u );
00308   }
00309 
00315   inline void writeDouble( double value )
00316   {
00317     union double_uint64_t
00318     {
00319         double d;
00320         uint64_t        ll;
00321     }v;
00322     v.d =  value;
00323     writeInt( v.ll );
00324   }
00325 
00338   inline void writeASCII(const char* value, uint32_t length = 0)
00339   {
00340     if ( value != NULL ) {
00341       if ( length == 0 ) {
00342         length = (uint32_t)strlen( value );
00343       }
00344       uint16_t len = (uint16_t)( length > 0xFFFF ? 0xFFFF : length );
00345       writeInt( len );
00346       writeBytesOnly( (int8_t*)value, len ); // K64
00347     } else {
00348       writeInt( (uint16_t)0 );
00349     }
00350   }
00351 
00352   inline void writeNativeString(const char* value)
00353   {
00354     //create cacheable string
00355     //write typeid id.
00356     //call todata
00357     CacheableStringPtr csPtr = CacheableString::create(value);
00358     write(csPtr->typeId());
00359     csPtr->toData(*this);
00360   }
00361 
00373   inline void writeASCIIHuge(const char* value, uint32_t length = 0)
00374   {
00375     if ( value != NULL ) {
00376       if ( length == 0 ) {
00377         length = (uint32_t)strlen( value );
00378       }
00379       writeInt( (uint32_t) length );
00380       writeBytesOnly( (int8_t*)value, (uint32_t) length );
00381     } else {
00382       writeInt( (uint32_t)0 );
00383     }
00384   }
00385 
00386 
00397   inline void writeFullUTF(const char* value, uint32_t length = 0)
00398   {
00399     if ( value != NULL ) {
00400       int32_t len = getEncodedLength( value, length );
00401       uint16_t encodedLen = (uint16_t)( len > 0xFFFF ? 0xFFFF : len );
00402       writeInt( (int32_t)encodedLen );
00403       ensureCapacity( encodedLen );
00404       write((int8_t)0); // isObject = 0 BYTE_CODE
00405       uint8_t* end = m_buf + encodedLen;
00406       while( m_buf < end ) {
00407         encodeChar( *value++ );
00408       }
00409       if ( m_buf > end ) m_buf = end;
00410     } else {
00411       writeInt( (uint16_t)0 );
00412     }
00413   }
00414 
00426   inline void writeUTF(const char* value, uint32_t length = 0)
00427   {
00428     if ( value != NULL ) {
00429       int32_t len = getEncodedLength( value, length );
00430       uint16_t encodedLen = (uint16_t)( len > 0xFFFF ? 0xFFFF : len );
00431       writeInt( encodedLen );
00432       ensureCapacity( encodedLen );
00433       uint8_t* end = m_buf + encodedLen;
00434       while( m_buf < end ) {
00435         encodeChar( *value++ );
00436       }
00437       if ( m_buf > end ) m_buf = end;
00438     } else {
00439       writeInt( (uint16_t)0 );
00440     }
00441   }
00442 
00455   inline void writeUTFHuge(const char* value, uint32_t length = 0)
00456   {
00457     if (value != NULL) {
00458       if (length == 0) {
00459         length = (uint32_t)strlen(value);
00460       }
00461       writeInt(length);
00462       ensureCapacity(length * 2);
00463       for (uint32_t pos = 0; pos < length; pos++) {
00464         writeNoCheck((int8_t)0);
00465         writeNoCheck((int8_t)value[pos]);
00466       }
00467     }
00468     else {
00469       writeInt((uint32_t)0);
00470     }
00471   }
00472 
00484   inline void writeUTF(const wchar_t* value, uint32_t length = 0)
00485   {
00486     if ( value != NULL ) {
00487       int32_t len = getEncodedLength( value, length );
00488       uint16_t encodedLen = (uint16_t)( len > 0xFFFF ? 0xFFFF : len );
00489       writeInt( encodedLen );
00490       ensureCapacity( encodedLen );
00491       uint8_t* end = m_buf + encodedLen;
00492       while( m_buf < end ) {
00493         encodeChar( *value++ );
00494       }
00495       if ( m_buf > end ) m_buf = end;
00496     } else {
00497       writeInt( (uint16_t)0 );
00498     }
00499   }
00500 
00511   inline void writeUTFHuge(const wchar_t* value, uint32_t length = 0)
00512   {
00513     if (value != NULL) {
00514       if (length == 0) {
00515         length = (uint32_t)wcslen(value);
00516       }
00517       writeInt(length);
00518       ensureCapacity(length * 2);
00519       for (uint32_t pos = 0; pos < length; pos++) {
00520         uint16_t item = (uint16_t)value[pos];
00521         writeNoCheck((uint8_t)((item & 0xFF00) >> 8));
00522         writeNoCheck((uint8_t)(item & 0xFF));
00523       }
00524     }
00525     else {
00526       writeInt((uint32_t)0);
00527     }
00528   }
00529 
00540   inline static int32_t getEncodedLength( const char* value,
00541       int32_t length = 0, uint32_t* valLength = NULL )
00542   {
00543     if ( value == NULL ) return 0;
00544     char currentChar;
00545     int32_t encodedLen = 0;
00546     const char* start = value;
00547     if ( length == 0 ) {
00548       while ( (currentChar = *value) != '\0' ) {
00549         getEncodedLength( currentChar, encodedLen );
00550         value++;
00551       }
00552     } else {
00553       const char* end = value + length;
00554       while ( value < end ) {
00555         currentChar = *value;
00556         getEncodedLength( currentChar, encodedLen );
00557         value++;
00558       }
00559     }
00560     if ( valLength != NULL ) {
00561       *valLength = static_cast<uint32_t>(value - start);
00562     }
00563     return encodedLen;
00564   }
00565 
00576   inline static int32_t getEncodedLength( const wchar_t* value,
00577       int32_t length = 0, uint32_t* valLength = NULL )
00578   {
00579     if ( value == NULL ) return 0;
00580     wchar_t currentChar;
00581     int32_t encodedLen = 0;
00582     const wchar_t* start = value;
00583     if ( length == 0 ) {
00584       while ( (currentChar = *value) != 0 ) {
00585         getEncodedLength( currentChar, encodedLen );
00586         value++;
00587       }
00588     } else {
00589       const wchar_t* end = value + length;
00590       while ( value < end ) {
00591         currentChar = *value;
00592         getEncodedLength( currentChar, encodedLen );
00593         value++;
00594       }
00595     }
00596     if ( valLength != NULL ) {
00597       *valLength = static_cast<uint32_t>(value - start);
00598     }
00599     return encodedLen;
00600   }
00601 
00608   template< class PTR >
00609   void writeObject( const SharedPtr<PTR>& objptr, bool isDelta = false )
00610   {
00611     writeObjectInternal( objptr.ptr( ), isDelta );
00612   }
00613 
00620   void writeObject( const Serializable* objptr )
00621   {
00622     writeObjectInternal( objptr );
00623   }
00624 
00629   const uint8_t* getCursor()
00630   {
00631     return  m_buf;
00632   }
00633 
00639   void advanceCursor(uint32_t offset)
00640   {
00641     ensureCapacity(offset);
00642     m_buf += offset;
00643   }
00644 
00650   void rewindCursor(uint32_t offset)
00651   {
00652     m_buf -= offset;
00653   }
00654 
00655   void updateValueAtPos(uint32_t offset, uint8_t value)
00656   {
00657     m_bytes[offset] = value;
00658   }
00659 
00660   uint8_t getValueAtPos(uint32_t offset)
00661   {
00662     return m_bytes[offset];
00663   }
00665   ~DataOutput( )
00666   {
00667     reset();
00668     DataOutput::checkinBuffer(m_bytes, m_size);
00669   }
00670 
00674   inline const uint8_t* getBuffer( ) const
00675   {
00676     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00677     return m_bytes;
00678   }
00679 
00683   inline uint32_t getRemainingBufferLength( ) const
00684   {
00685     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00686     return m_size - getBufferLength();
00687   }
00688 
00695   inline const uint8_t* getBuffer( uint32_t* rsize ) const
00696   {
00697     *rsize = (uint32_t)( m_buf - m_bytes );
00698     //GF_R_ASSERT(!((uint32_t)(m_bytes) % 4));
00699     return m_bytes;
00700   }
00701 
00702   inline uint8_t* getBufferCopy( )
00703   {
00704     uint32_t size = (uint32_t)( m_buf - m_bytes );
00705     uint8_t * result;
00706     GF_ALLOC(result, uint8_t, size);
00707     memcpy( result, m_bytes, size );
00708     return result;
00709   }
00710 
00715   inline uint32_t getBufferLength() const {
00716     return (uint32_t)( m_buf - m_bytes );
00717   }
00718 
00722   inline void reset()
00723   {
00724     if (m_haveBigBuffer) {
00725       // free existing buffer
00726       GF_FREE(m_bytes);
00727       // create smaller buffer
00728       GF_ALLOC(m_bytes, uint8_t, m_lowWaterMark);
00729       m_size = m_lowWaterMark;
00730       // reset the flag
00731       m_haveBigBuffer = false;
00732       // release the lock
00733       releaseLock();
00734     }
00735     m_buf = m_bytes;
00736   }
00737 
00738   // make sure there is room left for the requested size item.
00739   inline void ensureCapacity( uint32_t size )
00740   {
00741     uint32_t offset = (uint32_t)( m_buf - m_bytes );
00742     if ( (m_size - offset) < size ) {
00743       uint32_t newSize = m_size * 2 + (8192 * (size / 8192));
00744       if (newSize >= m_highWaterMark && !m_haveBigBuffer) {
00745         // acquire the lock
00746         acquireLock();
00747         // set flag
00748         m_haveBigBuffer = true;
00749       }
00750       m_size = newSize;
00751       GF_RESIZE( m_bytes, uint8_t, m_size );
00752       m_buf = m_bytes + offset;
00753     }
00754   }
00755 
00756    /*
00757    * This is for internal use
00758    */
00759   const char* getPoolName()
00760   {
00761     return m_poolName;
00762   }
00763 
00764   /*
00765    * This is for internal use
00766    */
00767   void setPoolName(const char* poolName)
00768   {
00769     m_poolName = poolName;
00770   }
00771 
00772   uint8_t * getBufferCopyFrom(const uint8_t *from, uint32_t length)
00773   {
00774     uint8_t * result;
00775     GF_NEW( result, uint8_t[ length ] );
00776     memcpy( result, from, length);
00777     
00778     return result;
00779   }
00780   
00781   static void safeDelete(uint8_t* src)
00782   {
00783     GF_SAFE_DELETE(src);
00784   }
00785 
00786   static DataOutput* getDataOutput()
00787   {
00788     return new DataOutput();
00789   }
00790   static void releaseDataOutput(DataOutput* dataOutput)
00791   {
00792     GF_SAFE_DELETE(dataOutput);
00793   }
00794 private:
00795 
00796   void writeObjectInternal( const Serializable* ptr, bool isDelta = false );
00797 
00798   static void acquireLock();
00799   static void releaseLock();
00800 
00801   
00802 
00803   const char* m_poolName;
00804   // memory m_buffer to encode to.
00805   uint8_t* m_bytes;
00806   // cursor.
00807   uint8_t* m_buf;
00808   // size of m_bytes.
00809   uint32_t m_size;
00810   // high and low water marks for buffer size
00811   static uint32_t m_lowWaterMark;
00812   static uint32_t m_highWaterMark;
00813   // flag to indicate we have a big buffer
00814   volatile bool m_haveBigBuffer;
00815 
00816   inline static void getEncodedLength( const char val, int32_t& encodedLen )
00817   {
00818     if ( (val == 0) || (val & 0x80) ) {
00819       // two byte.
00820       encodedLen += 2;
00821     } else {
00822       // one byte.
00823       encodedLen++;
00824     }
00825   }
00826 
00827   inline static void getEncodedLength( const wchar_t val, int32_t& encodedLen )
00828   {
00829     if( val == 0)
00830     {
00831       encodedLen += 2;
00832     }
00833     else if ( val < 0x80 )//ASCII character
00834     {
00835       encodedLen++;
00836     }
00837     else if ( val < 0x800 )
00838     {
00839       encodedLen += 2;
00840     }
00841     else
00842     {
00843        encodedLen += 3;
00844     }
00845   }
00846 
00847   inline void encodeChar( const char value )
00848   {
00849     uint8_t tmp = (uint8_t)value;
00850     if ( (tmp == 0) || (tmp & 0x80) ) {
00851       // two byte.
00852       *(m_buf++) = (uint8_t)(0xc0 | ((tmp & 0xc0 ) >> 6));
00853       *(m_buf++) = (uint8_t)(0x80 | (tmp & 0x3f ));
00854     } else {
00855       // one byte.
00856       *(m_buf++) = tmp;
00857     }
00858   }
00859 
00860   // this will lose the character set encoding.
00861   inline void encodeChar( const wchar_t value )
00862   {
00863     uint16_t c = (uint16_t)value;
00864     if ( c == 0 ) {
00865       *(m_buf++) = 0xc0;
00866       *(m_buf++) = 0x80;
00867     }
00868     else if ( c < 0x80 ) {//ASCII character
00869       *(m_buf++) = (uint8_t)c;
00870     }
00871     else if ( c < 0x800 ) {
00872       *(m_buf++) = (uint8_t)( 0xC0 | c >> 6 );
00873       *(m_buf++) = (uint8_t)( 0x80 | (c & 0x3F) );
00874     }
00875     else {
00876       *(m_buf++) = (uint8_t)( 0xE0 | c >> 12 );
00877       *(m_buf++) = (uint8_t)( 0x80 | ((c >> 6) & 0x3F) );
00878       *(m_buf++) = (uint8_t)( 0x80 | (c & 0x3F) );
00879     }
00880   }
00881 
00882   inline void writeNoCheck(uint8_t value)
00883   {
00884     *(m_buf++) = value;
00885   }
00886 
00887   inline void writeNoCheck(int8_t value)
00888   {
00889     writeNoCheck((uint8_t)value);
00890   }
00891 
00892 
00893   static uint8_t* checkoutBuffer( uint32_t* size );
00894   static void checkinBuffer( uint8_t* buffer, uint32_t size );
00895 
00896   // disable copy constructor and assignment
00897   DataOutput(const DataOutput&);
00898   DataOutput& operator =(const DataOutput&);
00899 };
00900 
00901 }
00902 
00903 #endif // __GEMFIRE_DATAOUTPUT_H__

GemFire C++ Cache API Documentation