20 #ifndef GEODE_DATAOUTPUT_H_
21 #define GEODE_DATAOUTPUT_H_
29 #include "ExceptionTypes.hpp"
30 #include "Serializable.hpp"
31 #include "internal/geode_globals.hpp"
37 class SerializationRegistry;
38 class 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;
741 template void DataOutput::writeJavaModifiedUtf8(
const std::u16string&);
743 template void DataOutput::writeJavaModifiedUtf8(
const std::wstring&);
749 #endif // GEODE_DATAOUTPUT_H_