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) {
275 auto len = value.length();
277 for (
unsigned int i = 0; i < len; i++) {
278 auto c = value.at(i);
279 if ((c <= 0x007F) && (c >= 0x0001)) {
281 }
else if (c > 0x07FF) {
287 auto writeUTF = utfLen > len;
289 if (utfLen > 0xFFFF) {
290 write(
static_cast<uint8_t
>(DSCode::CacheableStringHuge));
291 writeUtf16Huge(value);
293 write(
static_cast<uint8_t
>(DSCode::CacheableString));
294 writeJavaModifiedUtf8(value);
298 write(
static_cast<uint8_t
>(DSCode::CacheableASCIIStringHuge));
299 writeAsciiHuge(value);
301 write(
static_cast<uint8_t
>(DSCode::CacheableASCIIString));
307 template <
class _CharT>
308 inline void writeUTF(
const _CharT* value) {
309 if (
nullptr == value) {
310 throw NullPointerException(
"Parameter value must not be null.");
312 writeUTF(std::basic_string<_CharT>(value));
315 template <
class _CharT,
class... Tail>
316 inline void writeUTF(
const std::basic_string<_CharT, Tail...>& value) {
317 writeJavaModifiedUtf8(value);
329 template <
class _CharT,
class... _Tail>
330 inline void writeChars(
const std::basic_string<_CharT, _Tail...>& value) {
346 template <
class _CharT>
348 writeChars(std::basic_string<_CharT>(value));
358 void writeObject(
const std::shared_ptr<PTR>& objptr,
bool isDelta =
false) {
359 writeObjectInternal(objptr, isDelta);
374 ensureCapacity(offset);
385 void updateValueAtPos(
size_t offset, uint8_t value) {
386 m_bytes.get()[offset] = value;
389 uint8_t getValueAtPos(
size_t offset) {
return m_bytes.get()[offset]; }
396 return m_bytes.get();
404 return m_size - getBufferLength();
414 *rsize = m_buf - m_bytes.get();
416 return m_bytes.get();
419 inline uint8_t* getBufferCopy() {
420 size_t size = m_buf - m_bytes.get();
421 auto result =
static_cast<uint8_t*
>(std::malloc(size *
sizeof(uint8_t)));
422 if (result ==
nullptr) {
425 std::memcpy(result, m_bytes.get(), size);
439 if (m_haveBigBuffer) {
442 static_cast<uint8_t*
>(std::malloc(m_lowWaterMark *
sizeof(uint8_t))));
443 if (m_bytes ==
nullptr) {
446 m_size = m_lowWaterMark;
448 m_haveBigBuffer =
false;
452 m_buf = m_bytes.get();
456 inline void ensureCapacity(
size_t size) {
457 size_t offset = m_buf - m_bytes.get();
458 if ((m_size - offset) < size) {
459 size_t newSize = m_size * 2 + (8192 * (size / 8192));
460 if (newSize >= m_highWaterMark && !m_haveBigBuffer) {
464 m_haveBigBuffer =
true;
468 auto bytes = m_bytes.release();
470 static_cast<uint8_t*
>(std::realloc(bytes, m_size *
sizeof(uint8_t)));
471 if (tmp ==
nullptr) {
472 throw OutOfMemoryException(
"Out of Memory while resizing buffer");
475 m_buf = m_bytes.get() + offset;
479 uint8_t* getBufferCopyFrom(
const uint8_t* from,
size_t length) {
481 _GEODE_NEW(result, uint8_t[length]);
482 std::memcpy(result, from, length);
487 static void safeDelete(uint8_t* src) { _GEODE_SAFE_DELETE(src); }
489 virtual Cache* getCache()
const;
491 DataOutput() =
delete;
497 DataOutput::checkinBuffer(m_bytes.release(), m_size);
512 virtual const SerializationRegistry& getSerializationRegistry()
const;
515 void writeObjectInternal(
const std::shared_ptr<Serializable>& ptr,
516 bool isDelta =
false);
518 static void acquireLock();
519 static void releaseLock();
522 void operator()(uint8_t* p) { free(p); }
526 std::unique_ptr<uint8_t, FreeDeleter> m_bytes;
532 static size_t m_lowWaterMark;
533 static size_t m_highWaterMark;
535 volatile bool m_haveBigBuffer;
536 const CacheImpl* m_cache;
539 template <
class _CharT,
class... _Tail>
540 inline void writeAscii(
const std::basic_string<_CharT, _Tail...>& value) {
541 uint16_t len =
static_cast<uint16_t
>(std::min<size_t>(
542 value.length(), (std::numeric_limits<uint16_t>::max)()));
544 for (
size_t i = 0; i < len; i++) {
546 write(
static_cast<int8_t
>(value.data()[i] & 0x7F));
550 template <
class _CharT,
class... _Tail>
551 inline void writeAsciiHuge(
const std::basic_string<_CharT, _Tail...>& value) {
552 uint32_t len =
static_cast<uint32_t
>(std::min<size_t>(
553 value.length(), (std::numeric_limits<uint32_t>::max)()));
554 writeInt(
static_cast<uint32_t
>(len));
555 for (
size_t i = 0; i < len; i++) {
557 write(
static_cast<int8_t
>(value.data()[i] & 0x7F));
561 template <
class _CharT,
class _Traits,
class _Allocator>
562 void writeJavaModifiedUtf8(
563 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
564 writeJavaModifiedUtf8(value.data(), value.length());
567 template <
class _Traits,
class _Allocator>
568 void writeJavaModifiedUtf8(
569 const std::basic_string<char, _Traits, _Allocator>& value);
571 template <
class _Traits,
class _Allocator>
572 void writeJavaModifiedUtf8(
573 const std::basic_string<char32_t, _Traits, _Allocator>& value);
575 template <
class _Traits,
class _Allocator>
576 inline void writeJavaModifiedUtf8(
577 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
578 typedef std::conditional<
579 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
580 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
581 char>::type>::type _Convert;
582 writeJavaModifiedUtf8(
reinterpret_cast<const _Convert*
>(value.data()),
586 inline void writeJavaModifiedUtf8(
const char16_t* data,
size_t len) {
588 writeInt(
static_cast<uint16_t
>(0));
590 auto encodedLen =
static_cast<uint16_t
>(
591 std::min<size_t>(getJavaModifiedUtf8EncodedLength(data, len),
592 (std::numeric_limits<uint16_t>::max)()));
593 writeInt(encodedLen);
594 ensureCapacity(encodedLen);
595 const auto end = m_buf + encodedLen;
596 while (m_buf < end) {
597 encodeJavaModifiedUtf8(*data++);
599 if (m_buf > end) m_buf = end;
603 void writeJavaModifiedUtf8(
const char32_t* data,
size_t len);
605 template <
class _CharT,
class _Traits,
class _Allocator>
606 inline void writeUtf16Huge(
607 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
608 writeUtf16Huge(value.data(), value.length());
611 template <
class _Traits,
class _Allocator>
613 const std::basic_string<char, _Traits, _Allocator>& value);
615 template <
class _Traits,
class _Allocator>
617 const std::basic_string<char32_t, _Traits, _Allocator>& value);
619 template <
class _Traits,
class _Allocator>
620 inline void writeUtf16Huge(
621 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
622 typedef std::conditional<
623 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
624 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
625 char>::type>::type _Convert;
626 writeUtf16Huge(
reinterpret_cast<const _Convert*
>(value.data()),
630 inline void writeUtf16Huge(
const char16_t* data,
size_t length) {
631 uint32_t len =
static_cast<uint32_t
>(
632 std::min<size_t>(length, (std::numeric_limits<uint32_t>::max)()));
634 writeUtf16(data, length);
637 void writeUtf16Huge(
const char32_t* data,
size_t len);
639 template <
class _CharT,
class _Traits,
class _Allocator>
640 inline void writeUtf16(
641 const std::basic_string<_CharT, _Traits, _Allocator>& value) {
642 writeUtf16(value.data(), value.length());
645 template <
class _Traits,
class _Allocator>
646 void writeUtf16(
const std::basic_string<char, _Traits, _Allocator>& value);
648 template <
class _Traits,
class _Allocator>
650 const std::basic_string<char32_t, _Traits, _Allocator>& value);
652 template <
class _Traits,
class _Allocator>
653 inline void writeUtf16(
654 const std::basic_string<wchar_t, _Traits, _Allocator>& value) {
655 typedef std::conditional<
656 sizeof(wchar_t) ==
sizeof(
char16_t), char16_t,
657 std::conditional<
sizeof(wchar_t) ==
sizeof(
char32_t), char32_t,
658 char>::type>::type _Convert;
659 writeUtf16(
reinterpret_cast<const _Convert*
>(value.data()), value.length());
662 inline void writeUtf16(
const char16_t* data,
size_t length) {
663 ensureCapacity(length * 2);
664 for (; length > 0; length--, data++) {
665 writeNoCheck(
static_cast<uint8_t
>(*data >> 8));
666 writeNoCheck(
static_cast<uint8_t
>(*data));
670 void writeUtf16(
const char32_t* data,
size_t len);
672 static size_t getJavaModifiedUtf8EncodedLength(
const char16_t* data,
675 inline static void getEncodedLength(
const char val, int32_t& encodedLen) {
676 if ((val == 0) || (val & 0x80)) {
685 inline static void getEncodedLength(
const wchar_t val, int32_t& encodedLen) {
688 }
else if (val < 0x80)
691 }
else if (val < 0x800) {
698 inline void encodeChar(
const char value) {
699 uint8_t tmp =
static_cast<uint8_t
>(value);
700 if ((tmp == 0) || (tmp & 0x80)) {
702 *(m_buf++) =
static_cast<uint8_t
>(0xc0 | ((tmp & 0xc0) >> 6));
703 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (tmp & 0x3f));
711 inline void encodeChar(
const wchar_t value) {
712 uint16_t c =
static_cast<uint16_t
>(value);
716 }
else if (c < 0x80) {
717 *(m_buf++) =
static_cast<uint8_t
>(c);
718 }
else if (c < 0x800) {
719 *(m_buf++) =
static_cast<uint8_t
>(0xC0 | c >> 6);
720 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
722 *(m_buf++) =
static_cast<uint8_t
>(0xE0 | c >> 12);
723 *(m_buf++) =
static_cast<uint8_t
>(0x80 | ((c >> 6) & 0x3F));
724 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
728 inline void encodeJavaModifiedUtf8(
const char16_t c) {
733 }
else if (c < 0x80) {
735 *(m_buf++) =
static_cast<uint8_t
>(c);
736 }
else if (c < 0x800) {
737 *(m_buf++) =
static_cast<uint8_t
>(0xC0 | c >> 6);
738 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
740 *(m_buf++) =
static_cast<uint8_t
>(0xE0 | c >> 12);
741 *(m_buf++) =
static_cast<uint8_t
>(0x80 | ((c >> 6) & 0x3F));
742 *(m_buf++) =
static_cast<uint8_t
>(0x80 | (c & 0x3F));
746 inline void writeNoCheck(uint8_t value) { *(m_buf++) = value; }
748 inline void writeNoCheck(int8_t value) {
749 writeNoCheck(
static_cast<uint8_t
>(value));
752 Pool* getPool()
const {
return m_pool; }
754 static uint8_t* checkoutBuffer(
size_t* size);
755 static void checkinBuffer(uint8_t* buffer,
size_t size);
759 friend DataOutputInternal;
760 friend CacheableString;
764template void DataOutput::writeJavaModifiedUtf8(
const std::u16string&);
766template 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:383
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:330
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:366
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:394
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:402
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:358
virtual ~DataOutput() noexcept
Destruct a DataOutput, including releasing the created buffer.
Definition DataOutput.hpp:494
void reset()
Reset the internal cursor to the start of the buffer.
Definition DataOutput.hpp:438
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:413
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:433
void writeChars(const _CharT *value)
Writes a sequence of UTF-16 code units representing the given string value.
Definition DataOutput.hpp:347
void advanceCursor(size_t offset)
Advance the buffer cursor by the given offset.
Definition DataOutput.hpp:373
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:59