20#ifndef GEODE_DATAOUTPUT_H_
21#define GEODE_DATAOUTPUT_H_
28#include "CacheableString.hpp"
29#include "ExceptionTypes.hpp"
30#include "Serializable.hpp"
31#include "internal/geode_globals.hpp"
37class SerializationRegistry;
38class DataOutputInternal;
55 inline void write(uint8_t value) {
65 inline void write(int8_t value) {
write(
static_cast<uint8_t
>(value)); }
72 inline void writeBoolean(
bool value) { write(
static_cast<uint8_t
>(value)); }
80 inline void writeBytes(
const uint8_t* bytes, int32_t len) {
82 ensureCapacity(len + 5);
83 writeArrayLen(bytes ==
nullptr ? 0 : len);
84 if (len > 0 && bytes !=
nullptr) {
85 std::memcpy(m_buf, bytes, len);
89 write(
static_cast<int8_t
>(-1));
99 inline void writeBytes(
const int8_t* bytes, int32_t len) {
100 writeBytes(
reinterpret_cast<const uint8_t*
>(bytes), len);
116 std::memcpy(m_buf, bytes, len);
132 writeBytesOnly(
reinterpret_cast<const uint8_t*
>(bytes), len);
142 *(m_buf++) =
static_cast<uint8_t
>(value >> 8);
143 *(m_buf++) =
static_cast<uint8_t
>(value);
153 *(m_buf++) =
static_cast<uint8_t
>(value >> 8);
154 *(m_buf++) =
static_cast<uint8_t
>(value);
164 *(m_buf++) =
static_cast<uint8_t
>(value >> 24);
165 *(m_buf++) =
static_cast<uint8_t
>(value >> 16);
166 *(m_buf++) =
static_cast<uint8_t
>(value >> 8);
167 *(m_buf++) =
static_cast<uint8_t
>(value);
177 *(m_buf++) =
static_cast<uint8_t
>(value >> 56);
178 *(m_buf++) =
static_cast<uint8_t
>(value >> 48);
179 *(m_buf++) =
static_cast<uint8_t
>(value >> 40);
180 *(m_buf++) =
static_cast<uint8_t
>(value >> 32);
181 *(m_buf++) =
static_cast<uint8_t
>(value >> 24);
182 *(m_buf++) =
static_cast<uint8_t
>(value >> 16);
183 *(m_buf++) =
static_cast<uint8_t
>(value >> 8);
184 *(m_buf++) =
static_cast<uint8_t
>(value);
193 writeInt(
static_cast<uint16_t
>(value));
202 writeInt(
static_cast<uint32_t
>(value));
211 writeInt(
static_cast<uint64_t
>(value));
223 write(
static_cast<int8_t
>(-1));
224 }
else if (len <= 252) {
225 write(
static_cast<uint8_t
>(len));
226 }
else if (len <= 0xFFFF) {
227 write(
static_cast<int8_t
>(-2));
228 writeInt(
static_cast<uint16_t
>(len));
230 write(
static_cast<int8_t
>(-3));
241 union float_uint32_t {
255 union double_uint64_t {
263 template <
class _CharT>
264 inline void writeString(
const _CharT* value) {
266 if (
nullptr == value) {
267 write(
static_cast<uint8_t
>(DSCode::CacheableNullString));
269 writeString(std::basic_string<_CharT>(value));
273 template <
class _CharT,
class... _Tail>
274 inline void writeString(
const std::basic_string<_CharT, _Tail...>& value) {
277 if (value.length() * 3 <= std::numeric_limits<uint16_t>::max()) {
278 write(
static_cast<uint8_t
>(DSCode::CacheableString));
279 writeJavaModifiedUtf8(value);
281 write(
static_cast<uint8_t
>(DSCode::CacheableStringHuge));
282 writeUtf16Huge(value);
286 template <
class _CharT>
287 inline void writeUTF(
const _CharT* value) {
288 if (
nullptr == value) {
289 throw NullPointerException(
"Parameter value must not be null.");
291 writeUTF(std::basic_string<_CharT>(value));
294 template <
class _CharT,
class... Tail>
295 inline void writeUTF(
const std::basic_string<_CharT, Tail...>& value) {
296 writeJavaModifiedUtf8(value);
308 template <
class _CharT,
class... _Tail>
309 inline void writeChars(
const std::basic_string<_CharT, _Tail...>& value) {
325 template <
class _CharT>
327 writeChars(std::basic_string<_CharT>(value));
337 void writeObject(
const std::shared_ptr<PTR>& objptr,
bool isDelta =
false) {
338 writeObjectInternal(objptr, isDelta);
353 ensureCapacity(offset);
364 void updateValueAtPos(
size_t offset, uint8_t value) {
365 m_bytes.get()[offset] = value;
368 uint8_t getValueAtPos(
size_t offset) {
return m_bytes.get()[offset]; }
375 return m_bytes.get();
383 return m_size - getBufferLength();
393 *rsize = m_buf - m_bytes.get();
395 return m_bytes.get();
398 inline uint8_t* getBufferCopy() {
399 size_t size = m_buf - m_bytes.get();
400 auto result =
static_cast<uint8_t*
>(std::malloc(size *
sizeof(uint8_t)));
401 if (result ==
nullptr) {
404 std::memcpy(result, m_bytes.get(), size);
418 if (m_haveBigBuffer) {
421 static_cast<uint8_t*
>(std::malloc(m_lowWaterMark *
sizeof(uint8_t))));
422 if (m_bytes ==
nullptr) {
425 m_size = m_lowWaterMark;
427 m_haveBigBuffer =
false;
431 m_buf = m_bytes.get();
435 inline void ensureCapacity(
size_t size) {
436 size_t offset = m_buf - m_bytes.get();
437 if ((m_size - offset) < size) {
438 size_t newSize = m_size * 2 + (8192 * (size / 8192));
439 if (newSize >= m_highWaterMark && !m_haveBigBuffer) {
443 m_haveBigBuffer =
true;
447 auto bytes = m_bytes.release();
449 static_cast<uint8_t*
>(std::realloc(bytes, m_size *
sizeof(uint8_t)));
450 if (tmp ==
nullptr) {
451 throw OutOfMemoryException(
"Out of Memory while resizing buffer");
454 m_buf = m_bytes.get() + offset;
458 uint8_t* getBufferCopyFrom(
const uint8_t* from,
size_t length) {
460 _GEODE_NEW(result, uint8_t[length]);
461 std::memcpy(result, from, length);
466 static void safeDelete(uint8_t* src) { _GEODE_SAFE_DELETE(src); }
468 virtual Cache* getCache()
const;
470 DataOutput() =
delete;
476 DataOutput::checkinBuffer(m_bytes.release(), m_size);
491 virtual const SerializationRegistry& getSerializationRegistry()
const;
494 void writeObjectInternal(
const std::shared_ptr<Serializable>& ptr,
495 bool isDelta =
false);
497 static void acquireLock();
498 static void releaseLock();
501 void operator()(uint8_t* p) { free(p); }
505 std::unique_ptr<uint8_t, FreeDeleter> m_bytes;
511 static size_t m_lowWaterMark;
512 static size_t m_highWaterMark;
514 volatile bool m_haveBigBuffer;
515 const CacheImpl* m_cache;
518 inline void writeAscii(
const std::string& value) {
519 uint16_t len =
static_cast<uint16_t
>(
520 std::min<size_t>(value.length(), std::numeric_limits<uint16_t>::max()));
522 for (
size_t i = 0; i < len; i++) {
524 write(
static_cast<int8_t
>(value.data()[i] & 0x7F));
528 inline void writeAsciiHuge(
const std::string& value) {
529 uint32_t len =
static_cast<uint32_t
>(
530 std::min<size_t>(value.length(), std::numeric_limits<uint32_t>::max()));
531 writeInt(
static_cast<uint32_t
>(len));
532 for (
size_t i = 0; i < len; i++) {
534 write(
static_cast<int8_t
>(value.data()[i] & 0x7F));
538 template <
class _CharT,
class _Traits,
class _Allocator>
539 void writeJavaModifiedUtf8(
540 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
541 writeJavaModifiedUtf8(value.data(), value.length());
544 template <
class _Traits,
class _Allocator>
545 void writeJavaModifiedUtf8(
546 const std::basic_string<char, _Traits, _Allocator>& value);
548 template <
class _Traits,
class _Allocator>
549 void writeJavaModifiedUtf8(
550 const std::basic_string<char32_t, _Traits, _Allocator>& value);
552 template <
class _Traits,
class _Allocator>
553 inline void writeJavaModifiedUtf8(
554 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
555 typedef std::conditional<
556 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
557 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
558 char>::type>::type _Convert;
559 writeJavaModifiedUtf8(
reinterpret_cast<const _Convert*
>(value.data()),
563 inline void writeJavaModifiedUtf8(
const char16_t* data,
size_t len) {
565 writeInt(
static_cast<uint16_t
>(0));
567 auto encodedLen =
static_cast<uint16_t
>(
568 std::min<size_t>(getJavaModifiedUtf8EncodedLength(data, len),
569 std::numeric_limits<uint16_t>::max()));
570 writeInt(encodedLen);
571 ensureCapacity(encodedLen);
572 const auto end = m_buf + encodedLen;
573 while (m_buf < end) {
574 encodeJavaModifiedUtf8(*data++);
576 if (m_buf > end) m_buf = end;
580 void writeJavaModifiedUtf8(
const char32_t* data,
size_t len);
582 template <
class _CharT,
class _Traits,
class _Allocator>
583 inline void writeUtf16Huge(
584 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
585 writeUtf16Huge(value.data(), value.length());
588 template <
class _Traits,
class _Allocator>
590 const std::basic_string<char, _Traits, _Allocator>& value);
592 template <
class _Traits,
class _Allocator>
594 const std::basic_string<char32_t, _Traits, _Allocator>& value);
596 template <
class _Traits,
class _Allocator>
597 inline void writeUtf16Huge(
598 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
599 typedef std::conditional<
600 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
601 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
602 char>::type>::type _Convert;
603 writeUtf16Huge(
reinterpret_cast<const _Convert*
>(value.data()),
607 inline void writeUtf16Huge(
const char16_t* data,
size_t length) {
608 uint32_t len =
static_cast<uint32_t
>(
609 std::min<size_t>(length, std::numeric_limits<uint32_t>::max()));
611 writeUtf16(data, length);
614 void writeUtf16Huge(
const char32_t* data,
size_t len);
616 template <
class _CharT,
class _Traits,
class _Allocator>
617 inline void writeUtf16(
618 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
619 writeUtf16(value.data(), value.length());
622 template <
class _Traits,
class _Allocator>
623 void writeUtf16(
const std::basic_string<char, _Traits, _Allocator>& value);
625 template <
class _Traits,
class _Allocator>
627 const std::basic_string<char32_t, _Traits, _Allocator>& value);
629 template <
class _Traits,
class _Allocator>
630 inline void writeUtf16(
631 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
632 typedef std::conditional<
633 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
634 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
635 char>::type>::type _Convert;
636 writeUtf16(
reinterpret_cast<const _Convert*
>(value.data()), value.length());
639 inline void writeUtf16(
const char16_t* data,
size_t length) {
640 ensureCapacity(length * 2);
641 for (; length > 0; length--, data++) {
642 writeNoCheck(
static_cast<uint8_t
>(*data >> 8));
643 writeNoCheck(
static_cast<uint8_t
>(*data));
647 void writeUtf16(
const char32_t* data,
size_t len);
649 static size_t getJavaModifiedUtf8EncodedLength(
const char16_t* data,
652 inline static void getEncodedLength(
const char val, int32_t& encodedLen) {
653 if ((val == 0) || (val & 0x80)) {
662 inline static void getEncodedLength(
const wchar_t val, int32_t& encodedLen) {
665 }
else if (val < 0x80)
668 }
else if (val < 0x800) {
675 inline void encodeChar(
const char value) {
676 uint8_t tmp =
static_cast<uint8_t
>(value);
677 if ((tmp == 0) || (tmp & 0x80)) {
679 *(m_buf++) =
static_cast<uint8_t
>(0xc0 | ((tmp & 0xc0) >> 6));
680 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (tmp & 0x3f));
688 inline void encodeChar(
const wchar_t value) {
689 uint16_t c =
static_cast<uint16_t
>(value);
693 }
else if (c < 0x80) {
694 *(m_buf++) =
static_cast<uint8_t
>(c);
695 }
else if (c < 0x800) {
696 *(m_buf++) =
static_cast<uint8_t
>(0xC0 | c >> 6);
697 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
699 *(m_buf++) =
static_cast<uint8_t
>(0xE0 | c >> 12);
700 *(m_buf++) =
static_cast<uint8_t
>(0x80 | ((c >> 6) & 0x3F));
701 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
705 inline void encodeJavaModifiedUtf8(
const char16_t c) {
710 }
else if (c < 0x80) {
712 *(m_buf++) =
static_cast<uint8_t
>(c);
713 }
else if (c < 0x800) {
714 *(m_buf++) =
static_cast<uint8_t
>(0xC0 | c >> 6);
715 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
717 *(m_buf++) =
static_cast<uint8_t
>(0xE0 | c >> 12);
718 *(m_buf++) =
static_cast<uint8_t
>(0x80 | ((c >> 6) & 0x3F));
719 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
723 inline void writeNoCheck(uint8_t value) { *(m_buf++) = value; }
725 inline void writeNoCheck(int8_t value) {
726 writeNoCheck(
static_cast<uint8_t
>(value));
729 Pool* getPool()
const {
return m_pool; }
731 static uint8_t* checkoutBuffer(
size_t* size);
732 static void checkinBuffer(uint8_t* buffer,
size_t size);
736 friend DataOutputInternal;
737 friend CacheableString;
741template void DataOutput::writeJavaModifiedUtf8(
const std::u16string&);
743template void DataOutput::writeJavaModifiedUtf8(
const std::wstring&);
Provide operations for writing primitive data values, byte arrays, strings, Serializable objects to a...
Definition: DataOutput.hpp:48
void writeInt(uint64_t value)
Write a 64-bit unsigned integer value to the DataOutput.
Definition: DataOutput.hpp:175
void writeBytesOnly(const int8_t *bytes, size_t len)
Write an array of signed bytes without its length to the DataOutput.
Definition: DataOutput.hpp:131
void rewindCursor(size_t offset)
Rewind the buffer cursor by the given offset.
Definition: DataOutput.hpp:362
void writeChars(const std::basic_string< _CharT, _Tail... > &value)
Writes a sequence of UTF-16 code units representing the given string value.
Definition: DataOutput.hpp:309
void writeInt(int16_t value)
Write a 16-bit signed integer value to the DataOutput.
Definition: DataOutput.hpp:192
void writeChar(uint16_t value)
Write a 16-bit Char (wchar_t) value to the DataOutput.
Definition: DataOutput.hpp:151
void writeDouble(double value)
Write a double precision real number to the DataOutput.
Definition: DataOutput.hpp:254
const uint8_t * getCursor()
Get an internal pointer to the current location in the DataOutput byte array.
Definition: DataOutput.hpp:345
void writeFloat(float value)
Write a float value to the DataOutput.
Definition: DataOutput.hpp:240
const uint8_t * getBuffer() const
Get a pointer to the internal buffer of DataOutput.
Definition: DataOutput.hpp:373
void write(int8_t value)
Write a signed byte to the DataOutput.
Definition: DataOutput.hpp:65
size_t getRemainingBufferLength() const
Get a pointer to the internal buffer of DataOutput.
Definition: DataOutput.hpp:381
void writeBytes(const int8_t *bytes, int32_t len)
Write an array of signed bytes to the DataOutput.
Definition: DataOutput.hpp:99
void writeArrayLen(int32_t len)
Write a 32-bit signed integer array length value to the DataOutput in a manner compatible with java s...
Definition: DataOutput.hpp:221
void writeInt(uint16_t value)
Write a 16-bit unsigned integer value to the DataOutput.
Definition: DataOutput.hpp:140
void writeBytes(const uint8_t *bytes, int32_t len)
Write an array of unsigned bytes to the DataOutput.
Definition: DataOutput.hpp:80
DataOutput(const CacheImpl *cache, Pool *pool)
Construct a new DataOutput.
void writeBytesOnly(const uint8_t *bytes, size_t len)
Write an array of unsigned bytes without its length to the DataOutput.
Definition: DataOutput.hpp:114
void writeInt(uint32_t value)
Write a 32-bit unsigned integer value to the DataOutput.
Definition: DataOutput.hpp:162
void write(uint8_t value)
Write an unsigned byte to the DataOutput.
Definition: DataOutput.hpp:55
void writeObject(const std::shared_ptr< PTR > &objptr, bool isDelta=false)
Write a Serializable object to the DataOutput.
Definition: DataOutput.hpp:337
virtual ~DataOutput() noexcept
Destruct a DataOutput, including releasing the created buffer.
Definition: DataOutput.hpp:473
void reset()
Reset the internal cursor to the start of the buffer.
Definition: DataOutput.hpp:417
void writeInt(int32_t value)
Write a 32-bit signed integer value to the DataOutput.
Definition: DataOutput.hpp:201
const uint8_t * getBuffer(size_t *rsize) const
Get a pointer to the internal buffer of DataOutput.
Definition: DataOutput.hpp:392
void writeBoolean(bool value)
Write a boolean value to the DataOutput.
Definition: DataOutput.hpp:72
void writeInt(int64_t value)
Write a 64-bit signed integer value to the DataOutput.
Definition: DataOutput.hpp:210
size_t getBufferLength() const
Get the length of current data in the internal buffer of DataOutput.
Definition: DataOutput.hpp:412
void writeChars(const _CharT *value)
Writes a sequence of UTF-16 code units representing the given string value.
Definition: DataOutput.hpp:326
void advanceCursor(size_t offset)
Advance the buffer cursor by the given offset.
Definition: DataOutput.hpp:352
Thrown when the system cannot allocate any more memory.
Definition: ExceptionTypes.hpp:392
A pool of connections to connect from a client to a set of Geode Cache Servers.
Definition: Pool.hpp:63