Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:20

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
0009 #define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
0010 
0011 #include "google/protobuf/extension_set.h"
0012 #include "google/protobuf/metadata_lite.h"
0013 #include "google/protobuf/parse_context.h"
0014 
0015 namespace google {
0016 namespace protobuf {
0017 namespace internal {
0018 
0019 template <typename T>
0020 const char* ExtensionSet::ParseFieldWithExtensionInfo(
0021     int number, bool was_packed_on_wire, const ExtensionInfo& extension,
0022     InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) {
0023   if (was_packed_on_wire) {
0024     switch (extension.type) {
0025 #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE)                                \
0026   case WireFormatLite::TYPE_##UPPERCASE:                                     \
0027     return internal::Packed##CPP_CAMELCASE##Parser(                          \
0028         MutableRawRepeatedField(number, extension.type, extension.is_packed, \
0029                                 extension.descriptor),                       \
0030         ptr, ctx);
0031       HANDLE_TYPE(INT32, Int32);
0032       HANDLE_TYPE(INT64, Int64);
0033       HANDLE_TYPE(UINT32, UInt32);
0034       HANDLE_TYPE(UINT64, UInt64);
0035       HANDLE_TYPE(SINT32, SInt32);
0036       HANDLE_TYPE(SINT64, SInt64);
0037       HANDLE_TYPE(FIXED32, Fixed32);
0038       HANDLE_TYPE(FIXED64, Fixed64);
0039       HANDLE_TYPE(SFIXED32, SFixed32);
0040       HANDLE_TYPE(SFIXED64, SFixed64);
0041       HANDLE_TYPE(FLOAT, Float);
0042       HANDLE_TYPE(DOUBLE, Double);
0043       HANDLE_TYPE(BOOL, Bool);
0044 #undef HANDLE_TYPE
0045 
0046       case WireFormatLite::TYPE_ENUM:
0047         return internal::PackedEnumParserArg<T>(
0048             MutableRawRepeatedField(number, extension.type, extension.is_packed,
0049                                     extension.descriptor),
0050             ptr, ctx, extension.enum_validity_check.func,
0051             extension.enum_validity_check.arg, metadata, number);
0052       case WireFormatLite::TYPE_STRING:
0053       case WireFormatLite::TYPE_BYTES:
0054       case WireFormatLite::TYPE_GROUP:
0055       case WireFormatLite::TYPE_MESSAGE:
0056         ABSL_LOG(FATAL) << "Non-primitive types can't be packed.";
0057         break;
0058     }
0059   } else {
0060     switch (extension.type) {
0061 #define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE)                        \
0062   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
0063     uint64_t value;                                                         \
0064     ptr = VarintParse(ptr, &value);                                         \
0065     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);                                    \
0066     if (extension.is_repeated) {                                            \
0067       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
0068                          extension.is_packed, value, extension.descriptor); \
0069     } else {                                                                \
0070       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
0071                          extension.descriptor);                             \
0072     }                                                                       \
0073   } break
0074 
0075       HANDLE_VARINT_TYPE(INT32, Int32);
0076       HANDLE_VARINT_TYPE(INT64, Int64);
0077       HANDLE_VARINT_TYPE(UINT32, UInt32);
0078       HANDLE_VARINT_TYPE(UINT64, UInt64);
0079       HANDLE_VARINT_TYPE(BOOL, Bool);
0080 #undef HANDLE_VARINT_TYPE
0081 #define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE)                 \
0082   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
0083     uint64_t val;                                                           \
0084     ptr = VarintParse(ptr, &val);                                           \
0085     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);                                    \
0086     auto value = WireFormatLite::ZigZagDecode##SIZE(val);                   \
0087     if (extension.is_repeated) {                                            \
0088       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
0089                          extension.is_packed, value, extension.descriptor); \
0090     } else {                                                                \
0091       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
0092                          extension.descriptor);                             \
0093     }                                                                       \
0094   } break
0095 
0096       HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
0097       HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
0098 #undef HANDLE_SVARINT_TYPE
0099 #define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE)                \
0100   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
0101     auto value = UnalignedLoad<CPPTYPE>(ptr);                               \
0102     ptr += sizeof(CPPTYPE);                                                 \
0103     if (extension.is_repeated) {                                            \
0104       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
0105                          extension.is_packed, value, extension.descriptor); \
0106     } else {                                                                \
0107       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
0108                          extension.descriptor);                             \
0109     }                                                                       \
0110   } break
0111 
0112       HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t);
0113       HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t);
0114       HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t);
0115       HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t);
0116       HANDLE_FIXED_TYPE(FLOAT, Float, float);
0117       HANDLE_FIXED_TYPE(DOUBLE, Double, double);
0118 #undef HANDLE_FIXED_TYPE
0119 
0120       case WireFormatLite::TYPE_ENUM: {
0121         uint64_t tmp;
0122         ptr = VarintParse(ptr, &tmp);
0123         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0124         int value = tmp;
0125 
0126         if (!extension.enum_validity_check.func(
0127                 extension.enum_validity_check.arg, value)) {
0128           WriteVarint(number, value, metadata->mutable_unknown_fields<T>());
0129         } else if (extension.is_repeated) {
0130           AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
0131                   extension.descriptor);
0132         } else {
0133           SetEnum(number, WireFormatLite::TYPE_ENUM, value,
0134                   extension.descriptor);
0135         }
0136         break;
0137       }
0138 
0139       case WireFormatLite::TYPE_BYTES:
0140       case WireFormatLite::TYPE_STRING: {
0141         std::string* value =
0142             extension.is_repeated
0143                 ? AddString(number, WireFormatLite::TYPE_STRING,
0144                             extension.descriptor)
0145                 : MutableString(number, WireFormatLite::TYPE_STRING,
0146                                 extension.descriptor);
0147         int size = ReadSize(&ptr);
0148         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0149         return ctx->ReadString(ptr, size, value);
0150       }
0151 
0152       case WireFormatLite::TYPE_GROUP: {
0153         MessageLite* value =
0154             extension.is_repeated
0155                 ? AddMessage(number, WireFormatLite::TYPE_GROUP,
0156                              *extension.message_info.prototype,
0157                              extension.descriptor)
0158                 : MutableMessage(number, WireFormatLite::TYPE_GROUP,
0159                                  *extension.message_info.prototype,
0160                                  extension.descriptor);
0161         uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
0162         return ctx->ParseGroup(value, ptr, tag);
0163       }
0164 
0165       case WireFormatLite::TYPE_MESSAGE: {
0166         MessageLite* value =
0167             extension.is_repeated
0168                 ? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
0169                              *extension.message_info.prototype,
0170                              extension.descriptor)
0171                 : MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
0172                                  *extension.message_info.prototype,
0173                                  extension.descriptor);
0174         return ctx->ParseMessage(value, ptr);
0175       }
0176     }
0177   }
0178   return ptr;
0179 }
0180 
0181 template <typename Msg, typename T>
0182 const char* ExtensionSet::ParseMessageSetItemTmpl(
0183     const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata,
0184     internal::ParseContext* ctx) {
0185   std::string payload;
0186   uint32_t type_id = 0;
0187   enum class State { kNoTag, kHasType, kHasPayload, kDone };
0188   State state = State::kNoTag;
0189 
0190   while (!ctx->Done(&ptr)) {
0191     uint32_t tag = static_cast<uint8_t>(*ptr++);
0192     if (tag == WireFormatLite::kMessageSetTypeIdTag) {
0193       uint64_t tmp;
0194       ptr = ParseBigVarint(ptr, &tmp);
0195       // We should fail parsing if type id is 0 after cast to uint32.
0196       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr &&
0197                                      static_cast<uint32_t>(tmp) != 0);
0198       if (state == State::kNoTag) {
0199         type_id = static_cast<uint32_t>(tmp);
0200         state = State::kHasType;
0201       } else if (state == State::kHasPayload) {
0202         type_id = static_cast<uint32_t>(tmp);
0203         ExtensionInfo extension;
0204         bool was_packed_on_wire;
0205         if (!FindExtension(2, type_id, extendee, ctx, &extension,
0206                            &was_packed_on_wire)) {
0207           WriteLengthDelimited(type_id, payload,
0208                                metadata->mutable_unknown_fields<T>());
0209         } else {
0210           MessageLite* value =
0211               extension.is_repeated
0212                   ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
0213                                *extension.message_info.prototype,
0214                                extension.descriptor)
0215                   : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
0216                                    *extension.message_info.prototype,
0217                                    extension.descriptor);
0218 
0219           const char* p;
0220           // We can't use regular parse from string as we have to track
0221           // proper recursion depth and descriptor pools. Spawn a new
0222           // ParseContext inheriting those attributes.
0223           ParseContext tmp_ctx(ParseContext::kSpawn, *ctx, &p, payload);
0224           GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
0225                                          tmp_ctx.EndedAtLimit());
0226         }
0227         state = State::kDone;
0228       }
0229     } else if (tag == WireFormatLite::kMessageSetMessageTag) {
0230       if (state == State::kHasType) {
0231         ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr,
0232                                     extendee, metadata, ctx);
0233         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
0234         state = State::kDone;
0235       } else {
0236         std::string tmp;
0237         int32_t size = ReadSize(&ptr);
0238         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0239         ptr = ctx->ReadString(ptr, size, &tmp);
0240         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0241         if (state == State::kNoTag) {
0242           payload = std::move(tmp);
0243           state = State::kHasPayload;
0244         }
0245       }
0246     } else {
0247       ptr = ReadTag(ptr - 1, &tag);
0248       if (tag == 0 || (tag & 7) == 4) {
0249         ctx->SetLastTag(tag);
0250         return ptr;
0251       }
0252       ptr = ParseField(tag, ptr, extendee, metadata, ctx);
0253       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
0254     }
0255   }
0256   return ptr;
0257 }
0258 
0259 }  // namespace internal
0260 }  // namespace protobuf
0261 }  // namespace google
0262 
0263 #endif  // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__