| #pragma once |
| |
| #ifndef GEODE_GFCPP_DATAOUTPUT_H_ |
| #define GEODE_GFCPP_DATAOUTPUT_H_ |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "gfcpp_globals.hpp" |
| #include "ExceptionTypes.hpp" |
| #include "Log.hpp" |
| #include "Serializable.hpp" |
| #include "CacheableString.hpp" |
| |
| extern "C" { |
| #include <string.h> |
| #include <stdlib.h> |
| } |
| |
| /** |
| * @file |
| */ |
| |
| namespace apache { |
| namespace geode { |
| namespace client { |
| |
| /** |
| * C style memory allocation that throws OutOfMemoryException |
| * if it fails |
| */ |
| #define GF_ALLOC(v, t, s) \ |
| { \ |
| v = (t*)malloc((s) * sizeof(t)); \ |
| if ((v) == NULL) { \ |
| throw OutOfMemoryException( \ |
| "Out of Memory while allocating buffer for " #t " of size " #s); \ |
| } \ |
| } |
| |
| /** |
| * C style memory re-allocation that throws OutOfMemoryException |
| * if it fails |
| */ |
| #define GF_RESIZE(v, t, s) \ |
| { \ |
| v = (t*)realloc(v, (s) * sizeof(t)); \ |
| if ((v) == NULL) { \ |
| throw OutOfMemoryException( \ |
| "Out of Memory while resizing buffer for " #t); \ |
| } \ |
| } |
| |
| #define GF_FREE(v) free(v) |
| |
| /** |
| * Provide operations for writing primitive data values, byte arrays, |
| * strings, <code>Serializable</code> objects to a byte stream. |
| * This class is intentionally not thread safe. |
| */ |
| class CPPCACHE_EXPORT DataOutput { |
| public: |
| /** |
| * Construct a new DataOutput. |
| */ |
| DataOutput(); |
| |
| /** |
| * Write an unsigned byte to the <code>DataOutput</code>. |
| * |
| * @param value the unsigned byte to be written |
| */ |
| inline void write(uint8_t value) { |
| ensureCapacity(1); |
| writeNoCheck(value); |
| } |
| |
| /** |
| * Write a signed byte to the <code>DataOutput</code>. |
| * |
| * @param value the signed byte to be written |
| */ |
| inline void write(int8_t value) { write(static_cast<uint8_t>(value)); } |
| |
| /** |
| * Write a boolean value to the <code>DataOutput</code>. |
| * |
| * @param value the boolean value to be written |
| */ |
| inline void writeBoolean(bool value) { write(static_cast<uint8_t>(value)); } |
| |
| /** |
| * Write an array of unsigned bytes to the <code>DataOutput</code>. |
| * |
| * @param value the array of unsigned bytes to be written |
| * @param len the number of bytes from the start of array to be written |
| */ |
| inline void writeBytes(const uint8_t* bytes, int32_t len) { |
| if (len >= 0) { |
| ensureCapacity(len + 5); |
| writeArrayLen(bytes == NULL ? 0 : len); // length of bytes... |
| if (len > 0 && bytes != NULL) { |
| memcpy(m_buf, bytes, len); |
| m_buf += len; |
| } |
| } else { |
| write(static_cast<int8_t>(-1)); |
| } |
| } |
| |
| /** |
| * Write an array of signed bytes to the <code>DataOutput</code>. |
| * |
| * @param value the array of signed bytes to be written |
| * @param len the number of bytes from the start of array to be written |
| */ |
| inline void writeBytes(const int8_t* bytes, int32_t len) { |
| writeBytes(reinterpret_cast<const uint8_t*>(bytes), len); |
| } |
| |
| /** |
| * Write an array of unsigned bytes without its length to the |
| * <code>DataOutput</code>. |
| * @remarks The difference between this and <code>writeBytes</code> is that |
| * this does write the length of bytes so the corresponding |
| * <code>DataInput::readBytesOnly</code> (unlike |
| * <code>DataInput::readBytes</code>) needs the length argument explicitly. |
| * |
| * @param value the array of unsigned bytes to be written |
| * @param len the number of bytes from the start of array to be written |
| */ |
| inline void writeBytesOnly(const uint8_t* bytes, uint32_t len) { |
| ensureCapacity(len); |
| memcpy(m_buf, bytes, len); |
| m_buf += len; |
| } |
| |
| /** |
| * Write an array of signed bytes without its length to the |
| * <code>DataOutput</code>. |
| * @remarks The difference between this and <code>writeBytes</code> is that |
| * this does write the length of bytes so the corresponding |
| * <code>DataInput::readBytesOnly</code> (unlike |
| * <code>DataInput::readBytes</code>) needs the length argument explicitly. |
| * |
| * @param value the array of signed bytes to be written |
| * @param len the number of bytes from the start of array to be written |
| */ |
| inline void writeBytesOnly(const int8_t* bytes, uint32_t len) { |
| writeBytesOnly(reinterpret_cast<const uint8_t*>(bytes), len); |
| } |
| |
| /** |
| * Write a 16-bit unsigned integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 16-bit unsigned integer value to be written |
| */ |
| inline void writeInt(uint16_t value) { |
| ensureCapacity(2); |
| *(m_buf++) = static_cast<uint8_t>(value >> 8); |
| *(m_buf++) = static_cast<uint8_t>(value); |
| } |
| |
| /** |
| * Write a 16-bit Char (wchar_t) value to the <code>DataOutput</code>. |
| * |
| * @param value the 16-bit wchar_t value to be written |
| */ |
| inline void writeChar(uint16_t value) { |
| ensureCapacity(2); |
| *(m_buf++) = static_cast<uint8_t>(value >> 8); |
| *(m_buf++) = static_cast<uint8_t>(value); |
| } |
| |
| /** |
| * Write a 32-bit unsigned integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 32-bit unsigned integer value to be written |
| */ |
| inline void writeInt(uint32_t value) { |
| ensureCapacity(4); |
| *(m_buf++) = static_cast<uint8_t>(value >> 24); |
| *(m_buf++) = static_cast<uint8_t>(value >> 16); |
| *(m_buf++) = static_cast<uint8_t>(value >> 8); |
| *(m_buf++) = static_cast<uint8_t>(value); |
| } |
| |
| /** |
| * Write a 64-bit unsigned integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 64-bit unsigned integer value to be written |
| */ |
| inline void writeInt(uint64_t value) { |
| ensureCapacity(8); |
| // the defines are not reliable and can be changed by compiler options. |
| // Hence using sizeof() test instead. |
| //#if defined(_LP64) || ( defined(__WORDSIZE) && __WORDSIZE == 64 ) || |
| //( defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 ) |
| if (sizeof(long) == 8) { |
| *(m_buf++) = static_cast<uint8_t>(value >> 56); |
| *(m_buf++) = static_cast<uint8_t>(value >> 48); |
| *(m_buf++) = static_cast<uint8_t>(value >> 40); |
| *(m_buf++) = static_cast<uint8_t>(value >> 32); |
| *(m_buf++) = static_cast<uint8_t>(value >> 24); |
| *(m_buf++) = static_cast<uint8_t>(value >> 16); |
| *(m_buf++) = static_cast<uint8_t>(value >> 8); |
| *(m_buf++) = static_cast<uint8_t>(value); |
| } else { |
| uint32_t hword = static_cast<uint32_t>(value >> 32); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 24); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 16); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 8); |
| *(m_buf++) = static_cast<uint8_t>(hword); |
| |
| hword = static_cast<uint32_t>(value); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 24); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 16); |
| *(m_buf++) = static_cast<uint8_t>(hword >> 8); |
| *(m_buf++) = static_cast<uint8_t>(hword); |
| } |
| } |
| |
| /** |
| * Write a 16-bit signed integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 16-bit signed integer value to be written |
| */ |
| inline void writeInt(int16_t value) { |
| writeInt(static_cast<uint16_t>(value)); |
| } |
| |
| /** |
| * Write a 32-bit signed integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 32-bit signed integer value to be written |
| */ |
| inline void writeInt(int32_t value) { |
| writeInt(static_cast<uint32_t>(value)); |
| } |
| |
| /** |
| * Write a 64-bit signed integer value to the <code>DataOutput</code>. |
| * |
| * @param value the 64-bit signed integer value to be written |
| */ |
| inline void writeInt(int64_t value) { |
| writeInt(static_cast<uint64_t>(value)); |
| } |
| |
| /** |
| * Write a 32-bit signed integer array length value to the |
| * <code>DataOutput</code> in a manner compatible with java server's |
| * <code>DataSerializer.writeArrayLength</code>. |
| * |
| * @param value the 32-bit signed integer array length to be written |
| */ |
| inline void writeArrayLen(int32_t len) { |
| if (len == -1) { |
| write(static_cast<int8_t>(-1)); |
| } else if (len <= 252) { // 252 is java's ((byte)-4 && 0xFF) |
| write(static_cast<uint8_t>(len)); |
| } else if (len <= 0xFFFF) { |
| write(static_cast<int8_t>(-2)); |
| writeInt(static_cast<uint16_t>(len)); |
| } else { |
| write(static_cast<int8_t>(-3)); |
| writeInt(len); |
| } |
| } |
| |
| /** |
| * Write a float value to the <code>DataOutput</code>. |
| * |
| * @param value the float value to be written |
| */ |
| inline void writeFloat(float value) { |
| union float_uint32_t { |
| float f; |
| uint32_t u; |
| } v; |
| v.f = value; |
| writeInt(v.u); |
| } |
| |
| /** |
| * Write a double precision real number to the <code>DataOutput</code>. |
| * |
| * @param value the double precision real number to be written |
| */ |
| inline void writeDouble(double value) { |
| union double_uint64_t { |
| double d; |
| uint64_t ll; |
| } v; |
| v.d = value; |
| writeInt(v.ll); |
| } |
| |
| /** |
| * Writes the given ASCII string supporting maximum length of 64K |
| * (i.e. unsigned 16-bit integer). |
| * @remarks The string will be truncated if greater than the maximum |
| * permissible length of 64K. Use <code>writeBytes</code> or |
| * <code>writeASCIIHuge</code> to write ASCII strings of length larger |
| * than this. |
| * |
| * @param value the C string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| */ |
| inline void writeASCII(const char* value, uint32_t length = 0) { |
| if (value != NULL) { |
| if (length == 0) { |
| length = static_cast<uint32_t>(strlen(value)); |
| } |
| uint16_t len = static_cast<uint16_t>(length > 0xFFFF ? 0xFFFF : length); |
| writeInt(len); |
| writeBytesOnly((int8_t*)value, len); // K64 |
| } else { |
| writeInt(static_cast<uint16_t>(0)); |
| } |
| } |
| |
| inline void writeNativeString(const char* value) { |
| // create cacheable string |
| // write typeid id. |
| // call todata |
| CacheableStringPtr csPtr = CacheableString::create(value); |
| write(csPtr->typeId()); |
| csPtr->toData(*this); |
| } |
| |
| /** |
| * Writes the given ASCII string supporting upto maximum 32-bit |
| * integer value. |
| * @remarks Use this to write large ASCII strings. The other |
| * <code>writeASCII</code> method will truncate strings greater than |
| * 64K in size. |
| * |
| * @param value the wide-character string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| */ |
| inline void writeASCIIHuge(const char* value, uint32_t length = 0) { |
| if (value != NULL) { |
| if (length == 0) { |
| length = static_cast<uint32_t>(strlen(value)); |
| } |
| writeInt(length); |
| writeBytesOnly((int8_t*)value, length); |
| } else { |
| writeInt(static_cast<uint32_t>(0)); |
| } |
| } |
| |
| /** |
| * Writes the given given string using java modified UTF-8 encoding |
| * supporting maximum encoded length of 64K (i.e. unsigned 16-bit integer). |
| * @remarks The string will be truncated if greater than the maximum |
| * permissible length of 64K. Use <code>writeUTFHuge</code> to write |
| * strings of length larger than this. |
| * |
| * @param value the C string to be written |
| * |
| */ |
| inline void writeFullUTF(const char* value, uint32_t length = 0) { |
| if (value != NULL) { |
| int32_t len = getEncodedLength(value, length); |
| uint16_t encodedLen = static_cast<uint16_t>(len > 0xFFFF ? 0xFFFF : len); |
| writeInt(static_cast<int32_t>(encodedLen)); |
| ensureCapacity(encodedLen); |
| write(static_cast<int8_t>(0)); // isObject = 0 BYTE_CODE |
| uint8_t* end = m_buf + encodedLen; |
| while (m_buf < end) { |
| encodeChar(*value++); |
| } |
| if (m_buf > end) m_buf = end; |
| } else { |
| writeInt(static_cast<uint16_t>(0)); |
| } |
| } |
| |
| /** |
| * Writes the given given string using java modified UTF-8 encoding |
| * supporting maximum encoded length of 64K (i.e. unsigned 16-bit integer). |
| * @remarks The string will be truncated if greater than the maximum |
| * permissible length of 64K. Use <code>writeUTFHuge</code> to write |
| * strings of length larger than this. |
| * |
| * @param value the C string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| */ |
| inline void writeUTF(const char* value, uint32_t length = 0) { |
| if (value != NULL) { |
| int32_t len = getEncodedLength(value, length); |
| uint16_t encodedLen = static_cast<uint16_t>(len > 0xFFFF ? 0xFFFF : len); |
| writeInt(encodedLen); |
| ensureCapacity(encodedLen); |
| uint8_t* end = m_buf + encodedLen; |
| while (m_buf < end) { |
| encodeChar(*value++); |
| } |
| if (m_buf > end) m_buf = end; |
| } else { |
| writeInt(static_cast<uint16_t>(0)); |
| } |
| } |
| |
| /** |
| * Writes the given string using java modified UTF-8 encoding. |
| * @remarks Use this to write large strings. The other |
| * <code>writeUTF</code> method will truncate strings greater than |
| * 64K in size. |
| * |
| * @param value the C string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| * assuming a null terminated string; do not use this unless sure |
| * that the UTF string does not contain any null characters |
| */ |
| inline void writeUTFHuge(const char* value, uint32_t length = 0) { |
| if (value != NULL) { |
| if (length == 0) { |
| length = static_cast<uint32_t>(strlen(value)); |
| } |
| writeInt(length); |
| ensureCapacity(length * 2); |
| for (uint32_t pos = 0; pos < length; pos++) { |
| writeNoCheck(static_cast<int8_t>(0)); |
| writeNoCheck(static_cast<int8_t>(value[pos])); |
| } |
| } else { |
| writeInt(static_cast<uint32_t>(0)); |
| } |
| } |
| |
| /** |
| * Writes the given given string using java modified UTF-8 encoding |
| * supporting maximum encoded length of 64K (i.e. unsigned 16-bit integer). |
| * @remarks The string will be truncated if greater than the maximum |
| * permissible length of 64K. Use <code>writeUTFHuge</code> to write |
| * strings of length larger than this. |
| * |
| * @param value the wide-character string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| */ |
| inline void writeUTF(const wchar_t* value, uint32_t length = 0) { |
| if (value != NULL) { |
| int32_t len = getEncodedLength(value, length); |
| uint16_t encodedLen = static_cast<uint16_t>(len > 0xFFFF ? 0xFFFF : len); |
| writeInt(encodedLen); |
| ensureCapacity(encodedLen); |
| uint8_t* end = m_buf + encodedLen; |
| while (m_buf < end) { |
| encodeChar(*value++); |
| } |
| if (m_buf > end) m_buf = end; |
| } else { |
| writeInt(static_cast<uint16_t>(0)); |
| } |
| } |
| |
| /** |
| * Writes the given string using java modified UTF-8 encoding. |
| * @remarks Use this to write large strings. The other |
| * <code>writeUTF</code> method will truncate strings greater than |
| * 64K in size. |
| * |
| * @param value the wide-character string to be written |
| * @param length the number of characters from start of string to be |
| * written; the default value of 0 implies the complete string |
| */ |
| inline void writeUTFHuge(const wchar_t* value, uint32_t length = 0) { |
| if (value != NULL) { |
| if (length == 0) { |
| length = static_cast<uint32_t>(wcslen(value)); |
| } |
| writeInt(length); |
| ensureCapacity(length * 2); |
| for (uint32_t pos = 0; pos < length; pos++) { |
| uint16_t item = static_cast<uint16_t>(value[pos]); |
| writeNoCheck(static_cast<uint8_t>((item & 0xFF00) >> 8)); |
| writeNoCheck(static_cast<uint8_t>(item & 0xFF)); |
| } |
| } else { |
| writeInt(static_cast<uint32_t>(0)); |
| } |
| } |
| |
| /** |
| * Get the length required to represent a given wide-character string in |
| * java modified UTF-8 format. |
| * |
| * @param value The C string. |
| * @param length The length of the string; or zero to use the full string. |
| * @return The length required for representation in java modified |
| * UTF-8 format. |
| * @see DataInput::getDecodedLength |
| */ |
| inline static int32_t getEncodedLength(const char* value, int32_t length = 0, |
| uint32_t* valLength = NULL) { |
| if (value == NULL) return 0; |
| char currentChar; |
| int32_t encodedLen = 0; |
| const char* start = value; |
| if (length == 0) { |
| while ((currentChar = *value) != '\0') { |
| getEncodedLength(currentChar, encodedLen); |
| value++; |
| } |
| } else { |
| const char* end = value + length; |
| while (value < end) { |
| currentChar = *value; |
| getEncodedLength(currentChar, encodedLen); |
| value++; |
| } |
| } |
| if (valLength != NULL) { |
| *valLength = static_cast<uint32_t>(value - start); |
| } |
| return encodedLen; |
| } |
| |
| /** |
| * Get the length required to represent a given wide-character string in |
| * java modified UTF-8 format. |
| * |
| * @param value The wide-character string. |
| * @param length The length of the string. |
| * @return The length required for representation in java modified |
| * UTF-8 format. |
| * @see DataInput::getDecodedLength |
| */ |
| inline static int32_t getEncodedLength(const wchar_t* value, |
| int32_t length = 0, |
| uint32_t* valLength = NULL) { |
| if (value == NULL) return 0; |
| wchar_t currentChar; |
| int32_t encodedLen = 0; |
| const wchar_t* start = value; |
| if (length == 0) { |
| while ((currentChar = *value) != 0) { |
| getEncodedLength(currentChar, encodedLen); |
| value++; |
| } |
| } else { |
| const wchar_t* end = value + length; |
| while (value < end) { |
| currentChar = *value; |
| getEncodedLength(currentChar, encodedLen); |
| value++; |
| } |
| } |
| if (valLength != NULL) { |
| *valLength = static_cast<uint32_t>(value - start); |
| } |
| return encodedLen; |
| } |
| |
| /** |
| * Write a <code>Serializable</code> object to the <code>DataOutput</code>. |
| * |
| * @param objptr smart pointer to the <code>Serializable</code> object |
| * to be written |
| */ |
| template <class PTR> |
| void writeObject(const SharedPtr<PTR>& objptr, bool isDelta = false) { |
| writeObjectInternal(objptr.ptr(), isDelta); |
| } |
| |
| /** |
| * Write a <code>Serializable</code> object to the <code>DataOutput</code>. |
| * |
| * @param objptr pointer to the <code>Serializable</code> object |
| * to be written |
| */ |
| void writeObject(const Serializable* objptr) { writeObjectInternal(objptr); } |
| |
| /** |
| * Get an internal pointer to the current location in the |
| * <code>DataOutput</code> byte array. |
| */ |
| const uint8_t* getCursor() { return m_buf; } |
| |
| /** |
| * Advance the buffer cursor by the given offset. |
| * |
| * @param offset the offset by which to advance the cursor |
| */ |
| void advanceCursor(uint32_t offset) { |
| ensureCapacity(offset); |
| m_buf += offset; |
| } |
| |
| /** |
| * Rewind the buffer cursor by the given offset. |
| * |
| * @param offset the offset by which to rewind the cursor |
| */ |
| void rewindCursor(uint32_t offset) { m_buf -= offset; } |
| |
| void updateValueAtPos(uint32_t offset, uint8_t value) { |
| m_bytes[offset] = value; |
| } |
| |
| uint8_t getValueAtPos(uint32_t offset) { return m_bytes[offset]; } |
| /** Destruct a DataOutput, including releasing the created buffer. */ |
| ~DataOutput() { |
| reset(); |
| DataOutput::checkinBuffer(m_bytes, m_size); |
| } |
| |
| /** |
| * Get a pointer to the internal buffer of <code>DataOutput</code>. |
| */ |
| inline const uint8_t* getBuffer() const { |
| // GF_R_ASSERT(!((uint32_t)(m_bytes) % 4)); |
| return m_bytes; |
| } |
| |
| /** |
| * Get a pointer to the internal buffer of <code>DataOutput</code>. |
| */ |
| inline uint32_t getRemainingBufferLength() const { |
| // GF_R_ASSERT(!((uint32_t)(m_bytes) % 4)); |
| return m_size - getBufferLength(); |
| } |
| |
| /** |
| * Get a pointer to the internal buffer of <code>DataOutput</code>. |
| * |
| * @param rsize the size of buffer is filled in this output parameter; |
| * should not be NULL |
| */ |
| inline const uint8_t* getBuffer(uint32_t* rsize) const { |
| *rsize = static_cast<uint32_t>(m_buf - m_bytes); |
| // GF_R_ASSERT(!((uint32_t)(m_bytes) % 4)); |
| return m_bytes; |
| } |
| |
| inline uint8_t* getBufferCopy() { |
| uint32_t size = static_cast<uint32_t>(m_buf - m_bytes); |
| uint8_t* result; |
| GF_ALLOC(result, uint8_t, size); |
| memcpy(result, m_bytes, size); |
| return result; |
| } |
| |
| /** |
| * Get the length of current data in the internal buffer of |
| * <code>DataOutput</code>. |
| */ |
| inline uint32_t getBufferLength() const { |
| return static_cast<uint32_t>(m_buf - m_bytes); |
| } |
| |
| /** |
| * Reset the internal cursor to the start of the buffer. |
| */ |
| inline void reset() { |
| if (m_haveBigBuffer) { |
| // free existing buffer |
| GF_FREE(m_bytes); |
| // create smaller buffer |
| GF_ALLOC(m_bytes, uint8_t, m_lowWaterMark); |
| m_size = m_lowWaterMark; |
| // reset the flag |
| m_haveBigBuffer = false; |
| // release the lock |
| releaseLock(); |
| } |
| m_buf = m_bytes; |
| } |
| |
| // make sure there is room left for the requested size item. |
| inline void ensureCapacity(uint32_t size) { |
| uint32_t offset = static_cast<uint32_t>(m_buf - m_bytes); |
| if ((m_size - offset) < size) { |
| uint32_t newSize = m_size * 2 + (8192 * (size / 8192)); |
| if (newSize >= m_highWaterMark && !m_haveBigBuffer) { |
| // acquire the lock |
| acquireLock(); |
| // set flag |
| m_haveBigBuffer = true; |
| } |
| m_size = newSize; |
| GF_RESIZE(m_bytes, uint8_t, m_size); |
| m_buf = m_bytes + offset; |
| } |
| } |
| |
| /* |
| * This is for internal use |
| */ |
| const char* getPoolName() { return m_poolName; } |
| |
| /* |
| * This is for internal use |
| */ |
| void setPoolName(const char* poolName) { m_poolName = poolName; } |
| |
| uint8_t* getBufferCopyFrom(const uint8_t* from, uint32_t length) { |
| uint8_t* result; |
| GF_NEW(result, uint8_t[length]); |
| memcpy(result, from, length); |
| |
| return result; |
| } |
| |
| static void safeDelete(uint8_t* src) { GF_SAFE_DELETE(src); } |
| |
| static DataOutput* getDataOutput() { return new DataOutput(); } |
| static void releaseDataOutput(DataOutput* dataOutput) { |
| GF_SAFE_DELETE(dataOutput); |
| } |
| |
| private: |
| void writeObjectInternal(const Serializable* ptr, bool isDelta = false); |
| |
| static void acquireLock(); |
| static void releaseLock(); |
| |
| const char* m_poolName; |
| // memory m_buffer to encode to. |
| uint8_t* m_bytes; |
| // cursor. |
| uint8_t* m_buf; |
| // size of m_bytes. |
| uint32_t m_size; |
| // high and low water marks for buffer size |
| static uint32_t m_lowWaterMark; |
| static uint32_t m_highWaterMark; |
| // flag to indicate we have a big buffer |
| volatile bool m_haveBigBuffer; |
| |
| inline static void getEncodedLength(const char val, int32_t& encodedLen) { |
| if ((val == 0) || (val & 0x80)) { |
| // two byte. |
| encodedLen += 2; |
| } else { |
| // one byte. |
| encodedLen++; |
| } |
| } |
| |
| inline static void getEncodedLength(const wchar_t val, int32_t& encodedLen) { |
| if (val == 0) { |
| encodedLen += 2; |
| } else if (val < 0x80) // ASCII character |
| { |
| encodedLen++; |
| } else if (val < 0x800) { |
| encodedLen += 2; |
| } else { |
| encodedLen += 3; |
| } |
| } |
| |
| inline void encodeChar(const char value) { |
| uint8_t tmp = static_cast<uint8_t>(value); |
| if ((tmp == 0) || (tmp & 0x80)) { |
| // two byte. |
| *(m_buf++) = static_cast<uint8_t>(0xc0 | ((tmp & 0xc0) >> 6)); |
| *(m_buf++) = static_cast<uint8_t>(0x80 | (tmp & 0x3f)); |
| } else { |
| // one byte. |
| *(m_buf++) = tmp; |
| } |
| } |
| |
| // this will lose the character set encoding. |
| inline void encodeChar(const wchar_t value) { |
| uint16_t c = static_cast<uint16_t>(value); |
| if (c == 0) { |
| *(m_buf++) = 0xc0; |
| *(m_buf++) = 0x80; |
| } else if (c < 0x80) { // ASCII character |
| *(m_buf++) = static_cast<uint8_t>(c); |
| } else if (c < 0x800) { |
| *(m_buf++) = static_cast<uint8_t>(0xC0 | c >> 6); |
| *(m_buf++) = static_cast<uint8_t>(0x80 | (c & 0x3F)); |
| } else { |
| *(m_buf++) = static_cast<uint8_t>(0xE0 | c >> 12); |
| *(m_buf++) = static_cast<uint8_t>(0x80 | ((c >> 6) & 0x3F)); |
| *(m_buf++) = static_cast<uint8_t>(0x80 | (c & 0x3F)); |
| } |
| } |
| |
| inline void writeNoCheck(uint8_t value) { *(m_buf++) = value; } |
| |
| inline void writeNoCheck(int8_t value) { |
| writeNoCheck(static_cast<uint8_t>(value)); |
| } |
| |
| static uint8_t* checkoutBuffer(uint32_t* size); |
| static void checkinBuffer(uint8_t* buffer, uint32_t size); |
| |
| // disable copy constructor and assignment |
| DataOutput(const DataOutput&); |
| DataOutput& operator=(const DataOutput&); |
| }; |
| } // namespace client |
| } // namespace geode |
| } // namespace apache |
| |
| #endif // GEODE_GFCPP_DATAOUTPUT_H_ |