| // Protocol Buffers - Google's data interchange format |
| // Copyright 2008 Google Inc. All rights reserved. |
| // https://developers.google.com/protocol-buffers/ |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // Author: kenton@google.com (Kenton Varda) |
| // atenasio@google.com (Chris Atenasio) (ZigZag transform) |
| // wink@google.com (Wink Saville) (refactored from wire_format.h) |
| // Based on original Protocol Buffers design by |
| // Sanjay Ghemawat, Jeff Dean, and others. |
| // |
| // This header is logically internal, but is made public because it is used |
| // from protocol-compiler-generated code, which may reside in other components. |
| |
| #ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ |
| #define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ |
| |
| |
| #include <limits> |
| #include <string> |
| |
| #include "google/protobuf/stubs/common.h" |
| #include "google/protobuf/port.h" |
| #include "absl/base/casts.h" |
| #include "google/protobuf/stubs/logging.h" |
| #include "google/protobuf/arenastring.h" |
| #include "google/protobuf/io/coded_stream.h" |
| #include "google/protobuf/message_lite.h" |
| #include "google/protobuf/port.h" |
| #include "google/protobuf/repeated_field.h" |
| |
| #ifndef NDEBUG |
| #define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED |
| #endif |
| |
| // Avoid conflict with iOS where <ConditionalMacros.h> #defines TYPE_BOOL. |
| // |
| // If some one needs the macro TYPE_BOOL in a file that includes this header, |
| // it's possible to bring it back using push/pop_macro as follows. |
| // |
| // #pragma push_macro("TYPE_BOOL") |
| // #include this header and/or all headers that need the macro to be undefined. |
| // #pragma pop_macro("TYPE_BOOL") |
| #undef TYPE_BOOL |
| |
| |
| // Must be included last. |
| #include "google/protobuf/port_def.inc" |
| |
| namespace google { |
| namespace protobuf { |
| namespace internal { |
| |
| // This class is for internal use by the protocol buffer library and by |
| // protocol-compiler-generated message classes. It must not be called |
| // directly by clients. |
| // |
| // This class contains helpers for implementing the binary protocol buffer |
| // wire format without the need for reflection. Use WireFormat when using |
| // reflection. |
| // |
| // This class is really a namespace that contains only static methods. |
| class PROTOBUF_EXPORT WireFormatLite { |
| public: |
| WireFormatLite() = delete; |
| // ----------------------------------------------------------------- |
| // Helper constants and functions related to the format. These are |
| // mostly meant for internal and generated code to use. |
| |
| // The wire format is composed of a sequence of tag/value pairs, each |
| // of which contains the value of one field (or one element of a repeated |
| // field). Each tag is encoded as a varint. The lower bits of the tag |
| // identify its wire type, which specifies the format of the data to follow. |
| // The rest of the bits contain the field number. Each type of field (as |
| // declared by FieldDescriptor::Type, in descriptor.h) maps to one of |
| // these wire types. Immediately following each tag is the field's value, |
| // encoded in the format specified by the wire type. Because the tag |
| // identifies the encoding of this data, it is possible to skip |
| // unrecognized fields for forwards compatibility. |
| |
| enum WireType |
| #ifndef SWIG |
| : int |
| #endif // !SWIG |
| { |
| WIRETYPE_VARINT = 0, |
| WIRETYPE_FIXED64 = 1, |
| WIRETYPE_LENGTH_DELIMITED = 2, |
| WIRETYPE_START_GROUP = 3, |
| WIRETYPE_END_GROUP = 4, |
| WIRETYPE_FIXED32 = 5, |
| }; |
| |
| // Lite alternative to FieldDescriptor::Type. Must be kept in sync. |
| enum FieldType { |
| TYPE_DOUBLE = 1, |
| TYPE_FLOAT = 2, |
| TYPE_INT64 = 3, |
| TYPE_UINT64 = 4, |
| TYPE_INT32 = 5, |
| TYPE_FIXED64 = 6, |
| TYPE_FIXED32 = 7, |
| TYPE_BOOL = 8, |
| TYPE_STRING = 9, |
| TYPE_GROUP = 10, |
| TYPE_MESSAGE = 11, |
| TYPE_BYTES = 12, |
| TYPE_UINT32 = 13, |
| TYPE_ENUM = 14, |
| TYPE_SFIXED32 = 15, |
| TYPE_SFIXED64 = 16, |
| TYPE_SINT32 = 17, |
| TYPE_SINT64 = 18, |
| MAX_FIELD_TYPE = 18, |
| }; |
| |
| // Lite alternative to FieldDescriptor::CppType. Must be kept in sync. |
| enum CppType { |
| CPPTYPE_INT32 = 1, |
| CPPTYPE_INT64 = 2, |
| CPPTYPE_UINT32 = 3, |
| CPPTYPE_UINT64 = 4, |
| CPPTYPE_DOUBLE = 5, |
| CPPTYPE_FLOAT = 6, |
| CPPTYPE_BOOL = 7, |
| CPPTYPE_ENUM = 8, |
| CPPTYPE_STRING = 9, |
| CPPTYPE_MESSAGE = 10, |
| MAX_CPPTYPE = 10, |
| }; |
| |
| // Helper method to get the CppType for a particular Type. |
| static CppType FieldTypeToCppType(FieldType type); |
| |
| // Given a FieldDescriptor::Type return its WireType |
| static inline WireFormatLite::WireType WireTypeForFieldType( |
| WireFormatLite::FieldType type) { |
| return kWireTypeForFieldType[type]; |
| } |
| |
| // Number of bits in a tag which identify the wire type. |
| static constexpr int kTagTypeBits = 3; |
| // Mask for those bits. |
| static constexpr uint32_t kTagTypeMask = (1 << kTagTypeBits) - 1; |
| |
| // Helper functions for encoding and decoding tags. (Inlined below and in |
| // _inl.h) |
| // |
| // This is different from MakeTag(field->number(), field->type()) in the |
| // case of packed repeated fields. |
| constexpr static uint32_t MakeTag(int field_number, WireType type); |
| static WireType GetTagWireType(uint32_t tag); |
| static int GetTagFieldNumber(uint32_t tag); |
| |
| // Compute the byte size of a tag. For groups, this includes both the start |
| // and end tags. |
| static inline size_t TagSize(int field_number, |
| WireFormatLite::FieldType type); |
| |
| // Skips a field value with the given tag. The input should start |
| // positioned immediately after the tag. Skipped values are simply |
| // discarded, not recorded anywhere. See WireFormat::SkipField() for a |
| // version that records to an UnknownFieldSet. |
| static bool SkipField(io::CodedInputStream* input, uint32_t tag); |
| |
| // Skips a field value with the given tag. The input should start |
| // positioned immediately after the tag. Skipped values are recorded to a |
| // CodedOutputStream. |
| static bool SkipField(io::CodedInputStream* input, uint32_t tag, |
| io::CodedOutputStream* output); |
| |
| // Reads and ignores a message from the input. Skipped values are simply |
| // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a |
| // version that records to an UnknownFieldSet. |
| static bool SkipMessage(io::CodedInputStream* input); |
| |
| // Reads and ignores a message from the input. Skipped values are recorded |
| // to a CodedOutputStream. |
| static bool SkipMessage(io::CodedInputStream* input, |
| io::CodedOutputStream* output); |
| |
| // This macro does the same thing as WireFormatLite::MakeTag(), but the |
| // result is usable as a compile-time constant, which makes it usable |
| // as a switch case or a template input. WireFormatLite::MakeTag() is more |
| // type-safe, though, so prefer it if possible. |
| #define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \ |
| static_cast<uint32_t>((static_cast<uint32_t>(FIELD_NUMBER) << 3) | (TYPE)) |
| |
| // These are the tags for the old MessageSet format, which was defined as: |
| // message MessageSet { |
| // repeated group Item = 1 { |
| // required int32 type_id = 2; |
| // required string message = 3; |
| // } |
| // } |
| static constexpr int kMessageSetItemNumber = 1; |
| static constexpr int kMessageSetTypeIdNumber = 2; |
| static constexpr int kMessageSetMessageNumber = 3; |
| static const int kMessageSetItemStartTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( |
| kMessageSetItemNumber, WireFormatLite::WIRETYPE_START_GROUP); |
| static const int kMessageSetItemEndTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( |
| kMessageSetItemNumber, WireFormatLite::WIRETYPE_END_GROUP); |
| static const int kMessageSetTypeIdTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( |
| kMessageSetTypeIdNumber, WireFormatLite::WIRETYPE_VARINT); |
| static const int kMessageSetMessageTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( |
| kMessageSetMessageNumber, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); |
| |
| // Byte size of all tags of a MessageSet::Item combined. |
| static const size_t kMessageSetItemTagsSize; |
| |
| // Helper functions for converting between floats/doubles and IEEE-754 |
| // uint32s/uint64s so that they can be written. (Assumes your platform |
| // uses IEEE-754 floats.) |
| static uint32_t EncodeFloat(float value); |
| static float DecodeFloat(uint32_t value); |
| static uint64_t EncodeDouble(double value); |
| static double DecodeDouble(uint64_t value); |
| |
| // Helper functions for mapping signed integers to unsigned integers in |
| // such a way that numbers with small magnitudes will encode to smaller |
| // varints. If you simply static_cast a negative number to an unsigned |
| // number and varint-encode it, it will always take 10 bytes, defeating |
| // the purpose of varint. So, for the "sint32" and "sint64" field types, |
| // we ZigZag-encode the values. |
| static uint32_t ZigZagEncode32(int32_t n); |
| static int32_t ZigZagDecode32(uint32_t n); |
| static uint64_t ZigZagEncode64(int64_t n); |
| static int64_t ZigZagDecode64(uint64_t n); |
| |
| // ================================================================= |
| // Methods for reading/writing individual field. |
| |
| // Read fields, not including tags. The assumption is that you already |
| // read the tag to determine what field to read. |
| |
| // For primitive fields, we just use a templatized routine parameterized by |
| // the represented type and the FieldType. These are specialized with the |
| // appropriate definition for each declared type. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static bool ReadPrimitive(io::CodedInputStream* input, |
| CType* value); |
| |
| // Reads repeated primitive values, with optimizations for repeats. |
| // tag_size and tag should both be compile-time constants provided by the |
| // protocol compiler. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedPrimitive( |
| int tag_size, uint32_t tag, io::CodedInputStream* input, |
| RepeatedField<CType>* value); |
| |
| // Identical to ReadRepeatedPrimitive, except will not inline the |
| // implementation. |
| template <typename CType, enum FieldType DeclaredType> |
| static bool ReadRepeatedPrimitiveNoInline(int tag_size, uint32_t tag, |
| io::CodedInputStream* input, |
| RepeatedField<CType>* value); |
| |
| // Reads a primitive value directly from the provided buffer. It returns a |
| // pointer past the segment of data that was read. |
| // |
| // This is only implemented for the types with fixed wire size, e.g. |
| // float, double, and the (s)fixed* types. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static const uint8_t* ReadPrimitiveFromArray( |
| const uint8_t* buffer, CType* value); |
| |
| // Reads a primitive packed field. |
| // |
| // This is only implemented for packable types. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static bool ReadPackedPrimitive( |
| io::CodedInputStream* input, RepeatedField<CType>* value); |
| |
| // Identical to ReadPackedPrimitive, except will not inline the |
| // implementation. |
| template <typename CType, enum FieldType DeclaredType> |
| static bool ReadPackedPrimitiveNoInline(io::CodedInputStream* input, |
| RepeatedField<CType>* value); |
| |
| // Read a packed enum field. If the is_valid function is not nullptr, values |
| // for which is_valid(value) returns false are silently dropped. |
| static bool ReadPackedEnumNoInline(io::CodedInputStream* input, |
| bool (*is_valid)(int), |
| RepeatedField<int>* values); |
| |
| // Read a packed enum field. If the is_valid function is not nullptr, values |
| // for which is_valid(value) returns false are appended to |
| // unknown_fields_stream. |
| static bool ReadPackedEnumPreserveUnknowns( |
| io::CodedInputStream* input, int field_number, bool (*is_valid)(int), |
| io::CodedOutputStream* unknown_fields_stream, RepeatedField<int>* values); |
| |
| // Read a string. ReadString(..., std::string* value) requires an |
| // existing std::string. |
| static inline bool ReadString(io::CodedInputStream* input, |
| std::string* value); |
| // ReadString(..., std::string** p) is internal-only, and should only be |
| // called from generated code. It starts by setting *p to "new std::string" if |
| // *p == &GetEmptyStringAlreadyInited(). It then invokes |
| // ReadString(io::CodedInputStream* input, *p). This is useful for reducing |
| // code size. |
| static inline bool ReadString(io::CodedInputStream* input, std::string** p); |
| // Analogous to ReadString(). |
| static bool ReadBytes(io::CodedInputStream* input, std::string* value); |
| static bool ReadBytes(io::CodedInputStream* input, std::string** p); |
| |
| enum Operation { |
| PARSE = 0, |
| SERIALIZE = 1, |
| }; |
| |
| // Returns true if the data is valid UTF-8. |
| static bool VerifyUtf8String(const char* data, int size, Operation op, |
| const char* field_name); |
| |
| template <typename MessageType> |
| static inline bool ReadGroup(int field_number, io::CodedInputStream* input, |
| MessageType* value); |
| |
| template <typename MessageType> |
| static inline bool ReadMessage(io::CodedInputStream* input, |
| MessageType* value); |
| |
| template <typename MessageType> |
| static inline bool ReadMessageNoVirtual(io::CodedInputStream* input, |
| MessageType* value) { |
| return ReadMessage(input, value); |
| } |
| |
| // Write a tag. The Write*() functions typically include the tag, so |
| // normally there's no need to call this unless using the Write*NoTag() |
| // variants. |
| PROTOBUF_NDEBUG_INLINE static void WriteTag(int field_number, WireType type, |
| io::CodedOutputStream* output); |
| |
| // Write fields, without tags. |
| PROTOBUF_NDEBUG_INLINE static void WriteInt32NoTag( |
| int32_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteInt64NoTag( |
| int64_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteUInt32NoTag( |
| uint32_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteUInt64NoTag( |
| uint64_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteSInt32NoTag( |
| int32_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteSInt64NoTag( |
| int64_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteFixed32NoTag( |
| uint32_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteFixed64NoTag( |
| uint64_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteSFixed32NoTag( |
| int32_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteSFixed64NoTag( |
| int64_t value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteFloatNoTag( |
| float value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteDoubleNoTag( |
| double value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteBoolNoTag( |
| bool value, io::CodedOutputStream* output); |
| PROTOBUF_NDEBUG_INLINE static void WriteEnumNoTag( |
| int value, io::CodedOutputStream* output); |
| |
| // Write array of primitive fields, without tags |
| static void WriteFloatArray(const float* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteDoubleArray(const double* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteFixed32Array(const uint32_t* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteFixed64Array(const uint64_t* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteSFixed32Array(const int32_t* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteSFixed64Array(const int64_t* a, int n, |
| io::CodedOutputStream* output); |
| static void WriteBoolArray(const bool* a, int n, |
| io::CodedOutputStream* output); |
| |
| // Write fields, including tags. |
| static void WriteInt32(int field_number, int32_t value, |
| io::CodedOutputStream* output); |
| static void WriteInt64(int field_number, int64_t value, |
| io::CodedOutputStream* output); |
| static void WriteUInt32(int field_number, uint32_t value, |
| io::CodedOutputStream* output); |
| static void WriteUInt64(int field_number, uint64_t value, |
| io::CodedOutputStream* output); |
| static void WriteSInt32(int field_number, int32_t value, |
| io::CodedOutputStream* output); |
| static void WriteSInt64(int field_number, int64_t value, |
| io::CodedOutputStream* output); |
| static void WriteFixed32(int field_number, uint32_t value, |
| io::CodedOutputStream* output); |
| static void WriteFixed64(int field_number, uint64_t value, |
| io::CodedOutputStream* output); |
| static void WriteSFixed32(int field_number, int32_t value, |
| io::CodedOutputStream* output); |
| static void WriteSFixed64(int field_number, int64_t value, |
| io::CodedOutputStream* output); |
| static void WriteFloat(int field_number, float value, |
| io::CodedOutputStream* output); |
| static void WriteDouble(int field_number, double value, |
| io::CodedOutputStream* output); |
| static void WriteBool(int field_number, bool value, |
| io::CodedOutputStream* output); |
| static void WriteEnum(int field_number, int value, |
| io::CodedOutputStream* output); |
| |
| static void WriteString(int field_number, const std::string& value, |
| io::CodedOutputStream* output); |
| static void WriteBytes(int field_number, const std::string& value, |
| io::CodedOutputStream* output); |
| static void WriteStringMaybeAliased(int field_number, |
| const std::string& value, |
| io::CodedOutputStream* output); |
| static void WriteBytesMaybeAliased(int field_number, const std::string& value, |
| io::CodedOutputStream* output); |
| |
| static void WriteGroup(int field_number, const MessageLite& value, |
| io::CodedOutputStream* output); |
| static void WriteMessage(int field_number, const MessageLite& value, |
| io::CodedOutputStream* output); |
| // Like above, but these will check if the output stream has enough |
| // space to write directly to a flat array. |
| static void WriteGroupMaybeToArray(int field_number, const MessageLite& value, |
| io::CodedOutputStream* output); |
| static void WriteMessageMaybeToArray(int field_number, |
| const MessageLite& value, |
| io::CodedOutputStream* output); |
| |
| // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The |
| // pointer must point at an instance of MessageType, *not* a subclass (or |
| // the subclass must not override SerializeWithCachedSizes()). |
| template <typename MessageType> |
| static inline void WriteGroupNoVirtual(int field_number, |
| const MessageType& value, |
| io::CodedOutputStream* output); |
| template <typename MessageType> |
| static inline void WriteMessageNoVirtual(int field_number, |
| const MessageType& value, |
| io::CodedOutputStream* output); |
| |
| // Like above, but use only *ToArray methods of CodedOutputStream. |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteTagToArray(int field_number, |
| WireType type, |
| uint8_t* target); |
| |
| // Write fields, without tags. |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32NoTagToArray( |
| int32_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64NoTagToArray( |
| int64_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32NoTagToArray( |
| uint32_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64NoTagToArray( |
| uint64_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32NoTagToArray( |
| int32_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64NoTagToArray( |
| int64_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32NoTagToArray( |
| uint32_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64NoTagToArray( |
| uint64_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32NoTagToArray( |
| int32_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64NoTagToArray( |
| int64_t value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatNoTagToArray( |
| float value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleNoTagToArray( |
| double value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolNoTagToArray(bool value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumNoTagToArray(int value, |
| uint8_t* target); |
| |
| // Write fields, without tags. These require that value.size() > 0. |
| template <typename T> |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WritePrimitiveNoTagToArray( |
| const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), |
| uint8_t* target); |
| template <typename T> |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixedNoTagToArray( |
| const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), |
| uint8_t* target); |
| |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32NoTagToArray( |
| const RepeatedField<uint32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64NoTagToArray( |
| const RepeatedField<uint64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32NoTagToArray( |
| const RepeatedField<uint32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64NoTagToArray( |
| const RepeatedField<uint64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatNoTagToArray( |
| const RepeatedField<float>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleNoTagToArray( |
| const RepeatedField<double>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolNoTagToArray( |
| const RepeatedField<bool>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumNoTagToArray( |
| const RepeatedField<int>& value, uint8_t* output); |
| |
| // Write fields, including tags. |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32ToArray(int field_number, |
| uint32_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64ToArray(int field_number, |
| uint64_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32ToArray(int field_number, |
| uint32_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64ToArray(int field_number, |
| uint64_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatToArray(int field_number, |
| float value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleToArray(int field_number, |
| double value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolToArray(int field_number, |
| bool value, |
| uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumToArray(int field_number, |
| int value, |
| uint8_t* target); |
| |
| template <typename T> |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WritePrimitiveToArray( |
| int field_number, const RepeatedField<T>& value, |
| uint8_t* (*Writer)(int, T, uint8_t*), uint8_t* target); |
| |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32ToArray( |
| int field_number, const RepeatedField<uint32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64ToArray( |
| int field_number, const RepeatedField<uint64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32ToArray( |
| int field_number, const RepeatedField<uint32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64ToArray( |
| int field_number, const RepeatedField<uint64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatToArray( |
| int field_number, const RepeatedField<float>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleToArray( |
| int field_number, const RepeatedField<double>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolToArray( |
| int field_number, const RepeatedField<bool>& value, uint8_t* output); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumToArray( |
| int field_number, const RepeatedField<int>& value, uint8_t* output); |
| |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteStringToArray( |
| int field_number, const std::string& value, uint8_t* target); |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBytesToArray( |
| int field_number, const std::string& value, uint8_t* target); |
| |
| // Whether to serialize deterministically (e.g., map keys are |
| // sorted) is a property of a CodedOutputStream, and in the process |
| // of serialization, the "ToArray" variants may be invoked. But they don't |
| // have a CodedOutputStream available, so they get an additional parameter |
| // telling them whether to serialize deterministically. |
| static uint8_t* InternalWriteGroup(int field_number, const MessageLite& value, |
| uint8_t* target, |
| io::EpsCopyOutputStream* stream); |
| static uint8_t* InternalWriteMessage(int field_number, |
| const MessageLite& value, |
| int cached_size, uint8_t* target, |
| io::EpsCopyOutputStream* stream); |
| |
| // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The |
| // pointer must point at an instance of MessageType, *not* a subclass (or |
| // the subclass must not override SerializeWithCachedSizes()). |
| template <typename MessageType> |
| PROTOBUF_NDEBUG_INLINE static uint8_t* InternalWriteGroupNoVirtualToArray( |
| int field_number, const MessageType& value, uint8_t* target); |
| template <typename MessageType> |
| PROTOBUF_NDEBUG_INLINE static uint8_t* InternalWriteMessageNoVirtualToArray( |
| int field_number, const MessageType& value, uint8_t* target); |
| |
| // For backward-compatibility, the last four methods also have versions |
| // that are non-deterministic always. |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteGroupToArray( |
| int field_number, const MessageLite& value, uint8_t* target) { |
| io::EpsCopyOutputStream stream( |
| target, |
| value.GetCachedSize() + |
| static_cast<int>(2 * io::CodedOutputStream::VarintSize32( |
| static_cast<uint32_t>(field_number) << 3)), |
| io::CodedOutputStream::IsDefaultSerializationDeterministic()); |
| return InternalWriteGroup(field_number, value, target, &stream); |
| } |
| PROTOBUF_NDEBUG_INLINE static uint8_t* WriteMessageToArray( |
| int field_number, const MessageLite& value, uint8_t* target) { |
| int size = value.GetCachedSize(); |
| io::EpsCopyOutputStream stream( |
| target, |
| size + static_cast<int>(io::CodedOutputStream::VarintSize32( |
| static_cast<uint32_t>(field_number) << 3) + |
| io::CodedOutputStream::VarintSize32(size)), |
| io::CodedOutputStream::IsDefaultSerializationDeterministic()); |
| return InternalWriteMessage(field_number, value, value.GetCachedSize(), |
| target, &stream); |
| } |
| |
| // Compute the byte size of a field. The XxSize() functions do NOT include |
| // the tag, so you must also call TagSize(). (This is because, for repeated |
| // fields, you should only call TagSize() once and multiply it by the element |
| // count, but you may have to call XxSize() for each individual element.) |
| static inline size_t Int32Size(int32_t value); |
| static inline size_t Int64Size(int64_t value); |
| static inline size_t UInt32Size(uint32_t value); |
| static inline size_t UInt64Size(uint64_t value); |
| static inline size_t SInt32Size(int32_t value); |
| static inline size_t SInt64Size(int64_t value); |
| static inline size_t EnumSize(int value); |
| static inline size_t Int32SizePlusOne(int32_t value); |
| static inline size_t Int64SizePlusOne(int64_t value); |
| static inline size_t UInt32SizePlusOne(uint32_t value); |
| static inline size_t UInt64SizePlusOne(uint64_t value); |
| static inline size_t SInt32SizePlusOne(int32_t value); |
| static inline size_t SInt64SizePlusOne(int64_t value); |
| static inline size_t EnumSizePlusOne(int value); |
| |
| static size_t Int32Size(const RepeatedField<int32_t>& value); |
| static size_t Int64Size(const RepeatedField<int64_t>& value); |
| static size_t UInt32Size(const RepeatedField<uint32_t>& value); |
| static size_t UInt64Size(const RepeatedField<uint64_t>& value); |
| static size_t SInt32Size(const RepeatedField<int32_t>& value); |
| static size_t SInt64Size(const RepeatedField<int64_t>& value); |
| static size_t EnumSize(const RepeatedField<int>& value); |
| |
| // These types always have the same size. |
| static constexpr size_t kFixed32Size = 4; |
| static constexpr size_t kFixed64Size = 8; |
| static constexpr size_t kSFixed32Size = 4; |
| static constexpr size_t kSFixed64Size = 8; |
| static constexpr size_t kFloatSize = 4; |
| static constexpr size_t kDoubleSize = 8; |
| static constexpr size_t kBoolSize = 1; |
| |
| static inline size_t StringSize(const std::string& value); |
| static inline size_t BytesSize(const std::string& value); |
| |
| template <typename MessageType> |
| static inline size_t GroupSize(const MessageType& value); |
| template <typename MessageType> |
| static inline size_t MessageSize(const MessageType& value); |
| |
| // Like above, but de-virtualize the call to ByteSize(). The |
| // pointer must point at an instance of MessageType, *not* a subclass (or |
| // the subclass must not override ByteSize()). |
| template <typename MessageType> |
| static inline size_t GroupSizeNoVirtual(const MessageType& value); |
| template <typename MessageType> |
| static inline size_t MessageSizeNoVirtual(const MessageType& value); |
| |
| // Given the length of data, calculate the byte size of the data on the |
| // wire if we encode the data as a length delimited field. |
| static inline size_t LengthDelimitedSize(size_t length); |
| |
| private: |
| // A helper method for the repeated primitive reader. This method has |
| // optimizations for primitive types that have fixed size on the wire, and |
| // can be read using potentially faster paths. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedFixedSizePrimitive( |
| int tag_size, uint32_t tag, io::CodedInputStream* input, |
| RepeatedField<CType>* value); |
| |
| // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields. |
| template <typename CType, enum FieldType DeclaredType> |
| PROTOBUF_NDEBUG_INLINE static bool ReadPackedFixedSizePrimitive( |
| io::CodedInputStream* input, RepeatedField<CType>* value); |
| |
| static const CppType kFieldTypeToCppTypeMap[]; |
| static const WireFormatLite::WireType kWireTypeForFieldType[]; |
| static void WriteSubMessageMaybeToArray(int size, const MessageLite& value, |
| io::CodedOutputStream* output); |
| }; |
| |
| // A class which deals with unknown values. The default implementation just |
| // discards them. WireFormat defines a subclass which writes to an |
| // UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since |
| // ExtensionSet is part of the lite library but UnknownFieldSet is not. |
| class PROTOBUF_EXPORT FieldSkipper { |
| public: |
| FieldSkipper() {} |
| virtual ~FieldSkipper() {} |
| |
| // Skip a field whose tag has already been consumed. |
| virtual bool SkipField(io::CodedInputStream* input, uint32_t tag); |
| |
| // Skip an entire message or group, up to an end-group tag (which is consumed) |
| // or end-of-stream. |
| virtual bool SkipMessage(io::CodedInputStream* input); |
| |
| // Deal with an already-parsed unrecognized enum value. The default |
| // implementation does nothing, but the UnknownFieldSet-based implementation |
| // saves it as an unknown varint. |
| virtual void SkipUnknownEnum(int field_number, int value); |
| }; |
| |
| // Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream. |
| |
| class PROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper { |
| public: |
| explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields) |
| : unknown_fields_(unknown_fields) {} |
| ~CodedOutputStreamFieldSkipper() override {} |
| |
| // implements FieldSkipper ----------------------------------------- |
| bool SkipField(io::CodedInputStream* input, uint32_t tag) override; |
| bool SkipMessage(io::CodedInputStream* input) override; |
| void SkipUnknownEnum(int field_number, int value) override; |
| |
| protected: |
| io::CodedOutputStream* unknown_fields_; |
| }; |
| |
| // inline methods ==================================================== |
| |
| inline WireFormatLite::CppType WireFormatLite::FieldTypeToCppType( |
| FieldType type) { |
| return kFieldTypeToCppTypeMap[type]; |
| } |
| |
| constexpr inline uint32_t WireFormatLite::MakeTag(int field_number, |
| WireType type) { |
| return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type); |
| } |
| |
| inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32_t tag) { |
| return static_cast<WireType>(tag & kTagTypeMask); |
| } |
| |
| inline int WireFormatLite::GetTagFieldNumber(uint32_t tag) { |
| return static_cast<int>(tag >> kTagTypeBits); |
| } |
| |
| inline size_t WireFormatLite::TagSize(int field_number, |
| WireFormatLite::FieldType type) { |
| size_t result = io::CodedOutputStream::VarintSize32( |
| static_cast<uint32_t>(field_number << kTagTypeBits)); |
| if (type == TYPE_GROUP) { |
| // Groups have both a start and an end tag. |
| return result * 2; |
| } else { |
| return result; |
| } |
| } |
| |
| inline uint32_t WireFormatLite::EncodeFloat(float value) { |
| return absl::bit_cast<uint32_t>(value); |
| } |
| |
| inline float WireFormatLite::DecodeFloat(uint32_t value) { |
| return absl::bit_cast<float>(value); |
| } |
| |
| inline uint64_t WireFormatLite::EncodeDouble(double value) { |
| return absl::bit_cast<uint64_t>(value); |
| } |
| |
| inline double WireFormatLite::DecodeDouble(uint64_t value) { |
| return absl::bit_cast<double>(value); |
| } |
| |
| // ZigZag Transform: Encodes signed integers so that they can be |
| // effectively used with varint encoding. |
| // |
| // varint operates on unsigned integers, encoding smaller numbers into |
| // fewer bytes. If you try to use it on a signed integer, it will treat |
| // this number as a very large unsigned integer, which means that even |
| // small signed numbers like -1 will take the maximum number of bytes |
| // (10) to encode. ZigZagEncode() maps signed integers to unsigned |
| // in such a way that those with a small absolute value will have smaller |
| // encoded values, making them appropriate for encoding using varint. |
| // |
| // int32_t -> uint32_t |
| // ------------------------- |
| // 0 -> 0 |
| // -1 -> 1 |
| // 1 -> 2 |
| // -2 -> 3 |
| // ... -> ... |
| // 2147483647 -> 4294967294 |
| // -2147483648 -> 4294967295 |
| // |
| // >> encode >> |
| // << decode << |
| |
| inline uint32_t WireFormatLite::ZigZagEncode32(int32_t n) { |
| // Note: the right-shift must be arithmetic |
| // Note: left shift must be unsigned because of overflow |
| return (static_cast<uint32_t>(n) << 1) ^ static_cast<uint32_t>(n >> 31); |
| } |
| |
| inline int32_t WireFormatLite::ZigZagDecode32(uint32_t n) { |
| // Note: Using unsigned types prevent undefined behavior |
| return static_cast<int32_t>((n >> 1) ^ (~(n & 1) + 1)); |
| } |
| |
| inline uint64_t WireFormatLite::ZigZagEncode64(int64_t n) { |
| // Note: the right-shift must be arithmetic |
| // Note: left shift must be unsigned because of overflow |
| return (static_cast<uint64_t>(n) << 1) ^ static_cast<uint64_t>(n >> 63); |
| } |
| |
| inline int64_t WireFormatLite::ZigZagDecode64(uint64_t n) { |
| // Note: Using unsigned types prevent undefined behavior |
| return static_cast<int64_t>((n >> 1) ^ (~(n & 1) + 1)); |
| } |
| |
| // String is for UTF-8 text only, but, even so, ReadString() can simply |
| // call ReadBytes(). |
| |
| inline bool WireFormatLite::ReadString(io::CodedInputStream* input, |
| std::string* value) { |
| return ReadBytes(input, value); |
| } |
| |
| inline bool WireFormatLite::ReadString(io::CodedInputStream* input, |
| std::string** p) { |
| return ReadBytes(input, p); |
| } |
| |
| inline uint8_t* InternalSerializeUnknownMessageSetItemsToArray( |
| const std::string& unknown_fields, uint8_t* target, |
| io::EpsCopyOutputStream* stream) { |
| return stream->WriteRaw(unknown_fields.data(), |
| static_cast<int>(unknown_fields.size()), target); |
| } |
| |
| inline size_t ComputeUnknownMessageSetItemsSize( |
| const std::string& unknown_fields) { |
| return unknown_fields.size(); |
| } |
| |
| // Implementation details of ReadPrimitive. |
| |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_INT32>( |
| io::CodedInputStream* input, int32_t* value) { |
| uint32_t temp; |
| if (!input->ReadVarint32(&temp)) return false; |
| *value = static_cast<int32_t>(temp); |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_INT64>( |
| io::CodedInputStream* input, int64_t* value) { |
| uint64_t temp; |
| if (!input->ReadVarint64(&temp)) return false; |
| *value = static_cast<int64_t>(temp); |
| return true; |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<uint32_t, WireFormatLite::TYPE_UINT32>( |
| io::CodedInputStream* input, uint32_t* value) { |
| return input->ReadVarint32(value); |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<uint64_t, WireFormatLite::TYPE_UINT64>( |
| io::CodedInputStream* input, uint64_t* value) { |
| return input->ReadVarint64(value); |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_SINT32>( |
| io::CodedInputStream* input, int32_t* value) { |
| uint32_t temp; |
| if (!input->ReadVarint32(&temp)) return false; |
| *value = ZigZagDecode32(temp); |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_SINT64>( |
| io::CodedInputStream* input, int64_t* value) { |
| uint64_t temp; |
| if (!input->ReadVarint64(&temp)) return false; |
| *value = ZigZagDecode64(temp); |
| return true; |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<uint32_t, WireFormatLite::TYPE_FIXED32>( |
| io::CodedInputStream* input, uint32_t* value) { |
| return input->ReadLittleEndian32(value); |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<uint64_t, WireFormatLite::TYPE_FIXED64>( |
| io::CodedInputStream* input, uint64_t* value) { |
| return input->ReadLittleEndian64(value); |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_SFIXED32>( |
| io::CodedInputStream* input, int32_t* value) { |
| uint32_t temp; |
| if (!input->ReadLittleEndian32(&temp)) return false; |
| *value = static_cast<int32_t>(temp); |
| return true; |
| } |
| template <> |
| inline bool |
| WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_SFIXED64>( |
| io::CodedInputStream* input, int64_t* value) { |
| uint64_t temp; |
| if (!input->ReadLittleEndian64(&temp)) return false; |
| *value = static_cast<int64_t>(temp); |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>( |
| io::CodedInputStream* input, float* value) { |
| uint32_t temp; |
| if (!input->ReadLittleEndian32(&temp)) return false; |
| *value = DecodeFloat(temp); |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>( |
| io::CodedInputStream* input, double* value) { |
| uint64_t temp; |
| if (!input->ReadLittleEndian64(&temp)) return false; |
| *value = DecodeDouble(temp); |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>( |
| io::CodedInputStream* input, bool* value) { |
| uint64_t temp; |
| if (!input->ReadVarint64(&temp)) return false; |
| *value = temp != 0; |
| return true; |
| } |
| template <> |
| inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( |
| io::CodedInputStream* input, int* value) { |
| uint32_t temp; |
| if (!input->ReadVarint32(&temp)) return false; |
| *value = static_cast<int>(temp); |
| return true; |
| } |
| |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<uint32_t, WireFormatLite::TYPE_FIXED32>( |
| const uint8_t* buffer, uint32_t* value) { |
| return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value); |
| } |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<uint64_t, WireFormatLite::TYPE_FIXED64>( |
| const uint8_t* buffer, uint64_t* value) { |
| return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value); |
| } |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<int32_t, WireFormatLite::TYPE_SFIXED32>( |
| const uint8_t* buffer, int32_t* value) { |
| uint32_t temp; |
| buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); |
| *value = static_cast<int32_t>(temp); |
| return buffer; |
| } |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<int64_t, WireFormatLite::TYPE_SFIXED64>( |
| const uint8_t* buffer, int64_t* value) { |
| uint64_t temp; |
| buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); |
| *value = static_cast<int64_t>(temp); |
| return buffer; |
| } |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<float, WireFormatLite::TYPE_FLOAT>( |
| const uint8_t* buffer, float* value) { |
| uint32_t temp; |
| buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); |
| *value = DecodeFloat(temp); |
| return buffer; |
| } |
| template <> |
| inline const uint8_t* |
| WireFormatLite::ReadPrimitiveFromArray<double, WireFormatLite::TYPE_DOUBLE>( |
| const uint8_t* buffer, double* value) { |
| uint64_t temp; |
| buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); |
| *value = DecodeDouble(temp); |
| return buffer; |
| } |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| inline bool WireFormatLite::ReadRepeatedPrimitive( |
| int, // tag_size, unused. |
| uint32_t tag, io::CodedInputStream* input, RepeatedField<CType>* values) { |
| CType value; |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->Add(value); |
| int elements_already_reserved = values->Capacity() - values->size(); |
| while (elements_already_reserved > 0 && input->ExpectTag(tag)) { |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->AddAlreadyReserved(value); |
| elements_already_reserved--; |
| } |
| return true; |
| } |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( |
| int tag_size, uint32_t tag, io::CodedInputStream* input, |
| RepeatedField<CType>* values) { |
| GOOGLE_ABSL_DCHECK_EQ(UInt32Size(tag), static_cast<size_t>(tag_size)); |
| CType value; |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->Add(value); |
| |
| // For fixed size values, repeated values can be read more quickly by |
| // reading directly from a raw array. |
| // |
| // We can get a tight loop by only reading as many elements as can be |
| // added to the RepeatedField without having to do any resizing. Additionally, |
| // we only try to read as many elements as are available from the current |
| // buffer space. Doing so avoids having to perform boundary checks when |
| // reading the value: the maximum number of elements that can be read is |
| // known outside of the loop. |
| const void* void_pointer; |
| int size; |
| input->GetDirectBufferPointerInline(&void_pointer, &size); |
| if (size > 0) { |
| const uint8_t* buffer = reinterpret_cast<const uint8_t*>(void_pointer); |
| // The number of bytes each type occupies on the wire. |
| const int per_value_size = tag_size + static_cast<int>(sizeof(value)); |
| |
| // parentheses around (std::min) prevents macro expansion of min(...) |
| int elements_available = |
| (std::min)(values->Capacity() - values->size(), size / per_value_size); |
| int num_read = 0; |
| while (num_read < elements_available && |
| (buffer = io::CodedInputStream::ExpectTagFromArray(buffer, tag)) != |
| nullptr) { |
| buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value); |
| values->AddAlreadyReserved(value); |
| ++num_read; |
| } |
| const int read_bytes = num_read * per_value_size; |
| if (read_bytes > 0) { |
| input->Skip(read_bytes); |
| } |
| } |
| return true; |
| } |
| |
| // Specializations of ReadRepeatedPrimitive for the fixed size types, which use |
| // the optimized code path. |
| #define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ |
| template <> \ |
| inline bool WireFormatLite::ReadRepeatedPrimitive< \ |
| CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ |
| int tag_size, uint32_t tag, io::CodedInputStream* input, \ |
| RepeatedField<CPPTYPE>* values) { \ |
| return ReadRepeatedFixedSizePrimitive<CPPTYPE, \ |
| WireFormatLite::DECLARED_TYPE>( \ |
| tag_size, tag, input, values); \ |
| } |
| |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32_t, TYPE_FIXED32) |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64_t, TYPE_FIXED64) |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32_t, TYPE_SFIXED32) |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64_t, TYPE_SFIXED64) |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) |
| READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) |
| |
| #undef READ_REPEATED_FIXED_SIZE_PRIMITIVE |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| bool WireFormatLite::ReadRepeatedPrimitiveNoInline( |
| int tag_size, uint32_t tag, io::CodedInputStream* input, |
| RepeatedField<CType>* value) { |
| return ReadRepeatedPrimitive<CType, DeclaredType>(tag_size, tag, input, |
| value); |
| } |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, |
| RepeatedField<CType>* values) { |
| int length; |
| if (!input->ReadVarintSizeAsInt(&length)) return false; |
| io::CodedInputStream::Limit limit = input->PushLimit(length); |
| while (input->BytesUntilLimit() > 0) { |
| CType value; |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->Add(value); |
| } |
| input->PopLimit(limit); |
| return true; |
| } |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| inline bool WireFormatLite::ReadPackedFixedSizePrimitive( |
| io::CodedInputStream* input, RepeatedField<CType>* values) { |
| int length; |
| if (!input->ReadVarintSizeAsInt(&length)) return false; |
| const int old_entries = values->size(); |
| const int new_entries = length / static_cast<int>(sizeof(CType)); |
| const int new_bytes = new_entries * static_cast<int>(sizeof(CType)); |
| if (new_bytes != length) return false; |
| // We would *like* to pre-allocate the buffer to write into (for |
| // speed), but *must* avoid performing a very large allocation due |
| // to a malicious user-supplied "length" above. So we have a fast |
| // path that pre-allocates when the "length" is less than a bound. |
| // We determine the bound by calling BytesUntilTotalBytesLimit() and |
| // BytesUntilLimit(). These return -1 to mean "no limit set". |
| // There are four cases: |
| // TotalBytesLimit Limit |
| // -1 -1 Use slow path. |
| // -1 >= 0 Use fast path if length <= Limit. |
| // >= 0 -1 Use slow path. |
| // >= 0 >= 0 Use fast path if length <= min(both limits). |
| int64_t bytes_limit = input->BytesUntilTotalBytesLimit(); |
| if (bytes_limit == -1) { |
| bytes_limit = input->BytesUntilLimit(); |
| } else { |
| // parentheses around (std::min) prevents macro expansion of min(...) |
| bytes_limit = |
| (std::min)(bytes_limit, static_cast<int64_t>(input->BytesUntilLimit())); |
| } |
| if (bytes_limit >= new_bytes) { |
| // Fast-path that pre-allocates *values to the final size. |
| #if defined(PROTOBUF_LITTLE_ENDIAN) |
| values->Resize(old_entries + new_entries, 0); |
| // values->mutable_data() may change after Resize(), so do this after: |
| void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries); |
| if (!input->ReadRaw(dest, new_bytes)) { |
| values->Truncate(old_entries); |
| return false; |
| } |
| #else |
| values->Reserve(old_entries + new_entries); |
| CType value; |
| for (int i = 0; i < new_entries; ++i) { |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->AddAlreadyReserved(value); |
| } |
| #endif |
| } else { |
| // This is the slow-path case where "length" may be too large to |
| // safely allocate. We read as much as we can into *values |
| // without pre-allocating "length" bytes. |
| CType value; |
| for (int i = 0; i < new_entries; ++i) { |
| if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; |
| values->Add(value); |
| } |
| } |
| return true; |
| } |
| |
| // Specializations of ReadPackedPrimitive for the fixed size types, which use |
| // an optimized code path. |
| #define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ |
| template <> \ |
| inline bool \ |
| WireFormatLite::ReadPackedPrimitive<CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ |
| io::CodedInputStream * input, RepeatedField<CPPTYPE> * values) { \ |
| return ReadPackedFixedSizePrimitive<CPPTYPE, \ |
| WireFormatLite::DECLARED_TYPE>( \ |
| input, values); \ |
| } |
| |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32_t, TYPE_FIXED32) |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64_t, TYPE_FIXED64) |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32_t, TYPE_SFIXED32) |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64_t, TYPE_SFIXED64) |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) |
| READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) |
| |
| #undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE |
| |
| template <typename CType, enum WireFormatLite::FieldType DeclaredType> |
| bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, |
| RepeatedField<CType>* values) { |
| return ReadPackedPrimitive<CType, DeclaredType>(input, values); |
| } |
| |
| |
| template <typename MessageType> |
| inline bool WireFormatLite::ReadGroup(int field_number, |
| io::CodedInputStream* input, |
| MessageType* value) { |
| if (!input->IncrementRecursionDepth()) return false; |
| if (!value->MergePartialFromCodedStream(input)) return false; |
| input->UnsafeDecrementRecursionDepth(); |
| // Make sure the last thing read was an end tag for this group. |
| if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { |
| return false; |
| } |
| return true; |
| } |
| template <typename MessageType> |
| inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, |
| MessageType* value) { |
| int length; |
| if (!input->ReadVarintSizeAsInt(&length)) return false; |
| std::pair<io::CodedInputStream::Limit, int> p = |
| input->IncrementRecursionDepthAndPushLimit(length); |
| if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false; |
| // Make sure that parsing stopped when the limit was hit, not at an endgroup |
| // tag. |
| return input->DecrementRecursionDepthAndPopLimit(p.first); |
| } |
| |
| // =================================================================== |
| |
| inline void WireFormatLite::WriteTag(int field_number, WireType type, |
| io::CodedOutputStream* output) { |
| output->WriteTag(MakeTag(field_number, type)); |
| } |
| |
| inline void WireFormatLite::WriteInt32NoTag(int32_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint32SignExtended(value); |
| } |
| inline void WireFormatLite::WriteInt64NoTag(int64_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint64(static_cast<uint64_t>(value)); |
| } |
| inline void WireFormatLite::WriteUInt32NoTag(uint32_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint32(value); |
| } |
| inline void WireFormatLite::WriteUInt64NoTag(uint64_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint64(value); |
| } |
| inline void WireFormatLite::WriteSInt32NoTag(int32_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint32(ZigZagEncode32(value)); |
| } |
| inline void WireFormatLite::WriteSInt64NoTag(int64_t value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint64(ZigZagEncode64(value)); |
| } |
| inline void WireFormatLite::WriteFixed32NoTag(uint32_t value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian32(value); |
| } |
| inline void WireFormatLite::WriteFixed64NoTag(uint64_t value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian64(value); |
| } |
| inline void WireFormatLite::WriteSFixed32NoTag(int32_t value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian32(static_cast<uint32_t>(value)); |
| } |
| inline void WireFormatLite::WriteSFixed64NoTag(int64_t value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian64(static_cast<uint64_t>(value)); |
| } |
| inline void WireFormatLite::WriteFloatNoTag(float value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian32(EncodeFloat(value)); |
| } |
| inline void WireFormatLite::WriteDoubleNoTag(double value, |
| io::CodedOutputStream* output) { |
| output->WriteLittleEndian64(EncodeDouble(value)); |
| } |
| inline void WireFormatLite::WriteBoolNoTag(bool value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint32(value ? 1 : 0); |
| } |
| inline void WireFormatLite::WriteEnumNoTag(int value, |
| io::CodedOutputStream* output) { |
| output->WriteVarint32SignExtended(value); |
| } |
| |
| // See comment on ReadGroupNoVirtual to understand the need for this template |
| // parameter name. |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline void WireFormatLite::WriteGroupNoVirtual( |
| int field_number, const MessageType_WorkAroundCppLookupDefect& value, |
| io::CodedOutputStream* output) { |
| WriteTag(field_number, WIRETYPE_START_GROUP, output); |
| value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); |
| WriteTag(field_number, WIRETYPE_END_GROUP, output); |
| } |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline void WireFormatLite::WriteMessageNoVirtual( |
| int field_number, const MessageType_WorkAroundCppLookupDefect& value, |
| io::CodedOutputStream* output) { |
| WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); |
| output->WriteVarint32( |
| value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); |
| value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); |
| } |
| |
| // =================================================================== |
| |
| inline uint8_t* WireFormatLite::WriteTagToArray(int field_number, WireType type, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), |
| target); |
| } |
| |
| inline uint8_t* WireFormatLite::WriteInt32NoTagToArray(int32_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteInt64NoTagToArray(int64_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint64ToArray( |
| static_cast<uint64_t>(value), target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt32NoTagToArray(uint32_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint32ToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt64NoTagToArray(uint64_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint64ToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt32NoTagToArray(int32_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt64NoTagToArray(int64_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed32NoTagToArray(uint32_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed64NoTagToArray(uint64_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed32NoTagToArray(int32_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian32ToArray( |
| static_cast<uint32_t>(value), target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed64NoTagToArray(int64_t value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian64ToArray( |
| static_cast<uint64_t>(value), target); |
| } |
| inline uint8_t* WireFormatLite::WriteFloatNoTagToArray(float value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteDoubleNoTagToArray(double value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteBoolNoTagToArray(bool value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); |
| } |
| inline uint8_t* WireFormatLite::WriteEnumNoTagToArray(int value, |
| uint8_t* target) { |
| return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); |
| } |
| |
| template <typename T> |
| inline uint8_t* WireFormatLite::WritePrimitiveNoTagToArray( |
| const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), |
| uint8_t* target) { |
| const int n = value.size(); |
| GOOGLE_ABSL_DCHECK_GT(n, 0); |
| |
| const T* ii = value.data(); |
| int i = 0; |
| do { |
| target = Writer(ii[i], target); |
| } while (++i < n); |
| |
| return target; |
| } |
| |
| template <typename T> |
| inline uint8_t* WireFormatLite::WriteFixedNoTagToArray( |
| const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), |
| uint8_t* target) { |
| #if defined(PROTOBUF_LITTLE_ENDIAN) |
| (void)Writer; |
| |
| const int n = value.size(); |
| GOOGLE_ABSL_DCHECK_GT(n, 0); |
| |
| const T* ii = value.data(); |
| const int bytes = n * static_cast<int>(sizeof(ii[0])); |
| memcpy(target, ii, static_cast<size_t>(bytes)); |
| return target + bytes; |
| #else |
| return WritePrimitiveNoTagToArray(value, Writer, target); |
| #endif |
| } |
| |
| inline uint8_t* WireFormatLite::WriteInt32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteInt32NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteInt64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteInt64NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt32NoTagToArray( |
| const RepeatedField<uint32_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteUInt32NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt64NoTagToArray( |
| const RepeatedField<uint64_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteUInt64NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteSInt32NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteSInt64NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed32NoTagToArray( |
| const RepeatedField<uint32_t>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteFixed32NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed64NoTagToArray( |
| const RepeatedField<uint64_t>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteFixed64NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed32NoTagToArray( |
| const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteSFixed32NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed64NoTagToArray( |
| const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteSFixed64NoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFloatNoTagToArray( |
| const RepeatedField<float>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteFloatNoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteDoubleNoTagToArray( |
| const RepeatedField<double>& value, uint8_t* target) { |
| return WriteFixedNoTagToArray(value, WriteDoubleNoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteBoolNoTagToArray( |
| const RepeatedField<bool>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteBoolNoTagToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteEnumNoTagToArray( |
| const RepeatedField<int>& value, uint8_t* target) { |
| return WritePrimitiveNoTagToArray(value, WriteEnumNoTagToArray, target); |
| } |
| |
| inline uint8_t* WireFormatLite::WriteInt32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteInt32NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteInt64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteInt64NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt32ToArray(int field_number, |
| uint32_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteUInt32NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt64ToArray(int field_number, |
| uint64_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteUInt64NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteSInt32NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteSInt64NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed32ToArray(int field_number, |
| uint32_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); |
| return WriteFixed32NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed64ToArray(int field_number, |
| uint64_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); |
| return WriteFixed64NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed32ToArray(int field_number, |
| int32_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); |
| return WriteSFixed32NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed64ToArray(int field_number, |
| int64_t value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); |
| return WriteSFixed64NoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFloatToArray(int field_number, float value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); |
| return WriteFloatNoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteDoubleToArray(int field_number, |
| double value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); |
| return WriteDoubleNoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteBoolToArray(int field_number, bool value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteBoolNoTagToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteEnumToArray(int field_number, int value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); |
| return WriteEnumNoTagToArray(value, target); |
| } |
| |
| template <typename T> |
| inline uint8_t* WireFormatLite::WritePrimitiveToArray( |
| int field_number, const RepeatedField<T>& value, |
| uint8_t* (*Writer)(int, T, uint8_t*), uint8_t* target) { |
| const int n = value.size(); |
| if (n == 0) { |
| return target; |
| } |
| |
| const T* ii = value.data(); |
| int i = 0; |
| do { |
| target = Writer(field_number, ii[i], target); |
| } while (++i < n); |
| |
| return target; |
| } |
| |
| inline uint8_t* WireFormatLite::WriteInt32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteInt32ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteInt64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteInt64ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt32ToArray( |
| int field_number, const RepeatedField<uint32_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteUInt32ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteUInt64ToArray( |
| int field_number, const RepeatedField<uint64_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteUInt64ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteSInt32ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteSInt64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteSInt64ToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed32ToArray( |
| int field_number, const RepeatedField<uint32_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteFixed32ToArray, |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteFixed64ToArray( |
| int field_number, const RepeatedField<uint64_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteFixed64ToArray, |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed32ToArray( |
| int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteSFixed32ToArray, |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteSFixed64ToArray( |
| int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteSFixed64ToArray, |
| target); |
| } |
| inline uint8_t* WireFormatLite::WriteFloatToArray( |
| int field_number, const RepeatedField<float>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteFloatToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteDoubleToArray( |
| int field_number, const RepeatedField<double>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteDoubleToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteBoolToArray( |
| int field_number, const RepeatedField<bool>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteBoolToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteEnumToArray( |
| int field_number, const RepeatedField<int>& value, uint8_t* target) { |
| return WritePrimitiveToArray(field_number, value, WriteEnumToArray, target); |
| } |
| inline uint8_t* WireFormatLite::WriteStringToArray(int field_number, |
| const std::string& value, |
| uint8_t* target) { |
| // String is for UTF-8 text only |
| // WARNING: In wire_format.cc, both strings and bytes are handled by |
| // WriteString() to avoid code duplication. If the implementations become |
| // different, you will need to update that usage. |
| target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); |
| return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); |
| } |
| inline uint8_t* WireFormatLite::WriteBytesToArray(int field_number, |
| const std::string& value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); |
| return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); |
| } |
| |
| |
| // See comment on ReadGroupNoVirtual to understand the need for this template |
| // parameter name. |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline uint8_t* WireFormatLite::InternalWriteGroupNoVirtualToArray( |
| int field_number, const MessageType_WorkAroundCppLookupDefect& value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); |
| target = value.MessageType_WorkAroundCppLookupDefect:: |
| SerializeWithCachedSizesToArray(target); |
| return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); |
| } |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline uint8_t* WireFormatLite::InternalWriteMessageNoVirtualToArray( |
| int field_number, const MessageType_WorkAroundCppLookupDefect& value, |
| uint8_t* target) { |
| target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); |
| target = io::CodedOutputStream::WriteVarint32ToArray( |
| static_cast<uint32_t>( |
| value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()), |
| target); |
| return value |
| .MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizesToArray( |
| target); |
| } |
| |
| // =================================================================== |
| |
| inline size_t WireFormatLite::Int32Size(int32_t value) { |
| return io::CodedOutputStream::VarintSize32SignExtended(value); |
| } |
| inline size_t WireFormatLite::Int64Size(int64_t value) { |
| return io::CodedOutputStream::VarintSize64(static_cast<uint64_t>(value)); |
| } |
| inline size_t WireFormatLite::UInt32Size(uint32_t value) { |
| return io::CodedOutputStream::VarintSize32(value); |
| } |
| inline size_t WireFormatLite::UInt64Size(uint64_t value) { |
| return io::CodedOutputStream::VarintSize64(value); |
| } |
| inline size_t WireFormatLite::SInt32Size(int32_t value) { |
| return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); |
| } |
| inline size_t WireFormatLite::SInt64Size(int64_t value) { |
| return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); |
| } |
| inline size_t WireFormatLite::EnumSize(int value) { |
| return io::CodedOutputStream::VarintSize32SignExtended(value); |
| } |
| inline size_t WireFormatLite::Int32SizePlusOne(int32_t value) { |
| return io::CodedOutputStream::VarintSize32SignExtendedPlusOne(value); |
| } |
| inline size_t WireFormatLite::Int64SizePlusOne(int64_t value) { |
| return io::CodedOutputStream::VarintSize64PlusOne( |
| static_cast<uint64_t>(value)); |
| } |
| inline size_t WireFormatLite::UInt32SizePlusOne(uint32_t value) { |
| return io::CodedOutputStream::VarintSize32PlusOne(value); |
| } |
| inline size_t WireFormatLite::UInt64SizePlusOne(uint64_t value) { |
| return io::CodedOutputStream::VarintSize64PlusOne(value); |
| } |
| inline size_t WireFormatLite::SInt32SizePlusOne(int32_t value) { |
| return io::CodedOutputStream::VarintSize32PlusOne(ZigZagEncode32(value)); |
| } |
| inline size_t WireFormatLite::SInt64SizePlusOne(int64_t value) { |
| return io::CodedOutputStream::VarintSize64PlusOne(ZigZagEncode64(value)); |
| } |
| inline size_t WireFormatLite::EnumSizePlusOne(int value) { |
| return io::CodedOutputStream::VarintSize32SignExtendedPlusOne(value); |
| } |
| |
| inline size_t WireFormatLite::StringSize(const std::string& value) { |
| return LengthDelimitedSize(value.size()); |
| } |
| inline size_t WireFormatLite::BytesSize(const std::string& value) { |
| return LengthDelimitedSize(value.size()); |
| } |
| |
| |
| template <typename MessageType> |
| inline size_t WireFormatLite::GroupSize(const MessageType& value) { |
| return value.ByteSizeLong(); |
| } |
| template <typename MessageType> |
| inline size_t WireFormatLite::MessageSize(const MessageType& value) { |
| return LengthDelimitedSize(value.ByteSizeLong()); |
| } |
| |
| // See comment on ReadGroupNoVirtual to understand the need for this template |
| // parameter name. |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline size_t WireFormatLite::GroupSizeNoVirtual( |
| const MessageType_WorkAroundCppLookupDefect& value) { |
| return value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong(); |
| } |
| template <typename MessageType_WorkAroundCppLookupDefect> |
| inline size_t WireFormatLite::MessageSizeNoVirtual( |
| const MessageType_WorkAroundCppLookupDefect& value) { |
| return LengthDelimitedSize( |
| value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong()); |
| } |
| |
| inline size_t WireFormatLite::LengthDelimitedSize(size_t length) { |
| // The static_cast here prevents an error in certain compiler configurations |
| // but is not technically correct--if length is too large to fit in a uint32_t |
| // then it will be silently truncated. We will need to fix this if we ever |
| // decide to start supporting serialized messages greater than 2 GiB in size. |
| return length + |
| io::CodedOutputStream::VarintSize32(static_cast<uint32_t>(length)); |
| } |
| |
| template <typename MS> |
| bool ParseMessageSetItemImpl(io::CodedInputStream* input, MS ms) { |
| // This method parses a group which should contain two fields: |
| // required int32 type_id = 2; |
| // required data message = 3; |
| |
| uint32_t last_type_id = 0; |
| |
| // If we see message data before the type_id, we'll append it to this so |
| // we can parse it later. |
| std::string message_data; |
| |
| enum class State { kNoTag, kHasType, kHasPayload, kDone }; |
| State state = State::kNoTag; |
| |
| while (true) { |
| const uint32_t tag = input->ReadTagNoLastTag(); |
| if (tag == 0) return false; |
| |
| switch (tag) { |
| case WireFormatLite::kMessageSetTypeIdTag: { |
| uint32_t type_id; |
| if (!input->ReadVarint32(&type_id)) return false; |
| if (state == State::kNoTag) { |
| last_type_id = type_id; |
| state = State::kHasType; |
| } else if (state == State::kHasPayload) { |
| // We saw some message data before the type_id. Have to parse it |
| // now. |
| io::CodedInputStream sub_input( |
| reinterpret_cast<const uint8_t*>(message_data.data()), |
| static_cast<int>(message_data.size())); |
| sub_input.SetRecursionLimit(input->RecursionBudget()); |
| if (!ms.ParseField(type_id, &sub_input)) { |
| return false; |
| } |
| message_data.clear(); |
| state = State::kDone; |
| } |
| |
| break; |
| } |
| |
| case WireFormatLite::kMessageSetMessageTag: { |
| if (state == State::kHasType) { |
| // Already saw type_id, so we can parse this directly. |
| if (!ms.ParseField(last_type_id, input)) { |
| return false; |
| } |
| state = State::kDone; |
| } else if (state == State::kNoTag) { |
| // We haven't seen a type_id yet. Append this data to message_data. |
| uint32_t length; |
| if (!input->ReadVarint32(&length)) return false; |
| if (static_cast<int32_t>(length) < 0) return false; |
| uint32_t size = static_cast<uint32_t>( |
| length + io::CodedOutputStream::VarintSize32(length)); |
| message_data.resize(size); |
| auto ptr = reinterpret_cast<uint8_t*>(&message_data[0]); |
| ptr = io::CodedOutputStream::WriteVarint32ToArray(length, ptr); |
| if (!input->ReadRaw(ptr, length)) return false; |
| state = State::kHasPayload; |
| } else { |
| if (!ms.SkipField(tag, input)) return false; |
| } |
| |
| break; |
| } |
| |
| case WireFormatLite::kMessageSetItemEndTag: { |
| return true; |
| } |
| |
| default: { |
| if (!ms.SkipField(tag, input)) return false; |
| } |
| } |
| } |
| } |
| |
| } // namespace internal |
| } // namespace protobuf |
| } // namespace google |
| |
| #include "google/protobuf/port_undef.inc" |
| |
| #endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ |