• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
32 #define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
33 
34 #include <google/protobuf/parse_context.h>
35 #include <google/protobuf/extension_set.h>
36 
37 namespace google {
38 namespace protobuf {
39 namespace internal {
40 
41 #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
42 template <typename T>
ParseFieldWithExtensionInfo(int number,bool was_packed_on_wire,const ExtensionInfo & extension,T * metadata,const char * ptr,internal::ParseContext * ctx)43 const char* ExtensionSet::ParseFieldWithExtensionInfo(
44     int number, bool was_packed_on_wire, const ExtensionInfo& extension,
45     T* metadata, const char* ptr, internal::ParseContext* ctx) {
46   if (was_packed_on_wire) {
47     switch (extension.type) {
48 #define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE)                                \
49   case WireFormatLite::TYPE_##UPPERCASE:                                     \
50     return internal::Packed##CPP_CAMELCASE##Parser(                          \
51         MutableRawRepeatedField(number, extension.type, extension.is_packed, \
52                                 extension.descriptor),                       \
53         ptr, ctx);
54       HANDLE_TYPE(INT32, Int32);
55       HANDLE_TYPE(INT64, Int64);
56       HANDLE_TYPE(UINT32, UInt32);
57       HANDLE_TYPE(UINT64, UInt64);
58       HANDLE_TYPE(SINT32, SInt32);
59       HANDLE_TYPE(SINT64, SInt64);
60       HANDLE_TYPE(FIXED32, Fixed32);
61       HANDLE_TYPE(FIXED64, Fixed64);
62       HANDLE_TYPE(SFIXED32, SFixed32);
63       HANDLE_TYPE(SFIXED64, SFixed64);
64       HANDLE_TYPE(FLOAT, Float);
65       HANDLE_TYPE(DOUBLE, Double);
66       HANDLE_TYPE(BOOL, Bool);
67 #undef HANDLE_TYPE
68 
69       case WireFormatLite::TYPE_ENUM:
70         return internal::PackedEnumParserArg(
71             MutableRawRepeatedField(number, extension.type, extension.is_packed,
72                                     extension.descriptor),
73             ptr, ctx, extension.enum_validity_check.func,
74             extension.enum_validity_check.arg, metadata, number);
75       case WireFormatLite::TYPE_STRING:
76       case WireFormatLite::TYPE_BYTES:
77       case WireFormatLite::TYPE_GROUP:
78       case WireFormatLite::TYPE_MESSAGE:
79         GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
80         break;
81     }
82   } else {
83     switch (extension.type) {
84 #define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE)                        \
85   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
86     uint64 value;                                                           \
87     ptr = ParseVarint64(ptr, &value);                                       \
88     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);                                    \
89     if (extension.is_repeated) {                                            \
90       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
91                          extension.is_packed, value, extension.descriptor); \
92     } else {                                                                \
93       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
94                          extension.descriptor);                             \
95     }                                                                       \
96   } break
97 
98       HANDLE_VARINT_TYPE(INT32, Int32);
99       HANDLE_VARINT_TYPE(INT64, Int64);
100       HANDLE_VARINT_TYPE(UINT32, UInt32);
101       HANDLE_VARINT_TYPE(UINT64, UInt64);
102 #undef HANDLE_VARINT_TYPE
103 #define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE)                 \
104   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
105     uint64 val;                                                             \
106     ptr = ParseVarint64(ptr, &val);                                         \
107     GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);                                    \
108     auto value = WireFormatLite::ZigZagDecode##SIZE(val);                   \
109     if (extension.is_repeated) {                                            \
110       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
111                          extension.is_packed, value, extension.descriptor); \
112     } else {                                                                \
113       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
114                          extension.descriptor);                             \
115     }                                                                       \
116   } break
117 
118       HANDLE_SVARINT_TYPE(SINT32, Int32, 32);
119       HANDLE_SVARINT_TYPE(SINT64, Int64, 64);
120 #undef HANDLE_SVARINT_TYPE
121 #define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE)                \
122   case WireFormatLite::TYPE_##UPPERCASE: {                                  \
123     CPPTYPE value;                                                          \
124     std::memcpy(&value, ptr, sizeof(CPPTYPE));                              \
125     ptr += sizeof(CPPTYPE);                                                 \
126     if (extension.is_repeated) {                                            \
127       Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE,          \
128                          extension.is_packed, value, extension.descriptor); \
129     } else {                                                                \
130       Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value,   \
131                          extension.descriptor);                             \
132     }                                                                       \
133   } break
134 
135       HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32);
136       HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64);
137       HANDLE_FIXED_TYPE(SFIXED32, Int32, int32);
138       HANDLE_FIXED_TYPE(SFIXED64, Int64, int64);
139       HANDLE_FIXED_TYPE(FLOAT, Float, float);
140       HANDLE_FIXED_TYPE(DOUBLE, Double, double);
141       HANDLE_FIXED_TYPE(BOOL, Bool, bool);
142 #undef HANDLE_FIXED_TYPE
143 
144       case WireFormatLite::TYPE_ENUM: {
145         uint64 val;
146         ptr = ParseVarint64(ptr, &val);
147         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
148         int value = val;
149 
150         if (!extension.enum_validity_check.func(
151                 extension.enum_validity_check.arg, value)) {
152           WriteVarint(number, val, metadata->mutable_unknown_fields());
153         } else if (extension.is_repeated) {
154           AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value,
155                   extension.descriptor);
156         } else {
157           SetEnum(number, WireFormatLite::TYPE_ENUM, value,
158                   extension.descriptor);
159         }
160         break;
161       }
162 
163       case WireFormatLite::TYPE_BYTES:
164       case WireFormatLite::TYPE_STRING: {
165         std::string* value =
166             extension.is_repeated
167                 ? AddString(number, WireFormatLite::TYPE_STRING,
168                             extension.descriptor)
169                 : MutableString(number, WireFormatLite::TYPE_STRING,
170                                 extension.descriptor);
171         int size = ReadSize(&ptr);
172         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
173         return ctx->ReadString(ptr, size, value);
174       }
175 
176       case WireFormatLite::TYPE_GROUP: {
177         MessageLite* value =
178             extension.is_repeated
179                 ? AddMessage(number, WireFormatLite::TYPE_GROUP,
180                              *extension.message_info.prototype,
181                              extension.descriptor)
182                 : MutableMessage(number, WireFormatLite::TYPE_GROUP,
183                                  *extension.message_info.prototype,
184                                  extension.descriptor);
185         uint32 tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP;
186         return ctx->ParseGroup(value, ptr, tag);
187       }
188 
189       case WireFormatLite::TYPE_MESSAGE: {
190         MessageLite* value =
191             extension.is_repeated
192                 ? AddMessage(number, WireFormatLite::TYPE_MESSAGE,
193                              *extension.message_info.prototype,
194                              extension.descriptor)
195                 : MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
196                                  *extension.message_info.prototype,
197                                  extension.descriptor);
198         return ctx->ParseMessage(value, ptr);
199       }
200     }
201   }
202   return ptr;
203 }
204 
205 template <typename Msg, typename Metadata>
ParseMessageSetItemTmpl(const char * ptr,const Msg * containing_type,Metadata * metadata,internal::ParseContext * ctx)206 const char* ExtensionSet::ParseMessageSetItemTmpl(const char* ptr,
207                                                   const Msg* containing_type,
208                                                   Metadata* metadata,
209                                                   internal::ParseContext* ctx) {
210   std::string payload;
211   uint32 type_id = 0;
212   while (!ctx->Done(&ptr)) {
213     uint32 tag = static_cast<uint8>(*ptr++);
214     if (tag == WireFormatLite::kMessageSetTypeIdTag) {
215       uint64 tmp;
216       ptr = ParseVarint64Inline(ptr, &tmp);
217       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
218       type_id = tmp;
219       if (!payload.empty()) {
220         ExtensionInfo extension;
221         bool was_packed_on_wire;
222         if (!FindExtension(2, type_id, containing_type, ctx, &extension,
223                            &was_packed_on_wire)) {
224           WriteLengthDelimited(type_id, payload,
225                                metadata->mutable_unknown_fields());
226         } else {
227           MessageLite* value =
228               extension.is_repeated
229                   ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE,
230                                *extension.message_info.prototype,
231                                extension.descriptor)
232                   : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE,
233                                    *extension.message_info.prototype,
234                                    extension.descriptor);
235 
236           const char* p;
237           // We can't use regular parse from string as we have to track
238           // proper recursion depth and descriptor pools.
239           ParseContext tmp_ctx(ctx->depth(), false, &p, payload);
240           tmp_ctx.data().pool = ctx->data().pool;
241           tmp_ctx.data().factory = ctx->data().factory;
242           GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) &&
243                                          tmp_ctx.EndedAtLimit());
244         }
245         type_id = 0;
246       }
247     } else if (tag == WireFormatLite::kMessageSetMessageTag) {
248       if (type_id != 0) {
249         ptr = ParseFieldMaybeLazily(static_cast<uint64>(type_id) * 8 + 2, ptr,
250                                     containing_type, metadata, ctx);
251         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
252         type_id = 0;
253       } else {
254         int32 size = ReadSize(&ptr);
255         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
256         ptr = ctx->ReadString(ptr, size, &payload);
257         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
258       }
259     } else {
260       if (tag >= 128) {
261         // Parse remainder of tag varint
262         uint32 tmp;
263         ptr = VarintParse<4>(ptr, &tmp);
264         GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
265         tag += (tmp - 1) << 7;
266       }
267       if (tag == 0 || (tag & 7) == 4) {
268         ctx->SetLastTag(tag);
269         return ptr;
270       }
271       ptr = ParseField(tag, ptr, containing_type, metadata, ctx);
272       GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
273     }
274   }
275   return ptr;
276 }
277 #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
278 
279 }  // namespace internal
280 }  // namespace protobuf
281 }  // namespace google
282 
283 #endif  // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
284