#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
#include <assert.h>
#include <atomic>
#include <climits>
#include <cstddef>
#include <cstring>
#include <limits>
#include <string>
#include <type_traits>
#include <utility>
#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
#pragma runtime_checks("c", off)
#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/port.h>
#include <google/protobuf/stubs/port.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
class DescriptorPool;
class MessageFactory;
class ZeroCopyCodedInputStream;
namespace internal {
void MapTestForceDeterministic();
class EpsCopyByteStream;
}
namespace io {
class CodedInputStream;
class CodedOutputStream;
class ZeroCopyInputStream; class ZeroCopyOutputStream;
class PROTOBUF_EXPORT CodedInputStream {
public:
explicit CodedInputStream(ZeroCopyInputStream* input);
explicit CodedInputStream(const uint8_t* buffer, int size);
~CodedInputStream();
inline bool IsFlat() const;
inline bool Skip(int count);
bool GetDirectBufferPointer(const void** data, int* size);
PROTOBUF_ALWAYS_INLINE
void GetDirectBufferPointerInline(const void** data, int* size);
bool ReadRaw(void* buffer, int size);
bool ReadString(std::string* buffer, int size);
bool ReadLittleEndian32(uint32_t* value);
bool ReadLittleEndian64(uint64_t* value);
static const uint8_t* ReadLittleEndian32FromArray(const uint8_t* buffer,
uint32_t* value);
static const uint8_t* ReadLittleEndian64FromArray(const uint8_t* buffer,
uint64_t* value);
bool ReadVarint32(uint32_t* value);
bool ReadVarint64(uint64_t* value);
bool ReadVarintSizeAsInt(int* value);
PROTOBUF_ALWAYS_INLINE uint32_t ReadTag() {
return last_tag_ = ReadTagNoLastTag();
}
PROTOBUF_ALWAYS_INLINE uint32_t ReadTagNoLastTag();
PROTOBUF_ALWAYS_INLINE
std::pair<uint32_t, bool> ReadTagWithCutoff(uint32_t cutoff) {
std::pair<uint32_t, bool> result = ReadTagWithCutoffNoLastTag(cutoff);
last_tag_ = result.first;
return result;
}
PROTOBUF_ALWAYS_INLINE
std::pair<uint32_t, bool> ReadTagWithCutoffNoLastTag(uint32_t cutoff);
PROTOBUF_ALWAYS_INLINE bool ExpectTag(uint32_t expected);
PROTOBUF_ALWAYS_INLINE
static const uint8_t* ExpectTagFromArray(const uint8_t* buffer,
uint32_t expected);
bool ExpectAtEnd();
bool LastTagWas(uint32_t expected);
void SetLastTag(uint32_t tag) { last_tag_ = tag; }
bool ConsumedEntireMessage();
void SetConsumed() { legitimate_message_end_ = true; }
typedef int Limit;
Limit PushLimit(int byte_limit);
void PopLimit(Limit limit);
int BytesUntilLimit() const;
int CurrentPosition() const;
void SetTotalBytesLimit(int total_bytes_limit);
int BytesUntilTotalBytesLimit() const;
void SetRecursionLimit(int limit);
int RecursionBudget() { return recursion_budget_; }
static int GetDefaultRecursionLimit() { return default_recursion_limit_; }
bool IncrementRecursionDepth();
void DecrementRecursionDepth();
void UnsafeDecrementRecursionDepth();
std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit(
int byte_limit);
Limit ReadLengthAndPushLimit();
bool DecrementRecursionDepthAndPopLimit(Limit limit);
bool CheckEntireMessageConsumedAndPopLimit(Limit limit);
void SetExtensionRegistry(const DescriptorPool* pool,
MessageFactory* factory);
const DescriptorPool* GetExtensionPool();
MessageFactory* GetExtensionFactory();
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
const uint8_t* buffer_;
const uint8_t* buffer_end_; ZeroCopyInputStream* input_;
int total_bytes_read_;
int overflow_bytes_;
uint32_t last_tag_;
bool legitimate_message_end_;
bool aliasing_enabled_;
Limit current_limit_;
int buffer_size_after_limit_;
int total_bytes_limit_;
int recursion_budget_;
int recursion_limit_;
const DescriptorPool* extension_pool_;
MessageFactory* extension_factory_;
bool SkipFallback(int count, int original_buffer_size);
void Advance(int amount);
void BackUpInputToCurrentPosition();
void RecomputeBufferLimits();
void PrintTotalBytesLimitError();
bool Refresh();
int64_t ReadVarint32Fallback(uint32_t first_byte_or_zero);
int ReadVarintSizeAsIntFallback();
std::pair<uint64_t, bool> ReadVarint64Fallback();
bool ReadVarint32Slow(uint32_t* value);
bool ReadVarint64Slow(uint64_t* value);
int ReadVarintSizeAsIntSlow();
bool ReadLittleEndian32Fallback(uint32_t* value);
bool ReadLittleEndian64Fallback(uint64_t* value);
uint32_t ReadTagFallback(uint32_t first_byte_or_zero);
uint32_t ReadTagSlow();
bool ReadStringFallback(std::string* buffer, int size);
int BufferSize() const;
static const int kDefaultTotalBytesLimit = INT_MAX;
static int default_recursion_limit_;
friend class google::protobuf::ZeroCopyCodedInputStream;
friend class google::protobuf::internal::EpsCopyByteStream;
};
class PROTOBUF_EXPORT EpsCopyOutputStream {
public:
enum { kSlopBytes = 16 };
EpsCopyOutputStream(ZeroCopyOutputStream* stream, bool deterministic,
uint8_t** pp)
: end_(buffer_),
stream_(stream),
is_serialization_deterministic_(deterministic) {
*pp = buffer_;
}
EpsCopyOutputStream(void* data, int size, bool deterministic)
: end_(static_cast<uint8_t*>(data) + size),
buffer_end_(nullptr),
stream_(nullptr),
is_serialization_deterministic_(deterministic) {}
EpsCopyOutputStream(void* data, int size, ZeroCopyOutputStream* stream,
bool deterministic, uint8_t** pp)
: stream_(stream), is_serialization_deterministic_(deterministic) {
*pp = SetInitialBuffer(data, size);
}
uint8_t* Trim(uint8_t* ptr);
PROTOBUF_NODISCARD uint8_t* EnsureSpace(uint8_t* ptr) {
if (PROTOBUF_PREDICT_FALSE(ptr >= end_)) {
return EnsureSpaceFallback(ptr);
}
return ptr;
}
uint8_t* WriteRaw(const void* data, size_t size, uint8_t* ptr) {
if (PROTOBUF_PREDICT_FALSE(end_ - ptr < static_cast<int>(size))) {
return WriteRawFallback(data, size, ptr);
}
#if __GNUC__ >= 12
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
#endif std::memcpy(ptr, data, size);
#if __GNUC__ >= 12
#pragma GCC diagnostic pop
#endif return ptr + size;
}
#ifndef NDEBUG
PROTOBUF_NOINLINE
#endif
uint8_t* WriteRawMaybeAliased(const void* data, int size, uint8_t* ptr) {
if (aliasing_enabled_) {
return WriteAliasedRaw(data, size, ptr);
} else {
return WriteRaw(data, size, ptr);
}
}
#ifndef NDEBUG
PROTOBUF_NOINLINE
#endif
uint8_t* WriteStringMaybeAliased(uint32_t num, const std::string& s,
uint8_t* ptr) {
std::ptrdiff_t size = s.size();
if (PROTOBUF_PREDICT_FALSE(
size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) {
return WriteStringMaybeAliasedOutline(num, s, ptr);
}
ptr = UnsafeVarint((num << 3) | 2, ptr);
*ptr++ = static_cast<uint8_t>(size);
std::memcpy(ptr, s.data(), size);
return ptr + size;
}
uint8_t* WriteBytesMaybeAliased(uint32_t num, const std::string& s,
uint8_t* ptr) {
return WriteStringMaybeAliased(num, s, ptr);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteString(uint32_t num, const T& s,
uint8_t* ptr) {
std::ptrdiff_t size = s.size();
if (PROTOBUF_PREDICT_FALSE(
size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) {
return WriteStringOutline(num, s, ptr);
}
ptr = UnsafeVarint((num << 3) | 2, ptr);
*ptr++ = static_cast<uint8_t>(size);
std::memcpy(ptr, s.data(), size);
return ptr + size;
}
template <typename T>
#ifndef NDEBUG
PROTOBUF_NOINLINE
#endif
uint8_t* WriteBytes(uint32_t num, const T& s, uint8_t* ptr) {
return WriteString(num, s, ptr);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode32);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt32Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, ZigZagEncode32);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt64Packed(int num, const T& r,
int size, uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, ZigZagEncode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteEnumPacked(int num, const T& r, int size,
uint8_t* ptr) {
return WriteVarintPacked(num, r, size, ptr, Encode64);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteFixedPacked(int num, const T& r,
uint8_t* ptr) {
ptr = EnsureSpace(ptr);
constexpr auto element_size = sizeof(typename T::value_type);
auto size = r.size() * element_size;
ptr = WriteLengthDelim(num, size, ptr);
return WriteRawLittleEndian<element_size>(r.data(), static_cast<int>(size),
ptr);
}
bool HadError() const { return had_error_; }
void EnableAliasing(bool enabled);
void SetSerializationDeterministic(bool value) {
is_serialization_deterministic_ = value;
}
bool IsSerializationDeterministic() const {
return is_serialization_deterministic_;
}
int64_t ByteCount(uint8_t* ptr) const;
private:
uint8_t* end_;
uint8_t* buffer_end_ = buffer_;
uint8_t buffer_[2 * kSlopBytes];
ZeroCopyOutputStream* stream_;
bool had_error_ = false;
bool aliasing_enabled_ = false; bool is_serialization_deterministic_;
bool skip_check_consistency = false;
uint8_t* EnsureSpaceFallback(uint8_t* ptr);
inline uint8_t* Next();
int Flush(uint8_t* ptr);
std::ptrdiff_t GetSize(uint8_t* ptr) const {
GOOGLE_DCHECK(ptr <= end_ + kSlopBytes); return end_ + kSlopBytes - ptr;
}
uint8_t* Error() {
had_error_ = true;
end_ = buffer_ + kSlopBytes;
return buffer_;
}
static constexpr int TagSize(uint32_t tag) {
return (tag < (1 << 7)) ? 1
: (tag < (1 << 14)) ? 2
: (tag < (1 << 21)) ? 3
: (tag < (1 << 28)) ? 4
: 5;
}
PROTOBUF_ALWAYS_INLINE uint8_t* WriteTag(uint32_t num, uint32_t wt,
uint8_t* ptr) {
GOOGLE_DCHECK(ptr < end_); return UnsafeVarint((num << 3) | wt, ptr);
}
PROTOBUF_ALWAYS_INLINE uint8_t* WriteLengthDelim(int num, uint32_t size,
uint8_t* ptr) {
ptr = WriteTag(num, 2, ptr);
return UnsafeWriteSize(size, ptr);
}
uint8_t* WriteRawFallback(const void* data, int size, uint8_t* ptr);
uint8_t* WriteAliasedRaw(const void* data, int size, uint8_t* ptr);
uint8_t* WriteStringMaybeAliasedOutline(uint32_t num, const std::string& s,
uint8_t* ptr);
uint8_t* WriteStringOutline(uint32_t num, const std::string& s, uint8_t* ptr);
template <typename T, typename E>
PROTOBUF_ALWAYS_INLINE uint8_t* WriteVarintPacked(int num, const T& r,
int size, uint8_t* ptr,
const E& encode) {
ptr = EnsureSpace(ptr);
ptr = WriteLengthDelim(num, size, ptr);
auto it = r.data();
auto end = it + r.size();
do {
ptr = EnsureSpace(ptr);
ptr = UnsafeVarint(encode(*it++), ptr);
} while (it < end);
return ptr;
}
static uint32_t Encode32(uint32_t v) { return v; }
static uint64_t Encode64(uint64_t v) { return v; }
static uint32_t ZigZagEncode32(int32_t v) {
return (static_cast<uint32_t>(v) << 1) ^ static_cast<uint32_t>(v >> 31);
}
static uint64_t ZigZagEncode64(int64_t v) {
return (static_cast<uint64_t>(v) << 1) ^ static_cast<uint64_t>(v >> 63);
}
template <typename T>
PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeVarint(T value, uint8_t* ptr) {
static_assert(std::is_unsigned<T>::value,
"Varint serialization must be unsigned");
ptr[0] = static_cast<uint8_t>(value);
if (value < 0x80) {
return ptr + 1;
}
ptr[0] |= static_cast<uint8_t>(0x80);
value >>= 7;
ptr[1] = static_cast<uint8_t>(value);
if (value < 0x80) {
return ptr + 2;
}
ptr += 2;
do {
ptr[-1] |= static_cast<uint8_t>(0x80);
value >>= 7;
*ptr = static_cast<uint8_t>(value);
++ptr;
} while (value >= 0x80);
return ptr;
}
PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeWriteSize(uint32_t value,
uint8_t* ptr) {
while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) {
*ptr = static_cast<uint8_t>(value | 0x80);
value >>= 7;
++ptr;
}
*ptr++ = static_cast<uint8_t>(value);
return ptr;
}
template <int S>
uint8_t* WriteRawLittleEndian(const void* data, int size, uint8_t* ptr);
#if !defined(PROTOBUF_LITTLE_ENDIAN) || \
defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
uint8_t* WriteRawLittleEndian32(const void* data, int size, uint8_t* ptr);
uint8_t* WriteRawLittleEndian64(const void* data, int size, uint8_t* ptr);
#endif
public:
uint8_t* SetInitialBuffer(void* data, int size) {
auto ptr = static_cast<uint8_t*>(data);
if (size > kSlopBytes) {
end_ = ptr + size - kSlopBytes;
buffer_end_ = nullptr;
return ptr;
} else {
end_ = buffer_ + size;
buffer_end_ = ptr;
return buffer_;
}
}
private:
uint8_t* FlushAndResetBuffer(uint8_t*);
bool Skip(int count, uint8_t** pp);
bool GetDirectBufferPointer(void** data, int* size, uint8_t** pp);
uint8_t* GetDirectBufferForNBytesAndAdvance(int size, uint8_t** pp);
friend class CodedOutputStream;
};
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<1>(const void* data,
int size,
uint8_t* ptr) {
return WriteRaw(data, size, ptr);
}
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data,
int size,
uint8_t* ptr) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
return WriteRaw(data, size, ptr);
#else
return WriteRawLittleEndian32(data, size, ptr);
#endif
}
template <>
inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data,
int size,
uint8_t* ptr) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
return WriteRaw(data, size, ptr);
#else
return WriteRawLittleEndian64(data, size, ptr);
#endif
}
class PROTOBUF_EXPORT CodedOutputStream {
public:
template <class Stream, class = typename std::enable_if<std::is_base_of<
ZeroCopyOutputStream, Stream>::value>::type>
explicit CodedOutputStream(Stream* stream);
template <class Stream, class = typename std::enable_if<std::is_base_of<
ZeroCopyOutputStream, Stream>::value>::type>
CodedOutputStream(Stream* stream, bool eager_init);
~CodedOutputStream();
bool HadError() {
cur_ = impl_.FlushAndResetBuffer(cur_);
GOOGLE_DCHECK(cur_);
return impl_.HadError();
}
void Trim() { cur_ = impl_.Trim(cur_); }
bool Skip(int count) { return impl_.Skip(count, &cur_); }
bool GetDirectBufferPointer(void** data, int* size) {
return impl_.GetDirectBufferPointer(data, size, &cur_);
}
inline uint8_t* GetDirectBufferForNBytesAndAdvance(int size) {
return impl_.GetDirectBufferForNBytesAndAdvance(size, &cur_);
}
void WriteRaw(const void* buffer, int size) {
cur_ = impl_.WriteRaw(buffer, size, cur_);
}
void WriteRawMaybeAliased(const void* data, int size);
static uint8_t* WriteRawToArray(const void* buffer, int size,
uint8_t* target);
void WriteString(const std::string& str);
static uint8_t* WriteStringToArray(const std::string& str, uint8_t* target);
static uint8_t* WriteStringWithSizeToArray(const std::string& str,
uint8_t* target);
void WriteLittleEndian32(uint32_t value) {
cur_ = impl_.EnsureSpace(cur_);
SetCur(WriteLittleEndian32ToArray(value, Cur()));
}
static uint8_t* WriteLittleEndian32ToArray(uint32_t value, uint8_t* target);
void WriteLittleEndian64(uint64_t value) {
cur_ = impl_.EnsureSpace(cur_);
SetCur(WriteLittleEndian64ToArray(value, Cur()));
}
static uint8_t* WriteLittleEndian64ToArray(uint64_t value, uint8_t* target);
void WriteVarint32(uint32_t value);
static uint8_t* WriteVarint32ToArray(uint32_t value, uint8_t* target);
static uint8_t* WriteVarint32ToArrayOutOfLine(uint32_t value,
uint8_t* target);
void WriteVarint64(uint64_t value);
static uint8_t* WriteVarint64ToArray(uint64_t value, uint8_t* target);
void WriteVarint32SignExtended(int32_t value);
static uint8_t* WriteVarint32SignExtendedToArray(int32_t value,
uint8_t* target);
void WriteTag(uint32_t value);
PROTOBUF_ALWAYS_INLINE
static uint8_t* WriteTagToArray(uint32_t value, uint8_t* target);
static size_t VarintSize32(uint32_t value);
static size_t VarintSize64(uint64_t value);
static size_t VarintSize32SignExtended(int32_t value);
static size_t VarintSize32PlusOne(uint32_t value);
static size_t VarintSize64PlusOne(uint64_t value);
static size_t VarintSize32SignExtendedPlusOne(int32_t value);
template <uint32_t Value>
struct StaticVarintSize32 {
static const size_t value = (Value < (1 << 7)) ? 1
: (Value < (1 << 14)) ? 2
: (Value < (1 << 21)) ? 3
: (Value < (1 << 28)) ? 4
: 5;
};
int ByteCount() const {
return static_cast<int>(impl_.ByteCount(cur_) - start_count_);
}
void EnableAliasing(bool enabled) { impl_.EnableAliasing(enabled); }
void SetSerializationDeterministic(bool value) {
impl_.SetSerializationDeterministic(value);
}
bool IsSerializationDeterministic() const {
return impl_.IsSerializationDeterministic();
}
static bool IsDefaultSerializationDeterministic() {
return default_serialization_deterministic_.load(
std::memory_order_relaxed) != 0;
}
template <typename Func>
void Serialize(const Func& func);
uint8_t* Cur() const { return cur_; }
void SetCur(uint8_t* ptr) { cur_ = ptr; }
EpsCopyOutputStream* EpsCopy() { return &impl_; }
private:
template <class Stream>
void InitEagerly(Stream* stream);
EpsCopyOutputStream impl_;
uint8_t* cur_;
int64_t start_count_;
static std::atomic<bool> default_serialization_deterministic_;
friend void internal::MapTestForceDeterministic();
static void SetDefaultSerializationDeterministic() {
default_serialization_deterministic_.store(true, std::memory_order_relaxed);
}
static uint8_t* WriteVarint32ToArrayOutOfLineHelper(uint32_t value,
uint8_t* target);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
};
inline bool CodedInputStream::ReadVarint32(uint32_t* value) {
uint32_t v = 0;
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) {
v = *buffer_;
if (v < 0x80) {
*value = v;
Advance(1);
return true;
}
}
int64_t result = ReadVarint32Fallback(v);
*value = static_cast<uint32_t>(result);
return result >= 0;
}
inline bool CodedInputStream::ReadVarint64(uint64_t* value) {
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
*value = *buffer_;
Advance(1);
return true;
}
std::pair<uint64_t, bool> p = ReadVarint64Fallback();
*value = p.first;
return p.second;
}
inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) {
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) {
int v = *buffer_;
if (v < 0x80) {
*value = v;
Advance(1);
return true;
}
}
*value = ReadVarintSizeAsIntFallback();
return *value >= 0;
}
inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray(
const uint8_t* buffer, uint32_t* value) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
memcpy(value, buffer, sizeof(*value));
return buffer + sizeof(*value);
#else
*value = (static_cast<uint32_t>(buffer[0])) |
(static_cast<uint32_t>(buffer[1]) << 8) |
(static_cast<uint32_t>(buffer[2]) << 16) |
(static_cast<uint32_t>(buffer[3]) << 24);
return buffer + sizeof(*value);
#endif
}
inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray(
const uint8_t* buffer, uint64_t* value) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
memcpy(value, buffer, sizeof(*value));
return buffer + sizeof(*value);
#else
uint32_t part0 = (static_cast<uint32_t>(buffer[0])) |
(static_cast<uint32_t>(buffer[1]) << 8) |
(static_cast<uint32_t>(buffer[2]) << 16) |
(static_cast<uint32_t>(buffer[3]) << 24);
uint32_t part1 = (static_cast<uint32_t>(buffer[4])) |
(static_cast<uint32_t>(buffer[5]) << 8) |
(static_cast<uint32_t>(buffer[6]) << 16) |
(static_cast<uint32_t>(buffer[7]) << 24);
*value = static_cast<uint64_t>(part0) | (static_cast<uint64_t>(part1) << 32);
return buffer + sizeof(*value);
#endif
}
inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
buffer_ = ReadLittleEndian32FromArray(buffer_, value);
return true;
} else {
return ReadLittleEndian32Fallback(value);
}
#else
return ReadLittleEndian32Fallback(value);
#endif
}
inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) {
buffer_ = ReadLittleEndian64FromArray(buffer_, value);
return true;
} else {
return ReadLittleEndian64Fallback(value);
}
#else
return ReadLittleEndian64Fallback(value);
#endif
}
inline uint32_t CodedInputStream::ReadTagNoLastTag() {
uint32_t v = 0;
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) {
v = *buffer_;
if (v < 0x80) {
Advance(1);
return v;
}
}
v = ReadTagFallback(v);
return v;
}
inline std::pair<uint32_t, bool> CodedInputStream::ReadTagWithCutoffNoLastTag(
uint32_t cutoff) {
uint32_t first_byte_or_zero = 0;
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) {
first_byte_or_zero = buffer_[0];
if (static_cast<int8_t>(buffer_[0]) > 0) {
const uint32_t kMax1ByteVarint = 0x7f;
uint32_t tag = buffer_[0];
Advance(1);
return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
}
if (cutoff >= 0x80 && PROTOBUF_PREDICT_TRUE(buffer_ + 1 < buffer_end_) &&
PROTOBUF_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) {
const uint32_t kMax2ByteVarint = (0x7f << 7) + 0x7f;
uint32_t tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80);
Advance(2);
bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff;
return std::make_pair(tag, at_or_below_cutoff);
}
}
const uint32_t tag = ReadTagFallback(first_byte_or_zero);
return std::make_pair(tag, static_cast<uint32_t>(tag - 1) < cutoff);
}
inline bool CodedInputStream::LastTagWas(uint32_t expected) {
return last_tag_ == expected;
}
inline bool CodedInputStream::ConsumedEntireMessage() {
return legitimate_message_end_;
}
inline bool CodedInputStream::ExpectTag(uint32_t expected) {
if (expected < (1 << 7)) {
if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) &&
buffer_[0] == expected) {
Advance(1);
return true;
} else {
return false;
}
} else if (expected < (1 << 14)) {
if (PROTOBUF_PREDICT_TRUE(BufferSize() >= 2) &&
buffer_[0] == static_cast<uint8_t>(expected | 0x80) &&
buffer_[1] == static_cast<uint8_t>(expected >> 7)) {
Advance(2);
return true;
} else {
return false;
}
} else {
return false;
}
}
inline const uint8_t* CodedInputStream::ExpectTagFromArray(
const uint8_t* buffer, uint32_t expected) {
if (expected < (1 << 7)) {
if (buffer[0] == expected) {
return buffer + 1;
}
} else if (expected < (1 << 14)) {
if (buffer[0] == static_cast<uint8_t>(expected | 0x80) &&
buffer[1] == static_cast<uint8_t>(expected >> 7)) {
return buffer + 2;
}
}
return nullptr;
}
inline void CodedInputStream::GetDirectBufferPointerInline(const void** data,
int* size) {
*data = buffer_;
*size = static_cast<int>(buffer_end_ - buffer_);
}
inline bool CodedInputStream::ExpectAtEnd() {
if (buffer_ == buffer_end_ && ((buffer_size_after_limit_ != 0) ||
(total_bytes_read_ == current_limit_))) {
last_tag_ = 0; legitimate_message_end_ = true; return true;
} else {
return false;
}
}
inline int CodedInputStream::CurrentPosition() const {
return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_);
}
inline void CodedInputStream::Advance(int amount) { buffer_ += amount; }
inline void CodedInputStream::SetRecursionLimit(int limit) {
recursion_budget_ += limit - recursion_limit_;
recursion_limit_ = limit;
}
inline bool CodedInputStream::IncrementRecursionDepth() {
--recursion_budget_;
return recursion_budget_ >= 0;
}
inline void CodedInputStream::DecrementRecursionDepth() {
if (recursion_budget_ < recursion_limit_) ++recursion_budget_;
}
inline void CodedInputStream::UnsafeDecrementRecursionDepth() {
assert(recursion_budget_ < recursion_limit_);
++recursion_budget_;
}
inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
MessageFactory* factory) {
extension_pool_ = pool;
extension_factory_ = factory;
}
inline const DescriptorPool* CodedInputStream::GetExtensionPool() {
return extension_pool_;
}
inline MessageFactory* CodedInputStream::GetExtensionFactory() {
return extension_factory_;
}
inline int CodedInputStream::BufferSize() const {
return static_cast<int>(buffer_end_ - buffer_);
}
inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
: buffer_(nullptr),
buffer_end_(nullptr),
input_(input),
total_bytes_read_(0),
overflow_bytes_(0),
last_tag_(0),
legitimate_message_end_(false),
aliasing_enabled_(false),
current_limit_(std::numeric_limits<int32_t>::max()),
buffer_size_after_limit_(0),
total_bytes_limit_(kDefaultTotalBytesLimit),
recursion_budget_(default_recursion_limit_),
recursion_limit_(default_recursion_limit_),
extension_pool_(nullptr),
extension_factory_(nullptr) {
Refresh();
}
inline CodedInputStream::CodedInputStream(const uint8_t* buffer, int size)
: buffer_(buffer),
buffer_end_(buffer + size),
input_(nullptr),
total_bytes_read_(size),
overflow_bytes_(0),
last_tag_(0),
legitimate_message_end_(false),
aliasing_enabled_(false),
current_limit_(size),
buffer_size_after_limit_(0),
total_bytes_limit_(kDefaultTotalBytesLimit),
recursion_budget_(default_recursion_limit_),
recursion_limit_(default_recursion_limit_),
extension_pool_(nullptr),
extension_factory_(nullptr) {
}
inline bool CodedInputStream::IsFlat() const { return input_ == nullptr; }
inline bool CodedInputStream::Skip(int count) {
if (count < 0) return false;
const int original_buffer_size = BufferSize();
if (count <= original_buffer_size) {
Advance(count);
return true;
}
return SkipFallback(count, original_buffer_size);
}
template <class Stream, class>
inline CodedOutputStream::CodedOutputStream(Stream* stream)
: impl_(stream, IsDefaultSerializationDeterministic(), &cur_),
start_count_(stream->ByteCount()) {
InitEagerly(stream);
}
template <class Stream, class>
inline CodedOutputStream::CodedOutputStream(Stream* stream, bool eager_init)
: impl_(stream, IsDefaultSerializationDeterministic(), &cur_),
start_count_(stream->ByteCount()) {
if (eager_init) {
InitEagerly(stream);
}
}
template <class Stream>
inline void CodedOutputStream::InitEagerly(Stream* stream) {
void* data;
int size;
if (PROTOBUF_PREDICT_TRUE(stream->Next(&data, &size) && size > 0)) {
cur_ = impl_.SetInitialBuffer(data, size);
}
}
inline uint8_t* CodedOutputStream::WriteVarint32ToArray(uint32_t value,
uint8_t* target) {
return EpsCopyOutputStream::UnsafeVarint(value, target);
}
inline uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLine(
uint32_t value, uint8_t* target) {
target[0] = static_cast<uint8_t>(value);
if (value < 0x80) {
return target + 1;
} else {
return WriteVarint32ToArrayOutOfLineHelper(value, target);
}
}
inline uint8_t* CodedOutputStream::WriteVarint64ToArray(uint64_t value,
uint8_t* target) {
return EpsCopyOutputStream::UnsafeVarint(value, target);
}
inline void CodedOutputStream::WriteVarint32SignExtended(int32_t value) {
WriteVarint64(static_cast<uint64_t>(value));
}
inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray(
int32_t value, uint8_t* target) {
return WriteVarint64ToArray(static_cast<uint64_t>(value), target);
}
inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value,
uint8_t* target) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
memcpy(target, &value, sizeof(value));
#else
target[0] = static_cast<uint8_t>(value);
target[1] = static_cast<uint8_t>(value >> 8);
target[2] = static_cast<uint8_t>(value >> 16);
target[3] = static_cast<uint8_t>(value >> 24);
#endif
return target + sizeof(value);
}
inline uint8_t* CodedOutputStream::WriteLittleEndian64ToArray(uint64_t value,
uint8_t* target) {
#if defined(PROTOBUF_LITTLE_ENDIAN) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
memcpy(target, &value, sizeof(value));
#else
uint32_t part0 = static_cast<uint32_t>(value);
uint32_t part1 = static_cast<uint32_t>(value >> 32);
target[0] = static_cast<uint8_t>(part0);
target[1] = static_cast<uint8_t>(part0 >> 8);
target[2] = static_cast<uint8_t>(part0 >> 16);
target[3] = static_cast<uint8_t>(part0 >> 24);
target[4] = static_cast<uint8_t>(part1);
target[5] = static_cast<uint8_t>(part1 >> 8);
target[6] = static_cast<uint8_t>(part1 >> 16);
target[7] = static_cast<uint8_t>(part1 >> 24);
#endif
return target + sizeof(value);
}
inline void CodedOutputStream::WriteVarint32(uint32_t value) {
cur_ = impl_.EnsureSpace(cur_);
SetCur(WriteVarint32ToArray(value, Cur()));
}
inline void CodedOutputStream::WriteVarint64(uint64_t value) {
cur_ = impl_.EnsureSpace(cur_);
SetCur(WriteVarint64ToArray(value, Cur()));
}
inline void CodedOutputStream::WriteTag(uint32_t value) {
WriteVarint32(value);
}
inline uint8_t* CodedOutputStream::WriteTagToArray(uint32_t value,
uint8_t* target) {
return WriteVarint32ToArray(value, target);
}
inline size_t CodedOutputStream::VarintSize32(uint32_t value) {
uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1);
return static_cast<size_t>((log2value * 9 + 73) / 64);
}
inline size_t CodedOutputStream::VarintSize32PlusOne(uint32_t value) {
uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1);
return static_cast<size_t>((log2value * 9 + 73 + 64) / 64);
}
inline size_t CodedOutputStream::VarintSize64(uint64_t value) {
uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1);
return static_cast<size_t>((log2value * 9 + 73) / 64);
}
inline size_t CodedOutputStream::VarintSize64PlusOne(uint64_t value) {
uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1);
return static_cast<size_t>((log2value * 9 + 73 + 64) / 64);
}
inline size_t CodedOutputStream::VarintSize32SignExtended(int32_t value) {
return VarintSize64(static_cast<uint64_t>(int64_t{value}));
}
inline size_t CodedOutputStream::VarintSize32SignExtendedPlusOne(
int32_t value) {
return VarintSize64PlusOne(static_cast<uint64_t>(int64_t{value}));
}
inline void CodedOutputStream::WriteString(const std::string& str) {
WriteRaw(str.data(), static_cast<int>(str.size()));
}
inline void CodedOutputStream::WriteRawMaybeAliased(const void* data,
int size) {
cur_ = impl_.WriteRawMaybeAliased(data, size, cur_);
}
inline uint8_t* CodedOutputStream::WriteRawToArray(const void* data, int size,
uint8_t* target) {
memcpy(target, data, size);
return target + size;
}
inline uint8_t* CodedOutputStream::WriteStringToArray(const std::string& str,
uint8_t* target) {
return WriteRawToArray(str.data(), static_cast<int>(str.size()), target);
}
} } }
#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
#pragma runtime_checks("c", restore)
#endif
#include <google/protobuf/port_undef.inc>
#endif