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 | // Author: jschorr@google.com (Joseph Schorr) |
32 | // Based on original Protocol Buffers design by |
33 | // Sanjay Ghemawat, Jeff Dean, and others. |
34 | |
35 | #include <google/protobuf/text_format.h> |
36 | |
37 | #include <float.h> |
38 | #include <stdio.h> |
39 | |
40 | #include <algorithm> |
41 | #include <atomic> |
42 | #include <climits> |
43 | #include <cmath> |
44 | #include <limits> |
45 | #include <utility> |
46 | #include <vector> |
47 | |
48 | #include <google/protobuf/io/coded_stream.h> |
49 | #include <google/protobuf/io/tokenizer.h> |
50 | #include <google/protobuf/io/zero_copy_stream.h> |
51 | #include <google/protobuf/io/zero_copy_stream_impl.h> |
52 | #include <google/protobuf/stubs/strutil.h> |
53 | #include <google/protobuf/any.h> |
54 | #include <google/protobuf/descriptor.h> |
55 | #include <google/protobuf/descriptor.pb.h> |
56 | #include <google/protobuf/dynamic_message.h> |
57 | #include <google/protobuf/io/strtod.h> |
58 | #include <google/protobuf/map_field.h> |
59 | #include <google/protobuf/message.h> |
60 | #include <google/protobuf/repeated_field.h> |
61 | #include <google/protobuf/unknown_field_set.h> |
62 | #include <google/protobuf/wire_format_lite.h> |
63 | #include <google/protobuf/stubs/map_util.h> |
64 | #include <google/protobuf/stubs/stl_util.h> |
65 | |
66 | // Must be included last. |
67 | #include <google/protobuf/port_def.inc> |
68 | |
69 | namespace google { |
70 | namespace protobuf { |
71 | |
72 | namespace { |
73 | |
74 | inline bool IsHexNumber(const std::string& str) { |
75 | return (str.length() >= 2 && str[0] == '0' && |
76 | (str[1] == 'x' || str[1] == 'X')); |
77 | } |
78 | |
79 | inline bool IsOctNumber(const std::string& str) { |
80 | return (str.length() >= 2 && str[0] == '0' && |
81 | (str[1] >= '0' && str[1] < '8')); |
82 | } |
83 | |
84 | } // namespace |
85 | |
86 | namespace internal { |
87 | const char kDebugStringSilentMarker[] = "" ; |
88 | const char kDebugStringSilentMarkerForDetection[] = "\t " ; |
89 | |
90 | // Controls insertion of kDebugStringSilentMarker. |
91 | PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_format_marker; |
92 | } // namespace internal |
93 | |
94 | std::string Message::DebugString() const { |
95 | std::string debug_string; |
96 | |
97 | TextFormat::Printer printer; |
98 | printer.SetExpandAny(true); |
99 | printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( |
100 | m: std::memory_order_relaxed)); |
101 | |
102 | printer.PrintToString(message: *this, output: &debug_string); |
103 | |
104 | return debug_string; |
105 | } |
106 | |
107 | std::string Message::ShortDebugString() const { |
108 | std::string debug_string; |
109 | |
110 | TextFormat::Printer printer; |
111 | printer.SetSingleLineMode(true); |
112 | printer.SetExpandAny(true); |
113 | printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( |
114 | m: std::memory_order_relaxed)); |
115 | |
116 | printer.PrintToString(message: *this, output: &debug_string); |
117 | // Single line mode currently might have an extra space at the end. |
118 | if (!debug_string.empty() && debug_string[debug_string.size() - 1] == ' ') { |
119 | debug_string.resize(n: debug_string.size() - 1); |
120 | } |
121 | |
122 | return debug_string; |
123 | } |
124 | |
125 | std::string Message::Utf8DebugString() const { |
126 | std::string debug_string; |
127 | |
128 | TextFormat::Printer printer; |
129 | printer.SetUseUtf8StringEscaping(true); |
130 | printer.SetExpandAny(true); |
131 | printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( |
132 | m: std::memory_order_relaxed)); |
133 | |
134 | printer.PrintToString(message: *this, output: &debug_string); |
135 | |
136 | return debug_string; |
137 | } |
138 | |
139 | void Message::PrintDebugString() const { printf(format: "%s" , DebugString().c_str()); } |
140 | |
141 | |
142 | // =========================================================================== |
143 | // Implementation of the parse information tree class. |
144 | void TextFormat::ParseInfoTree::RecordLocation( |
145 | const FieldDescriptor* field, TextFormat::ParseLocationRange range) { |
146 | locations_[field].push_back(x: range); |
147 | } |
148 | |
149 | TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( |
150 | const FieldDescriptor* field) { |
151 | // Owned by us in the map. |
152 | auto& vec = nested_[field]; |
153 | vec.emplace_back(args: new TextFormat::ParseInfoTree()); |
154 | return vec.back().get(); |
155 | } |
156 | |
157 | void CheckFieldIndex(const FieldDescriptor* field, int index) { |
158 | if (field == nullptr) { |
159 | return; |
160 | } |
161 | |
162 | if (field->is_repeated() && index == -1) { |
163 | GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " |
164 | << "Field: " << field->name(); |
165 | } else if (!field->is_repeated() && index != -1) { |
166 | GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields." |
167 | << "Field: " << field->name(); |
168 | } |
169 | } |
170 | |
171 | TextFormat::ParseLocationRange TextFormat::ParseInfoTree::GetLocationRange( |
172 | const FieldDescriptor* field, int index) const { |
173 | CheckFieldIndex(field, index); |
174 | if (index == -1) { |
175 | index = 0; |
176 | } |
177 | |
178 | const std::vector<TextFormat::ParseLocationRange>* locations = |
179 | FindOrNull(collection: locations_, key: field); |
180 | if (locations == nullptr || |
181 | index >= static_cast<int64_t>(locations->size())) { |
182 | return TextFormat::ParseLocationRange(); |
183 | } |
184 | |
185 | return (*locations)[index]; |
186 | } |
187 | |
188 | TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( |
189 | const FieldDescriptor* field, int index) const { |
190 | CheckFieldIndex(field, index); |
191 | if (index == -1) { |
192 | index = 0; |
193 | } |
194 | |
195 | auto it = nested_.find(x: field); |
196 | if (it == nested_.end() || index >= static_cast<int64_t>(it->second.size())) { |
197 | return nullptr; |
198 | } |
199 | |
200 | return it->second[index].get(); |
201 | } |
202 | |
203 | namespace { |
204 | // These functions implement the behavior of the "default" TextFormat::Finder, |
205 | // they are defined as standalone to be called when finder_ is nullptr. |
206 | const FieldDescriptor* DefaultFinderFindExtension(Message* message, |
207 | const std::string& name) { |
208 | const Descriptor* descriptor = message->GetDescriptor(); |
209 | return descriptor->file()->pool()->FindExtensionByPrintableName(extendee: descriptor, |
210 | printable_name: name); |
211 | } |
212 | |
213 | const FieldDescriptor* DefaultFinderFindExtensionByNumber( |
214 | const Descriptor* descriptor, int number) { |
215 | return descriptor->file()->pool()->FindExtensionByNumber(extendee: descriptor, number); |
216 | } |
217 | |
218 | const Descriptor* DefaultFinderFindAnyType(const Message& message, |
219 | const std::string& prefix, |
220 | const std::string& name) { |
221 | if (prefix != internal::kTypeGoogleApisComPrefix && |
222 | prefix != internal::kTypeGoogleProdComPrefix) { |
223 | return nullptr; |
224 | } |
225 | return message.GetDescriptor()->file()->pool()->FindMessageTypeByName(name); |
226 | } |
227 | } // namespace |
228 | |
229 | // =========================================================================== |
230 | // Internal class for parsing an ASCII representation of a Protocol Message. |
231 | // This class makes use of the Protocol Message compiler's tokenizer found |
232 | // in //net/proto2/io/public/tokenizer.h. Note that class's Parse |
233 | // method is *not* thread-safe and should only be used in a single thread at |
234 | // a time. |
235 | |
236 | // Makes code slightly more readable. The meaning of "DO(foo)" is |
237 | // "Execute foo and fail if it fails.", where failure is indicated by |
238 | // returning false. Borrowed from parser.cc (Thanks Kenton!). |
239 | #define DO(STATEMENT) \ |
240 | if (STATEMENT) { \ |
241 | } else { \ |
242 | return false; \ |
243 | } |
244 | |
245 | class TextFormat::Parser::ParserImpl { |
246 | public: |
247 | // Determines if repeated values for non-repeated fields and |
248 | // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a |
249 | // required/optional field named "foo", or "baz: 1 bar: 2" |
250 | // where "baz" and "bar" are members of the same oneof. |
251 | enum SingularOverwritePolicy { |
252 | ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained |
253 | FORBID_SINGULAR_OVERWRITES = 1, // an error is issued |
254 | }; |
255 | |
256 | ParserImpl(const Descriptor* root_message_type, |
257 | io::ZeroCopyInputStream* input_stream, |
258 | io::ErrorCollector* error_collector, |
259 | const TextFormat::Finder* finder, ParseInfoTree* parse_info_tree, |
260 | SingularOverwritePolicy singular_overwrite_policy, |
261 | bool allow_case_insensitive_field, bool allow_unknown_field, |
262 | bool allow_unknown_extension, bool allow_unknown_enum, |
263 | bool allow_field_number, bool allow_relaxed_whitespace, |
264 | bool allow_partial, int recursion_limit) |
265 | : error_collector_(error_collector), |
266 | finder_(finder), |
267 | parse_info_tree_(parse_info_tree), |
268 | tokenizer_error_collector_(this), |
269 | tokenizer_(input_stream, &tokenizer_error_collector_), |
270 | root_message_type_(root_message_type), |
271 | singular_overwrite_policy_(singular_overwrite_policy), |
272 | allow_case_insensitive_field_(allow_case_insensitive_field), |
273 | allow_unknown_field_(allow_unknown_field), |
274 | allow_unknown_extension_(allow_unknown_extension), |
275 | allow_unknown_enum_(allow_unknown_enum), |
276 | allow_field_number_(allow_field_number), |
277 | allow_partial_(allow_partial), |
278 | initial_recursion_limit_(recursion_limit), |
279 | recursion_limit_(recursion_limit), |
280 | had_silent_marker_(false), |
281 | had_errors_(false) { |
282 | // For backwards-compatibility with proto1, we need to allow the 'f' suffix |
283 | // for floats. |
284 | tokenizer_.set_allow_f_after_float(true); |
285 | |
286 | // '#' starts a comment. |
287 | tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); |
288 | |
289 | if (allow_relaxed_whitespace) { |
290 | tokenizer_.set_require_space_after_number(false); |
291 | tokenizer_.set_allow_multiline_strings(true); |
292 | } |
293 | |
294 | // Consume the starting token. |
295 | tokenizer_.Next(); |
296 | } |
297 | ~ParserImpl() {} |
298 | |
299 | // Parses the ASCII representation specified in input and saves the |
300 | // information into the output pointer (a Message). Returns |
301 | // false if an error occurs (an error will also be logged to |
302 | // GOOGLE_LOG(ERROR)). |
303 | bool Parse(Message* output) { |
304 | // Consume fields until we cannot do so anymore. |
305 | while (true) { |
306 | if (LookingAtType(token_type: io::Tokenizer::TYPE_END)) { |
307 | // Ensures recursion limit properly unwinded, but only for success |
308 | // cases. This implicitly avoids the check when `Parse` returns false |
309 | // via `DO(...)`. |
310 | GOOGLE_DCHECK(had_errors_ || recursion_limit_ == initial_recursion_limit_) |
311 | << "Recursion limit at end of parse should be " |
312 | << initial_recursion_limit_ << ", but was " << recursion_limit_ |
313 | << ". Difference of " << initial_recursion_limit_ - recursion_limit_ |
314 | << " stack frames not accounted for stack unwind." ; |
315 | |
316 | return !had_errors_; |
317 | } |
318 | |
319 | DO(ConsumeField(output)); |
320 | } |
321 | } |
322 | |
323 | bool ParseField(const FieldDescriptor* field, Message* output) { |
324 | bool suc; |
325 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
326 | suc = ConsumeFieldMessage(message: output, reflection: output->GetReflection(), field); |
327 | } else { |
328 | suc = ConsumeFieldValue(message: output, reflection: output->GetReflection(), field); |
329 | } |
330 | return suc && LookingAtType(token_type: io::Tokenizer::TYPE_END); |
331 | } |
332 | |
333 | void ReportError(int line, int col, const std::string& message) { |
334 | had_errors_ = true; |
335 | if (error_collector_ == nullptr) { |
336 | if (line >= 0) { |
337 | GOOGLE_LOG(ERROR) << "Error parsing text-format " |
338 | << root_message_type_->full_name() << ": " << (line + 1) |
339 | << ":" << (col + 1) << ": " << message; |
340 | } else { |
341 | GOOGLE_LOG(ERROR) << "Error parsing text-format " |
342 | << root_message_type_->full_name() << ": " << message; |
343 | } |
344 | } else { |
345 | error_collector_->AddError(line, column: col, message); |
346 | } |
347 | } |
348 | |
349 | void ReportWarning(int line, int col, const std::string& message) { |
350 | if (error_collector_ == nullptr) { |
351 | if (line >= 0) { |
352 | GOOGLE_LOG(WARNING) << "Warning parsing text-format " |
353 | << root_message_type_->full_name() << ": " << (line + 1) |
354 | << ":" << (col + 1) << ": " << message; |
355 | } else { |
356 | GOOGLE_LOG(WARNING) << "Warning parsing text-format " |
357 | << root_message_type_->full_name() << ": " << message; |
358 | } |
359 | } else { |
360 | error_collector_->AddWarning(line, col, message); |
361 | } |
362 | } |
363 | |
364 | private: |
365 | static constexpr int32_t kint32max = std::numeric_limits<int32_t>::max(); |
366 | static constexpr uint32_t kuint32max = std::numeric_limits<uint32_t>::max(); |
367 | static constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); |
368 | static constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); |
369 | static constexpr uint64_t kuint64max = std::numeric_limits<uint64_t>::max(); |
370 | |
371 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl); |
372 | |
373 | // Reports an error with the given message with information indicating |
374 | // the position (as derived from the current token). |
375 | void ReportError(const std::string& message) { |
376 | ReportError(line: tokenizer_.current().line, col: tokenizer_.current().column, |
377 | message); |
378 | } |
379 | |
380 | // Reports a warning with the given message with information indicating |
381 | // the position (as derived from the current token). |
382 | void ReportWarning(const std::string& message) { |
383 | ReportWarning(line: tokenizer_.current().line, col: tokenizer_.current().column, |
384 | message); |
385 | } |
386 | |
387 | // Consumes the specified message with the given starting delimiter. |
388 | // This method checks to see that the end delimiter at the conclusion of |
389 | // the consumption matches the starting delimiter passed in here. |
390 | bool ConsumeMessage(Message* message, const std::string delimiter) { |
391 | while (!LookingAt(text: ">" ) && !LookingAt(text: "}" )) { |
392 | DO(ConsumeField(message)); |
393 | } |
394 | |
395 | // Confirm that we have a valid ending delimiter. |
396 | DO(Consume(delimiter)); |
397 | return true; |
398 | } |
399 | |
400 | // Consume either "<" or "{". |
401 | bool ConsumeMessageDelimiter(std::string* delimiter) { |
402 | if (TryConsume(value: "<" )) { |
403 | *delimiter = ">" ; |
404 | } else { |
405 | DO(Consume("{" )); |
406 | *delimiter = "}" ; |
407 | } |
408 | return true; |
409 | } |
410 | |
411 | |
412 | // Consumes the current field (as returned by the tokenizer) on the |
413 | // passed in message. |
414 | bool ConsumeField(Message* message) { |
415 | const Reflection* reflection = message->GetReflection(); |
416 | const Descriptor* descriptor = message->GetDescriptor(); |
417 | |
418 | std::string field_name; |
419 | bool reserved_field = false; |
420 | const FieldDescriptor* field = nullptr; |
421 | int start_line = tokenizer_.current().line; |
422 | int start_column = tokenizer_.current().column; |
423 | |
424 | const FieldDescriptor* any_type_url_field; |
425 | const FieldDescriptor* any_value_field; |
426 | if (internal::GetAnyFieldDescriptors(message: *message, type_url_field: &any_type_url_field, |
427 | value_field: &any_value_field) && |
428 | TryConsume(value: "[" )) { |
429 | std::string full_type_name, prefix; |
430 | DO(ConsumeAnyTypeUrl(&full_type_name, &prefix)); |
431 | std::string prefix_and_full_type_name = |
432 | StrCat(a: prefix, b: full_type_name); |
433 | DO(ConsumeBeforeWhitespace("]" )); |
434 | TryConsumeWhitespace(); |
435 | // ':' is optional between message labels and values. |
436 | if (TryConsumeBeforeWhitespace(value: ":" )) { |
437 | TryConsumeWhitespace(); |
438 | } |
439 | std::string serialized_value; |
440 | const Descriptor* value_descriptor = |
441 | finder_ ? finder_->FindAnyType(message: *message, prefix, name: full_type_name) |
442 | : DefaultFinderFindAnyType(message: *message, prefix, name: full_type_name); |
443 | if (value_descriptor == nullptr) { |
444 | ReportError(message: "Could not find type \"" + prefix_and_full_type_name + |
445 | "\" stored in google.protobuf.Any." ); |
446 | return false; |
447 | } |
448 | DO(ConsumeAnyValue(value_descriptor, &serialized_value)); |
449 | if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { |
450 | // Fail if any_type_url_field has already been specified. |
451 | if ((!any_type_url_field->is_repeated() && |
452 | reflection->HasField(message: *message, field: any_type_url_field)) || |
453 | (!any_value_field->is_repeated() && |
454 | reflection->HasField(message: *message, field: any_value_field))) { |
455 | ReportError(message: "Non-repeated Any specified multiple times." ); |
456 | return false; |
457 | } |
458 | } |
459 | reflection->SetString(message, field: any_type_url_field, |
460 | value: std::move(prefix_and_full_type_name)); |
461 | reflection->SetString(message, field: any_value_field, |
462 | value: std::move(serialized_value)); |
463 | return true; |
464 | } |
465 | if (TryConsume(value: "[" )) { |
466 | // Extension. |
467 | DO(ConsumeFullTypeName(&field_name)); |
468 | DO(ConsumeBeforeWhitespace("]" )); |
469 | TryConsumeWhitespace(); |
470 | |
471 | field = finder_ ? finder_->FindExtension(message, name: field_name) |
472 | : DefaultFinderFindExtension(message, name: field_name); |
473 | |
474 | if (field == nullptr) { |
475 | if (!allow_unknown_field_ && !allow_unknown_extension_) { |
476 | ReportError(message: "Extension \"" + field_name + |
477 | "\" is not defined or " |
478 | "is not an extension of \"" + |
479 | descriptor->full_name() + "\"." ); |
480 | return false; |
481 | } else { |
482 | ReportWarning(message: "Ignoring extension \"" + field_name + |
483 | "\" which is not defined or is not an extension of \"" + |
484 | descriptor->full_name() + "\"." ); |
485 | } |
486 | } |
487 | } else { |
488 | DO(ConsumeIdentifierBeforeWhitespace(&field_name)); |
489 | TryConsumeWhitespace(); |
490 | |
491 | int32_t field_number; |
492 | if (allow_field_number_ && safe_strto32(str: field_name, value: &field_number)) { |
493 | if (descriptor->IsExtensionNumber(number: field_number)) { |
494 | field = finder_ |
495 | ? finder_->FindExtensionByNumber(descriptor, number: field_number) |
496 | : DefaultFinderFindExtensionByNumber(descriptor, |
497 | number: field_number); |
498 | } else if (descriptor->IsReservedNumber(number: field_number)) { |
499 | reserved_field = true; |
500 | } else { |
501 | field = descriptor->FindFieldByNumber(number: field_number); |
502 | } |
503 | } else { |
504 | field = descriptor->FindFieldByName(name: field_name); |
505 | // Group names are expected to be capitalized as they appear in the |
506 | // .proto file, which actually matches their type names, not their |
507 | // field names. |
508 | if (field == nullptr) { |
509 | std::string lower_field_name = field_name; |
510 | LowerString(s: &lower_field_name); |
511 | field = descriptor->FindFieldByName(name: lower_field_name); |
512 | // If the case-insensitive match worked but the field is NOT a group, |
513 | if (field != nullptr && |
514 | field->type() != FieldDescriptor::TYPE_GROUP) { |
515 | field = nullptr; |
516 | } |
517 | } |
518 | // Again, special-case group names as described above. |
519 | if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP && |
520 | field->message_type()->name() != field_name) { |
521 | field = nullptr; |
522 | } |
523 | |
524 | if (field == nullptr && allow_case_insensitive_field_) { |
525 | std::string lower_field_name = field_name; |
526 | LowerString(s: &lower_field_name); |
527 | field = descriptor->FindFieldByLowercaseName(lowercase_name: lower_field_name); |
528 | } |
529 | |
530 | if (field == nullptr) { |
531 | reserved_field = descriptor->IsReservedName(name: field_name); |
532 | } |
533 | } |
534 | |
535 | if (field == nullptr && !reserved_field) { |
536 | if (!allow_unknown_field_) { |
537 | ReportError(message: "Message type \"" + descriptor->full_name() + |
538 | "\" has no field named \"" + field_name + "\"." ); |
539 | return false; |
540 | } else { |
541 | ReportWarning(message: "Message type \"" + descriptor->full_name() + |
542 | "\" has no field named \"" + field_name + "\"." ); |
543 | } |
544 | } |
545 | } |
546 | |
547 | // Skips unknown or reserved fields. |
548 | if (field == nullptr) { |
549 | GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field); |
550 | |
551 | // Try to guess the type of this field. |
552 | // If this field is not a message, there should be a ":" between the |
553 | // field name and the field value and also the field value should not |
554 | // start with "{" or "<" which indicates the beginning of a message body. |
555 | // If there is no ":" or there is a "{" or "<" after ":", this field has |
556 | // to be a message or the input is ill-formed. |
557 | if (TryConsumeBeforeWhitespace(value: ":" )) { |
558 | TryConsumeWhitespace(); |
559 | if (!LookingAt(text: "{" ) && !LookingAt(text: "<" )) { |
560 | return SkipFieldValue(); |
561 | } |
562 | } |
563 | return SkipFieldMessage(); |
564 | } |
565 | |
566 | if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { |
567 | // Fail if the field is not repeated and it has already been specified. |
568 | if (!field->is_repeated() && reflection->HasField(message: *message, field)) { |
569 | ReportError(message: "Non-repeated field \"" + field_name + |
570 | "\" is specified multiple times." ); |
571 | return false; |
572 | } |
573 | // Fail if the field is a member of a oneof and another member has already |
574 | // been specified. |
575 | const OneofDescriptor* oneof = field->containing_oneof(); |
576 | if (oneof != nullptr && reflection->HasOneof(message: *message, oneof_descriptor: oneof)) { |
577 | const FieldDescriptor* other_field = |
578 | reflection->GetOneofFieldDescriptor(message: *message, oneof_descriptor: oneof); |
579 | ReportError(message: "Field \"" + field_name + |
580 | "\" is specified along with " |
581 | "field \"" + |
582 | other_field->name() + |
583 | "\", another member " |
584 | "of oneof \"" + |
585 | oneof->name() + "\"." ); |
586 | return false; |
587 | } |
588 | } |
589 | |
590 | // Perform special handling for embedded message types. |
591 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
592 | // ':' is optional here. |
593 | bool consumed_semicolon = TryConsumeBeforeWhitespace(value: ":" ); |
594 | if (consumed_semicolon) { |
595 | TryConsumeWhitespace(); |
596 | } |
597 | if (consumed_semicolon && field->options().weak() && |
598 | LookingAtType(token_type: io::Tokenizer::TYPE_STRING)) { |
599 | // we are getting a bytes string for a weak field. |
600 | std::string tmp; |
601 | DO(ConsumeString(&tmp)); |
602 | MessageFactory* factory = |
603 | finder_ ? finder_->FindExtensionFactory(field) : nullptr; |
604 | reflection->MutableMessage(message, field, factory) |
605 | ->ParseFromString(data: tmp); |
606 | goto label_skip_parsing; |
607 | } |
608 | } else { |
609 | // ':' is required here. |
610 | DO(ConsumeBeforeWhitespace(":" )); |
611 | TryConsumeWhitespace(); |
612 | } |
613 | |
614 | if (field->is_repeated() && TryConsume(value: "[" )) { |
615 | // Short repeated format, e.g. "foo: [1, 2, 3]". |
616 | if (!TryConsume(value: "]" )) { |
617 | // "foo: []" is treated as empty. |
618 | while (true) { |
619 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
620 | // Perform special handling for embedded message types. |
621 | DO(ConsumeFieldMessage(message, reflection, field)); |
622 | } else { |
623 | DO(ConsumeFieldValue(message, reflection, field)); |
624 | } |
625 | if (TryConsume(value: "]" )) { |
626 | break; |
627 | } |
628 | DO(Consume("," )); |
629 | } |
630 | } |
631 | } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
632 | DO(ConsumeFieldMessage(message, reflection, field)); |
633 | } else { |
634 | DO(ConsumeFieldValue(message, reflection, field)); |
635 | } |
636 | label_skip_parsing: |
637 | // For historical reasons, fields may optionally be separated by commas or |
638 | // semicolons. |
639 | TryConsume(value: ";" ) || TryConsume(value: "," ); |
640 | |
641 | if (field->options().deprecated()) { |
642 | ReportWarning(message: "text format contains deprecated field \"" + field_name + |
643 | "\"" ); |
644 | } |
645 | |
646 | // If a parse info tree exists, add the location for the parsed |
647 | // field. |
648 | if (parse_info_tree_ != nullptr) { |
649 | int end_line = tokenizer_.previous().line; |
650 | int end_column = tokenizer_.previous().end_column; |
651 | |
652 | RecordLocation(info_tree: parse_info_tree_, field, |
653 | location: ParseLocationRange(ParseLocation(start_line, start_column), |
654 | ParseLocation(end_line, end_column))); |
655 | } |
656 | |
657 | return true; |
658 | } |
659 | |
660 | // Skips the next field including the field's name and value. |
661 | bool SkipField() { |
662 | std::string field_name; |
663 | if (TryConsume(value: "[" )) { |
664 | // Extension name or type URL. |
665 | DO(ConsumeTypeUrlOrFullTypeName(&field_name)); |
666 | DO(ConsumeBeforeWhitespace("]" )); |
667 | } else { |
668 | DO(ConsumeIdentifierBeforeWhitespace(&field_name)); |
669 | } |
670 | TryConsumeWhitespace(); |
671 | |
672 | // Try to guess the type of this field. |
673 | // If this field is not a message, there should be a ":" between the |
674 | // field name and the field value and also the field value should not |
675 | // start with "{" or "<" which indicates the beginning of a message body. |
676 | // If there is no ":" or there is a "{" or "<" after ":", this field has |
677 | // to be a message or the input is ill-formed. |
678 | if (TryConsumeBeforeWhitespace(value: ":" )) { |
679 | TryConsumeWhitespace(); |
680 | if (!LookingAt(text: "{" ) && !LookingAt(text: "<" )) { |
681 | DO(SkipFieldValue()); |
682 | } else { |
683 | DO(SkipFieldMessage()); |
684 | } |
685 | } else { |
686 | DO(SkipFieldMessage()); |
687 | } |
688 | // For historical reasons, fields may optionally be separated by commas or |
689 | // semicolons. |
690 | TryConsume(value: ";" ) || TryConsume(value: "," ); |
691 | return true; |
692 | } |
693 | |
694 | bool ConsumeFieldMessage(Message* message, const Reflection* reflection, |
695 | const FieldDescriptor* field) { |
696 | if (--recursion_limit_ < 0) { |
697 | ReportError( |
698 | message: StrCat(a: "Message is too deep, the parser exceeded the " |
699 | "configured recursion limit of " , |
700 | b: initial_recursion_limit_, c: "." )); |
701 | return false; |
702 | } |
703 | // If the parse information tree is not nullptr, create a nested one |
704 | // for the nested message. |
705 | ParseInfoTree* parent = parse_info_tree_; |
706 | if (parent != nullptr) { |
707 | parse_info_tree_ = CreateNested(info_tree: parent, field); |
708 | } |
709 | |
710 | std::string delimiter; |
711 | DO(ConsumeMessageDelimiter(&delimiter)); |
712 | MessageFactory* factory = |
713 | finder_ ? finder_->FindExtensionFactory(field) : nullptr; |
714 | if (field->is_repeated()) { |
715 | DO(ConsumeMessage(reflection->AddMessage(message, field, factory), |
716 | delimiter)); |
717 | } else { |
718 | DO(ConsumeMessage(reflection->MutableMessage(message, field, factory), |
719 | delimiter)); |
720 | } |
721 | |
722 | ++recursion_limit_; |
723 | |
724 | // Reset the parse information tree. |
725 | parse_info_tree_ = parent; |
726 | return true; |
727 | } |
728 | |
729 | // Skips the whole body of a message including the beginning delimiter and |
730 | // the ending delimiter. |
731 | bool SkipFieldMessage() { |
732 | if (--recursion_limit_ < 0) { |
733 | ReportError( |
734 | message: StrCat(a: "Message is too deep, the parser exceeded the " |
735 | "configured recursion limit of " , |
736 | b: initial_recursion_limit_, c: "." )); |
737 | return false; |
738 | } |
739 | |
740 | std::string delimiter; |
741 | DO(ConsumeMessageDelimiter(&delimiter)); |
742 | while (!LookingAt(text: ">" ) && !LookingAt(text: "}" )) { |
743 | DO(SkipField()); |
744 | } |
745 | DO(Consume(delimiter)); |
746 | |
747 | ++recursion_limit_; |
748 | return true; |
749 | } |
750 | |
751 | bool ConsumeFieldValue(Message* message, const Reflection* reflection, |
752 | const FieldDescriptor* field) { |
753 | // Define an easy to use macro for setting fields. This macro checks |
754 | // to see if the field is repeated (in which case we need to use the Add |
755 | // methods or not (in which case we need to use the Set methods). |
756 | #define SET_FIELD(CPPTYPE, VALUE) \ |
757 | if (field->is_repeated()) { \ |
758 | reflection->Add##CPPTYPE(message, field, VALUE); \ |
759 | } else { \ |
760 | reflection->Set##CPPTYPE(message, field, VALUE); \ |
761 | } |
762 | |
763 | switch (field->cpp_type()) { |
764 | case FieldDescriptor::CPPTYPE_INT32: { |
765 | int64_t value; |
766 | DO(ConsumeSignedInteger(&value, kint32max)); |
767 | SET_FIELD(Int32, static_cast<int32_t>(value)); |
768 | break; |
769 | } |
770 | |
771 | case FieldDescriptor::CPPTYPE_UINT32: { |
772 | uint64_t value; |
773 | DO(ConsumeUnsignedInteger(&value, kuint32max)); |
774 | SET_FIELD(UInt32, static_cast<uint32_t>(value)); |
775 | break; |
776 | } |
777 | |
778 | case FieldDescriptor::CPPTYPE_INT64: { |
779 | int64_t value; |
780 | DO(ConsumeSignedInteger(&value, kint64max)); |
781 | SET_FIELD(Int64, value); |
782 | break; |
783 | } |
784 | |
785 | case FieldDescriptor::CPPTYPE_UINT64: { |
786 | uint64_t value; |
787 | DO(ConsumeUnsignedInteger(&value, kuint64max)); |
788 | SET_FIELD(UInt64, value); |
789 | break; |
790 | } |
791 | |
792 | case FieldDescriptor::CPPTYPE_FLOAT: { |
793 | double value; |
794 | DO(ConsumeDouble(&value)); |
795 | SET_FIELD(Float, io::SafeDoubleToFloat(value)); |
796 | break; |
797 | } |
798 | |
799 | case FieldDescriptor::CPPTYPE_DOUBLE: { |
800 | double value; |
801 | DO(ConsumeDouble(&value)); |
802 | SET_FIELD(Double, value); |
803 | break; |
804 | } |
805 | |
806 | case FieldDescriptor::CPPTYPE_STRING: { |
807 | std::string value; |
808 | DO(ConsumeString(&value)); |
809 | SET_FIELD(String, std::move(value)); |
810 | break; |
811 | } |
812 | |
813 | case FieldDescriptor::CPPTYPE_BOOL: { |
814 | if (LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
815 | uint64_t value; |
816 | DO(ConsumeUnsignedInteger(&value, 1)); |
817 | SET_FIELD(Bool, value); |
818 | } else { |
819 | std::string value; |
820 | DO(ConsumeIdentifier(&value)); |
821 | if (value == "true" || value == "True" || value == "t" ) { |
822 | SET_FIELD(Bool, true); |
823 | } else if (value == "false" || value == "False" || value == "f" ) { |
824 | SET_FIELD(Bool, false); |
825 | } else { |
826 | ReportError(message: "Invalid value for boolean field \"" + field->name() + |
827 | "\". Value: \"" + value + "\"." ); |
828 | return false; |
829 | } |
830 | } |
831 | break; |
832 | } |
833 | |
834 | case FieldDescriptor::CPPTYPE_ENUM: { |
835 | std::string value; |
836 | int64_t int_value = kint64max; |
837 | const EnumDescriptor* enum_type = field->enum_type(); |
838 | const EnumValueDescriptor* enum_value = nullptr; |
839 | |
840 | if (LookingAtType(token_type: io::Tokenizer::TYPE_IDENTIFIER)) { |
841 | DO(ConsumeIdentifier(&value)); |
842 | // Find the enumeration value. |
843 | enum_value = enum_type->FindValueByName(name: value); |
844 | |
845 | } else if (LookingAt(text: "-" ) || |
846 | LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
847 | DO(ConsumeSignedInteger(&int_value, kint32max)); |
848 | value = StrCat(a: int_value); // for error reporting |
849 | enum_value = enum_type->FindValueByNumber(number: int_value); |
850 | } else { |
851 | ReportError(message: "Expected integer or identifier, got: " + |
852 | tokenizer_.current().text); |
853 | return false; |
854 | } |
855 | |
856 | if (enum_value == nullptr) { |
857 | if (int_value != kint64max && |
858 | reflection->SupportsUnknownEnumValues()) { |
859 | SET_FIELD(EnumValue, int_value); |
860 | return true; |
861 | } else if (!allow_unknown_enum_) { |
862 | ReportError(message: "Unknown enumeration value of \"" + value + |
863 | "\" for " |
864 | "field \"" + |
865 | field->name() + "\"." ); |
866 | return false; |
867 | } else { |
868 | ReportWarning(message: "Unknown enumeration value of \"" + value + |
869 | "\" for " |
870 | "field \"" + |
871 | field->name() + "\"." ); |
872 | return true; |
873 | } |
874 | } |
875 | |
876 | SET_FIELD(Enum, enum_value); |
877 | break; |
878 | } |
879 | |
880 | case FieldDescriptor::CPPTYPE_MESSAGE: { |
881 | // We should never get here. Put here instead of a default |
882 | // so that if new types are added, we get a nice compiler warning. |
883 | GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE" ; |
884 | break; |
885 | } |
886 | } |
887 | #undef SET_FIELD |
888 | return true; |
889 | } |
890 | |
891 | bool SkipFieldValue() { |
892 | if (--recursion_limit_ < 0) { |
893 | ReportError( |
894 | message: StrCat(a: "Message is too deep, the parser exceeded the " |
895 | "configured recursion limit of " , |
896 | b: initial_recursion_limit_, c: "." )); |
897 | return false; |
898 | } |
899 | |
900 | if (LookingAtType(token_type: io::Tokenizer::TYPE_STRING)) { |
901 | while (LookingAtType(token_type: io::Tokenizer::TYPE_STRING)) { |
902 | tokenizer_.Next(); |
903 | } |
904 | ++recursion_limit_; |
905 | return true; |
906 | } |
907 | if (TryConsume(value: "[" )) { |
908 | while (true) { |
909 | if (!LookingAt(text: "{" ) && !LookingAt(text: "<" )) { |
910 | DO(SkipFieldValue()); |
911 | } else { |
912 | DO(SkipFieldMessage()); |
913 | } |
914 | if (TryConsume(value: "]" )) { |
915 | break; |
916 | } |
917 | DO(Consume("," )); |
918 | } |
919 | ++recursion_limit_; |
920 | return true; |
921 | } |
922 | // Possible field values other than string: |
923 | // 12345 => TYPE_INTEGER |
924 | // -12345 => TYPE_SYMBOL + TYPE_INTEGER |
925 | // 1.2345 => TYPE_FLOAT |
926 | // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT |
927 | // inf => TYPE_IDENTIFIER |
928 | // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER |
929 | // TYPE_INTEGER => TYPE_IDENTIFIER |
930 | // Divides them into two group, one with TYPE_SYMBOL |
931 | // and the other without: |
932 | // Group one: |
933 | // 12345 => TYPE_INTEGER |
934 | // 1.2345 => TYPE_FLOAT |
935 | // inf => TYPE_IDENTIFIER |
936 | // TYPE_INTEGER => TYPE_IDENTIFIER |
937 | // Group two: |
938 | // -12345 => TYPE_SYMBOL + TYPE_INTEGER |
939 | // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT |
940 | // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER |
941 | // As we can see, the field value consists of an optional '-' and one of |
942 | // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER. |
943 | bool has_minus = TryConsume(value: "-" ); |
944 | if (!LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER) && |
945 | !LookingAtType(token_type: io::Tokenizer::TYPE_FLOAT) && |
946 | !LookingAtType(token_type: io::Tokenizer::TYPE_IDENTIFIER)) { |
947 | std::string text = tokenizer_.current().text; |
948 | ReportError(message: "Cannot skip field value, unexpected token: " + text); |
949 | ++recursion_limit_; |
950 | return false; |
951 | } |
952 | // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field |
953 | // value while other combinations all generate valid values. |
954 | // We check if the value of this combination is valid here. |
955 | // TYPE_IDENTIFIER after a '-' should be one of the float values listed |
956 | // below: |
957 | // inf, inff, infinity, nan |
958 | if (has_minus && LookingAtType(token_type: io::Tokenizer::TYPE_IDENTIFIER)) { |
959 | std::string text = tokenizer_.current().text; |
960 | LowerString(s: &text); |
961 | if (text != "inf" && |
962 | text != "infinity" && text != "nan" ) { |
963 | ReportError(message: "Invalid float number: " + text); |
964 | ++recursion_limit_; |
965 | return false; |
966 | } |
967 | } |
968 | tokenizer_.Next(); |
969 | ++recursion_limit_; |
970 | return true; |
971 | } |
972 | |
973 | // Returns true if the current token's text is equal to that specified. |
974 | bool LookingAt(const std::string& text) { |
975 | return tokenizer_.current().text == text; |
976 | } |
977 | |
978 | // Returns true if the current token's type is equal to that specified. |
979 | bool LookingAtType(io::Tokenizer::TokenType token_type) { |
980 | return tokenizer_.current().type == token_type; |
981 | } |
982 | |
983 | // Consumes an identifier and saves its value in the identifier parameter. |
984 | // Returns false if the token is not of type IDENTFIER. |
985 | bool ConsumeIdentifier(std::string* identifier) { |
986 | if (LookingAtType(token_type: io::Tokenizer::TYPE_IDENTIFIER)) { |
987 | *identifier = tokenizer_.current().text; |
988 | tokenizer_.Next(); |
989 | return true; |
990 | } |
991 | |
992 | // If allow_field_numer_ or allow_unknown_field_ is true, we should able |
993 | // to parse integer identifiers. |
994 | if ((allow_field_number_ || allow_unknown_field_ || |
995 | allow_unknown_extension_) && |
996 | LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
997 | *identifier = tokenizer_.current().text; |
998 | tokenizer_.Next(); |
999 | return true; |
1000 | } |
1001 | |
1002 | ReportError(message: "Expected identifier, got: " + tokenizer_.current().text); |
1003 | return false; |
1004 | } |
1005 | |
1006 | // Similar to `ConsumeIdentifier`, but any following whitespace token may |
1007 | // be reported. |
1008 | bool ConsumeIdentifierBeforeWhitespace(std::string* identifier) { |
1009 | tokenizer_.set_report_whitespace(true); |
1010 | bool result = ConsumeIdentifier(identifier); |
1011 | tokenizer_.set_report_whitespace(false); |
1012 | return result; |
1013 | } |
1014 | |
1015 | // Consume a string of form "<id1>.<id2>....<idN>". |
1016 | bool ConsumeFullTypeName(std::string* name) { |
1017 | DO(ConsumeIdentifier(name)); |
1018 | while (TryConsume(value: "." )) { |
1019 | std::string part; |
1020 | DO(ConsumeIdentifier(&part)); |
1021 | *name += "." ; |
1022 | *name += part; |
1023 | } |
1024 | return true; |
1025 | } |
1026 | |
1027 | bool ConsumeTypeUrlOrFullTypeName(std::string* name) { |
1028 | DO(ConsumeIdentifier(name)); |
1029 | while (true) { |
1030 | std::string connector; |
1031 | if (TryConsume(value: "." )) { |
1032 | connector = "." ; |
1033 | } else if (TryConsume(value: "/" )) { |
1034 | connector = "/" ; |
1035 | } else { |
1036 | break; |
1037 | } |
1038 | std::string part; |
1039 | DO(ConsumeIdentifier(&part)); |
1040 | *name += connector; |
1041 | *name += part; |
1042 | } |
1043 | return true; |
1044 | } |
1045 | |
1046 | // Consumes a string and saves its value in the text parameter. |
1047 | // Returns false if the token is not of type STRING. |
1048 | bool ConsumeString(std::string* text) { |
1049 | if (!LookingAtType(token_type: io::Tokenizer::TYPE_STRING)) { |
1050 | ReportError(message: "Expected string, got: " + tokenizer_.current().text); |
1051 | return false; |
1052 | } |
1053 | |
1054 | text->clear(); |
1055 | while (LookingAtType(token_type: io::Tokenizer::TYPE_STRING)) { |
1056 | io::Tokenizer::ParseStringAppend(text: tokenizer_.current().text, output: text); |
1057 | |
1058 | tokenizer_.Next(); |
1059 | } |
1060 | |
1061 | return true; |
1062 | } |
1063 | |
1064 | // Consumes a uint64_t and saves its value in the value parameter. |
1065 | // Returns false if the token is not of type INTEGER. |
1066 | bool ConsumeUnsignedInteger(uint64_t* value, uint64_t max_value) { |
1067 | if (!LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
1068 | ReportError(message: "Expected integer, got: " + tokenizer_.current().text); |
1069 | return false; |
1070 | } |
1071 | |
1072 | if (!io::Tokenizer::ParseInteger(text: tokenizer_.current().text, max_value, |
1073 | output: value)) { |
1074 | ReportError(message: "Integer out of range (" + tokenizer_.current().text + ")" ); |
1075 | return false; |
1076 | } |
1077 | |
1078 | tokenizer_.Next(); |
1079 | return true; |
1080 | } |
1081 | |
1082 | // Consumes an int64_t and saves its value in the value parameter. |
1083 | // Note that since the tokenizer does not support negative numbers, |
1084 | // we actually may consume an additional token (for the minus sign) in this |
1085 | // method. Returns false if the token is not an integer |
1086 | // (signed or otherwise). |
1087 | bool ConsumeSignedInteger(int64_t* value, uint64_t max_value) { |
1088 | bool negative = false; |
1089 | |
1090 | if (TryConsume(value: "-" )) { |
1091 | negative = true; |
1092 | // Two's complement always allows one more negative integer than |
1093 | // positive. |
1094 | ++max_value; |
1095 | } |
1096 | |
1097 | uint64_t unsigned_value; |
1098 | |
1099 | DO(ConsumeUnsignedInteger(&unsigned_value, max_value)); |
1100 | |
1101 | if (negative) { |
1102 | if ((static_cast<uint64_t>(kint64max) + 1) == unsigned_value) { |
1103 | *value = kint64min; |
1104 | } else { |
1105 | *value = -static_cast<int64_t>(unsigned_value); |
1106 | } |
1107 | } else { |
1108 | *value = static_cast<int64_t>(unsigned_value); |
1109 | } |
1110 | |
1111 | return true; |
1112 | } |
1113 | |
1114 | // Consumes a double and saves its value in the value parameter. |
1115 | // Accepts decimal numbers only, rejects hex or oct numbers. |
1116 | bool ConsumeUnsignedDecimalAsDouble(double* value, uint64_t max_value) { |
1117 | if (!LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
1118 | ReportError(message: "Expected integer, got: " + tokenizer_.current().text); |
1119 | return false; |
1120 | } |
1121 | |
1122 | const std::string& text = tokenizer_.current().text; |
1123 | if (IsHexNumber(str: text) || IsOctNumber(str: text)) { |
1124 | ReportError(message: "Expect a decimal number, got: " + text); |
1125 | return false; |
1126 | } |
1127 | |
1128 | uint64_t uint64_value; |
1129 | if (io::Tokenizer::ParseInteger(text, max_value, output: &uint64_value)) { |
1130 | *value = static_cast<double>(uint64_value); |
1131 | } else { |
1132 | // Uint64 overflow, attempt to parse as a double instead. |
1133 | *value = io::Tokenizer::ParseFloat(text); |
1134 | } |
1135 | |
1136 | tokenizer_.Next(); |
1137 | return true; |
1138 | } |
1139 | |
1140 | // Consumes a double and saves its value in the value parameter. |
1141 | // Note that since the tokenizer does not support negative numbers, |
1142 | // we actually may consume an additional token (for the minus sign) in this |
1143 | // method. Returns false if the token is not a double |
1144 | // (signed or otherwise). |
1145 | bool ConsumeDouble(double* value) { |
1146 | bool negative = false; |
1147 | |
1148 | if (TryConsume(value: "-" )) { |
1149 | negative = true; |
1150 | } |
1151 | |
1152 | // A double can actually be an integer, according to the tokenizer. |
1153 | // Therefore, we must check both cases here. |
1154 | if (LookingAtType(token_type: io::Tokenizer::TYPE_INTEGER)) { |
1155 | // We have found an integer value for the double. |
1156 | DO(ConsumeUnsignedDecimalAsDouble(value, kuint64max)); |
1157 | } else if (LookingAtType(token_type: io::Tokenizer::TYPE_FLOAT)) { |
1158 | // We have found a float value for the double. |
1159 | *value = io::Tokenizer::ParseFloat(text: tokenizer_.current().text); |
1160 | |
1161 | // Mark the current token as consumed. |
1162 | tokenizer_.Next(); |
1163 | } else if (LookingAtType(token_type: io::Tokenizer::TYPE_IDENTIFIER)) { |
1164 | std::string text = tokenizer_.current().text; |
1165 | LowerString(s: &text); |
1166 | if (text == "inf" || |
1167 | text == "infinity" ) { |
1168 | *value = std::numeric_limits<double>::infinity(); |
1169 | tokenizer_.Next(); |
1170 | } else if (text == "nan" ) { |
1171 | *value = std::numeric_limits<double>::quiet_NaN(); |
1172 | tokenizer_.Next(); |
1173 | } else { |
1174 | ReportError(message: "Expected double, got: " + text); |
1175 | return false; |
1176 | } |
1177 | } else { |
1178 | ReportError(message: "Expected double, got: " + tokenizer_.current().text); |
1179 | return false; |
1180 | } |
1181 | |
1182 | if (negative) { |
1183 | *value = -*value; |
1184 | } |
1185 | |
1186 | return true; |
1187 | } |
1188 | |
1189 | // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name" |
1190 | // or "type.googleprod.com/full.type.Name" |
1191 | bool ConsumeAnyTypeUrl(std::string* full_type_name, std::string* prefix) { |
1192 | // TODO(saito) Extend Consume() to consume multiple tokens at once, so that |
1193 | // this code can be written as just DO(Consume(kGoogleApisTypePrefix)). |
1194 | DO(ConsumeIdentifier(prefix)); |
1195 | while (TryConsume(value: "." )) { |
1196 | std::string url; |
1197 | DO(ConsumeIdentifier(&url)); |
1198 | *prefix += "." + url; |
1199 | } |
1200 | DO(Consume("/" )); |
1201 | *prefix += "/" ; |
1202 | DO(ConsumeFullTypeName(full_type_name)); |
1203 | |
1204 | return true; |
1205 | } |
1206 | |
1207 | // A helper function for reconstructing Any::value. Consumes a text of |
1208 | // full_type_name, then serializes it into serialized_value. |
1209 | bool ConsumeAnyValue(const Descriptor* value_descriptor, |
1210 | std::string* serialized_value) { |
1211 | DynamicMessageFactory factory; |
1212 | const Message* value_prototype = factory.GetPrototype(type: value_descriptor); |
1213 | if (value_prototype == nullptr) { |
1214 | return false; |
1215 | } |
1216 | std::unique_ptr<Message> value(value_prototype->New()); |
1217 | std::string sub_delimiter; |
1218 | DO(ConsumeMessageDelimiter(&sub_delimiter)); |
1219 | DO(ConsumeMessage(value.get(), sub_delimiter)); |
1220 | |
1221 | if (allow_partial_) { |
1222 | value->AppendPartialToString(output: serialized_value); |
1223 | } else { |
1224 | if (!value->IsInitialized()) { |
1225 | ReportError( |
1226 | message: "Value of type \"" + value_descriptor->full_name() + |
1227 | "\" stored in google.protobuf.Any has missing required fields" ); |
1228 | return false; |
1229 | } |
1230 | value->AppendToString(output: serialized_value); |
1231 | } |
1232 | return true; |
1233 | } |
1234 | |
1235 | // Consumes a token and confirms that it matches that specified in the |
1236 | // value parameter. Returns false if the token found does not match that |
1237 | // which was specified. |
1238 | bool Consume(const std::string& value) { |
1239 | const std::string& current_value = tokenizer_.current().text; |
1240 | |
1241 | if (current_value != value) { |
1242 | ReportError(message: "Expected \"" + value + "\", found \"" + current_value + |
1243 | "\"." ); |
1244 | return false; |
1245 | } |
1246 | |
1247 | tokenizer_.Next(); |
1248 | |
1249 | return true; |
1250 | } |
1251 | |
1252 | // Similar to `Consume`, but the following token may be tokenized as |
1253 | // TYPE_WHITESPACE. |
1254 | bool ConsumeBeforeWhitespace(const std::string& value) { |
1255 | // Report whitespace after this token, but only once. |
1256 | tokenizer_.set_report_whitespace(true); |
1257 | bool result = Consume(value); |
1258 | tokenizer_.set_report_whitespace(false); |
1259 | return result; |
1260 | } |
1261 | |
1262 | // Attempts to consume the supplied value. Returns false if a the |
1263 | // token found does not match the value specified. |
1264 | bool TryConsume(const std::string& value) { |
1265 | if (tokenizer_.current().text == value) { |
1266 | tokenizer_.Next(); |
1267 | return true; |
1268 | } else { |
1269 | return false; |
1270 | } |
1271 | } |
1272 | |
1273 | // Similar to `TryConsume`, but the following token may be tokenized as |
1274 | // TYPE_WHITESPACE. |
1275 | bool TryConsumeBeforeWhitespace(const std::string& value) { |
1276 | // Report whitespace after this token, but only once. |
1277 | tokenizer_.set_report_whitespace(true); |
1278 | bool result = TryConsume(value); |
1279 | tokenizer_.set_report_whitespace(false); |
1280 | return result; |
1281 | } |
1282 | |
1283 | bool TryConsumeWhitespace() { |
1284 | had_silent_marker_ = false; |
1285 | if (LookingAtType(token_type: io::Tokenizer::TYPE_WHITESPACE)) { |
1286 | if (tokenizer_.current().text == |
1287 | StrCat(a: " " , b: internal::kDebugStringSilentMarkerForDetection)) { |
1288 | had_silent_marker_ = true; |
1289 | } |
1290 | tokenizer_.Next(); |
1291 | return true; |
1292 | } |
1293 | return false; |
1294 | } |
1295 | |
1296 | // An internal instance of the Tokenizer's error collector, used to |
1297 | // collect any base-level parse errors and feed them to the ParserImpl. |
1298 | class ParserErrorCollector : public io::ErrorCollector { |
1299 | public: |
1300 | explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) |
1301 | : parser_(parser) {} |
1302 | |
1303 | ~ParserErrorCollector() override {} |
1304 | |
1305 | void AddError(int line, int column, const std::string& message) override { |
1306 | parser_->ReportError(line, col: column, message); |
1307 | } |
1308 | |
1309 | void AddWarning(int line, int column, const std::string& message) override { |
1310 | parser_->ReportWarning(line, col: column, message); |
1311 | } |
1312 | |
1313 | private: |
1314 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); |
1315 | TextFormat::Parser::ParserImpl* parser_; |
1316 | }; |
1317 | |
1318 | io::ErrorCollector* error_collector_; |
1319 | const TextFormat::Finder* finder_; |
1320 | ParseInfoTree* parse_info_tree_; |
1321 | ParserErrorCollector tokenizer_error_collector_; |
1322 | io::Tokenizer tokenizer_; |
1323 | const Descriptor* root_message_type_; |
1324 | SingularOverwritePolicy singular_overwrite_policy_; |
1325 | const bool allow_case_insensitive_field_; |
1326 | const bool allow_unknown_field_; |
1327 | const bool allow_unknown_extension_; |
1328 | const bool allow_unknown_enum_; |
1329 | const bool allow_field_number_; |
1330 | const bool allow_partial_; |
1331 | const int initial_recursion_limit_; |
1332 | int recursion_limit_; |
1333 | bool had_silent_marker_; |
1334 | bool had_errors_; |
1335 | }; |
1336 | |
1337 | // =========================================================================== |
1338 | // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted |
1339 | // from the Printer found in //net/proto2/io/public/printer.h |
1340 | class TextFormat::Printer::TextGenerator |
1341 | : public TextFormat::BaseTextGenerator { |
1342 | public: |
1343 | explicit TextGenerator(io::ZeroCopyOutputStream* output, |
1344 | int initial_indent_level) |
1345 | : output_(output), |
1346 | buffer_(nullptr), |
1347 | buffer_size_(0), |
1348 | at_start_of_line_(true), |
1349 | failed_(false), |
1350 | insert_silent_marker_(false), |
1351 | indent_level_(initial_indent_level), |
1352 | initial_indent_level_(initial_indent_level) {} |
1353 | |
1354 | explicit TextGenerator(io::ZeroCopyOutputStream* output, |
1355 | bool insert_silent_marker, int initial_indent_level) |
1356 | : output_(output), |
1357 | buffer_(nullptr), |
1358 | buffer_size_(0), |
1359 | at_start_of_line_(true), |
1360 | failed_(false), |
1361 | insert_silent_marker_(insert_silent_marker), |
1362 | indent_level_(initial_indent_level), |
1363 | initial_indent_level_(initial_indent_level) {} |
1364 | |
1365 | ~TextGenerator() override { |
1366 | // Only BackUp() if we're sure we've successfully called Next() at least |
1367 | // once. |
1368 | if (!failed_) { |
1369 | output_->BackUp(count: buffer_size_); |
1370 | } |
1371 | } |
1372 | |
1373 | // Indent text by two spaces. After calling Indent(), two spaces will be |
1374 | // inserted at the beginning of each line of text. Indent() may be called |
1375 | // multiple times to produce deeper indents. |
1376 | void Indent() override { ++indent_level_; } |
1377 | |
1378 | // Reduces the current indent level by two spaces, or crashes if the indent |
1379 | // level is zero. |
1380 | void Outdent() override { |
1381 | if (indent_level_ == 0 || indent_level_ < initial_indent_level_) { |
1382 | GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()." ; |
1383 | return; |
1384 | } |
1385 | |
1386 | --indent_level_; |
1387 | } |
1388 | |
1389 | size_t GetCurrentIndentationSize() const override { |
1390 | return 2 * indent_level_; |
1391 | } |
1392 | |
1393 | // Print text to the output stream. |
1394 | void Print(const char* text, size_t size) override { |
1395 | if (indent_level_ > 0) { |
1396 | size_t pos = 0; // The number of bytes we've written so far. |
1397 | for (size_t i = 0; i < size; i++) { |
1398 | if (text[i] == '\n') { |
1399 | // Saw newline. If there is more text, we may need to insert an |
1400 | // indent here. So, write what we have so far, including the '\n'. |
1401 | Write(data: text + pos, size: i - pos + 1); |
1402 | pos = i + 1; |
1403 | |
1404 | // Setting this true will cause the next Write() to insert an indent |
1405 | // first. |
1406 | at_start_of_line_ = true; |
1407 | } |
1408 | } |
1409 | // Write the rest. |
1410 | Write(data: text + pos, size: size - pos); |
1411 | } else { |
1412 | Write(data: text, size); |
1413 | if (size > 0 && text[size - 1] == '\n') { |
1414 | at_start_of_line_ = true; |
1415 | } |
1416 | } |
1417 | } |
1418 | |
1419 | // True if any write to the underlying stream failed. (We don't just |
1420 | // crash in this case because this is an I/O failure, not a programming |
1421 | // error.) |
1422 | bool failed() const { return failed_; } |
1423 | |
1424 | void PrintMaybeWithMarker(StringPiece text) { |
1425 | Print(text: text.data(), size: text.size()); |
1426 | if (ConsumeInsertSilentMarker()) { |
1427 | PrintLiteral(text: internal::kDebugStringSilentMarker); |
1428 | } |
1429 | } |
1430 | |
1431 | void PrintMaybeWithMarker(StringPiece text_head, |
1432 | StringPiece text_tail) { |
1433 | Print(text: text_head.data(), size: text_head.size()); |
1434 | if (ConsumeInsertSilentMarker()) { |
1435 | PrintLiteral(text: internal::kDebugStringSilentMarker); |
1436 | } |
1437 | Print(text: text_tail.data(), size: text_tail.size()); |
1438 | } |
1439 | |
1440 | private: |
1441 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator); |
1442 | |
1443 | void Write(const char* data, size_t size) { |
1444 | if (failed_) return; |
1445 | if (size == 0) return; |
1446 | |
1447 | if (at_start_of_line_) { |
1448 | // Insert an indent. |
1449 | at_start_of_line_ = false; |
1450 | WriteIndent(); |
1451 | if (failed_) return; |
1452 | } |
1453 | |
1454 | while (static_cast<int64_t>(size) > buffer_size_) { |
1455 | // Data exceeds space in the buffer. Copy what we can and request a |
1456 | // new buffer. |
1457 | if (buffer_size_ > 0) { |
1458 | memcpy(dest: buffer_, src: data, n: buffer_size_); |
1459 | data += buffer_size_; |
1460 | size -= buffer_size_; |
1461 | } |
1462 | void* void_buffer = nullptr; |
1463 | failed_ = !output_->Next(data: &void_buffer, size: &buffer_size_); |
1464 | if (failed_) return; |
1465 | buffer_ = reinterpret_cast<char*>(void_buffer); |
1466 | } |
1467 | |
1468 | // Buffer is big enough to receive the data; copy it. |
1469 | memcpy(dest: buffer_, src: data, n: size); |
1470 | buffer_ += size; |
1471 | buffer_size_ -= size; |
1472 | } |
1473 | |
1474 | void WriteIndent() { |
1475 | if (indent_level_ == 0) { |
1476 | return; |
1477 | } |
1478 | GOOGLE_DCHECK(!failed_); |
1479 | int size = GetCurrentIndentationSize(); |
1480 | |
1481 | while (size > buffer_size_) { |
1482 | // Data exceeds space in the buffer. Write what we can and request a new |
1483 | // buffer. |
1484 | if (buffer_size_ > 0) { |
1485 | memset(s: buffer_, c: ' ', n: buffer_size_); |
1486 | } |
1487 | size -= buffer_size_; |
1488 | void* void_buffer; |
1489 | failed_ = !output_->Next(data: &void_buffer, size: &buffer_size_); |
1490 | if (failed_) return; |
1491 | buffer_ = reinterpret_cast<char*>(void_buffer); |
1492 | } |
1493 | |
1494 | // Buffer is big enough to receive the data; copy it. |
1495 | memset(s: buffer_, c: ' ', n: size); |
1496 | buffer_ += size; |
1497 | buffer_size_ -= size; |
1498 | } |
1499 | |
1500 | // Return the current value of insert_silent_marker_. If it is true, set it |
1501 | // to false as we assume that a silent marker is inserted after a call to this |
1502 | // function. |
1503 | bool ConsumeInsertSilentMarker() { |
1504 | if (insert_silent_marker_) { |
1505 | insert_silent_marker_ = false; |
1506 | return true; |
1507 | } |
1508 | return false; |
1509 | } |
1510 | |
1511 | io::ZeroCopyOutputStream* const output_; |
1512 | char* buffer_; |
1513 | int buffer_size_; |
1514 | bool at_start_of_line_; |
1515 | bool failed_; |
1516 | // This flag is false when inserting silent marker is disabled or a silent |
1517 | // marker has been inserted. |
1518 | bool insert_silent_marker_; |
1519 | |
1520 | int indent_level_; |
1521 | int initial_indent_level_; |
1522 | }; |
1523 | |
1524 | // =========================================================================== |
1525 | // An internal field value printer that may insert a silent marker in |
1526 | // DebugStrings. |
1527 | class TextFormat::Printer::DebugStringFieldValuePrinter |
1528 | : public TextFormat::FastFieldValuePrinter { |
1529 | public: |
1530 | void PrintMessageStart(const Message& /*message*/, int /*field_index*/, |
1531 | int /*field_count*/, bool single_line_mode, |
1532 | BaseTextGenerator* generator) const override { |
1533 | // This is safe as only TextGenerator is used with |
1534 | // DebugStringFieldValuePrinter. |
1535 | TextGenerator* text_generator = static_cast<TextGenerator*>(generator); |
1536 | if (single_line_mode) { |
1537 | text_generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{ " ); |
1538 | } else { |
1539 | text_generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{\n" ); |
1540 | } |
1541 | } |
1542 | }; |
1543 | |
1544 | // =========================================================================== |
1545 | // An internal field value printer that escape UTF8 strings. |
1546 | class TextFormat::Printer::FastFieldValuePrinterUtf8Escaping |
1547 | : public TextFormat::Printer::DebugStringFieldValuePrinter { |
1548 | public: |
1549 | void PrintString(const std::string& val, |
1550 | TextFormat::BaseTextGenerator* generator) const override { |
1551 | generator->PrintLiteral(text: "\"" ); |
1552 | generator->PrintString(str: strings::Utf8SafeCEscape(src: val)); |
1553 | generator->PrintLiteral(text: "\"" ); |
1554 | } |
1555 | void PrintBytes(const std::string& val, |
1556 | TextFormat::BaseTextGenerator* generator) const override { |
1557 | return FastFieldValuePrinter::PrintString(val, generator); |
1558 | } |
1559 | }; |
1560 | |
1561 | // =========================================================================== |
1562 | // Implementation of the default Finder for extensions. |
1563 | TextFormat::Finder::~Finder() {} |
1564 | |
1565 | const FieldDescriptor* TextFormat::Finder::FindExtension( |
1566 | Message* message, const std::string& name) const { |
1567 | return DefaultFinderFindExtension(message, name); |
1568 | } |
1569 | |
1570 | const FieldDescriptor* TextFormat::Finder::FindExtensionByNumber( |
1571 | const Descriptor* descriptor, int number) const { |
1572 | return DefaultFinderFindExtensionByNumber(descriptor, number); |
1573 | } |
1574 | |
1575 | const Descriptor* TextFormat::Finder::FindAnyType( |
1576 | const Message& message, const std::string& prefix, |
1577 | const std::string& name) const { |
1578 | return DefaultFinderFindAnyType(message, prefix, name); |
1579 | } |
1580 | |
1581 | MessageFactory* TextFormat::Finder::FindExtensionFactory( |
1582 | const FieldDescriptor* /*field*/) const { |
1583 | return nullptr; |
1584 | } |
1585 | |
1586 | // =========================================================================== |
1587 | |
1588 | TextFormat::Parser::Parser() |
1589 | : error_collector_(nullptr), |
1590 | finder_(nullptr), |
1591 | parse_info_tree_(nullptr), |
1592 | allow_partial_(false), |
1593 | allow_case_insensitive_field_(false), |
1594 | allow_unknown_field_(false), |
1595 | allow_unknown_extension_(false), |
1596 | allow_unknown_enum_(false), |
1597 | allow_field_number_(false), |
1598 | allow_relaxed_whitespace_(false), |
1599 | allow_singular_overwrites_(false), |
1600 | recursion_limit_(std::numeric_limits<int>::max()) {} |
1601 | |
1602 | TextFormat::Parser::~Parser() {} |
1603 | |
1604 | namespace { |
1605 | |
1606 | bool CheckParseInputSize(StringPiece input, |
1607 | io::ErrorCollector* error_collector) { |
1608 | if (input.size() > INT_MAX) { |
1609 | error_collector->AddError( |
1610 | line: -1, column: 0, |
1611 | message: StrCat( |
1612 | a: "Input size too large: " , b: static_cast<int64_t>(input.size()), |
1613 | c: " bytes" , d: " > " , INT_MAX, f: " bytes." )); |
1614 | return false; |
1615 | } |
1616 | return true; |
1617 | } |
1618 | |
1619 | } // namespace |
1620 | |
1621 | bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, |
1622 | Message* output) { |
1623 | output->Clear(); |
1624 | |
1625 | ParserImpl::SingularOverwritePolicy overwrites_policy = |
1626 | allow_singular_overwrites_ ? ParserImpl::ALLOW_SINGULAR_OVERWRITES |
1627 | : ParserImpl::FORBID_SINGULAR_OVERWRITES; |
1628 | |
1629 | ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, |
1630 | parse_info_tree_, overwrites_policy, |
1631 | allow_case_insensitive_field_, allow_unknown_field_, |
1632 | allow_unknown_extension_, allow_unknown_enum_, |
1633 | allow_field_number_, allow_relaxed_whitespace_, |
1634 | allow_partial_, recursion_limit_); |
1635 | return MergeUsingImpl(input, output, parser_impl: &parser); |
1636 | } |
1637 | |
1638 | bool TextFormat::Parser::ParseFromString(ConstStringParam input, |
1639 | Message* output) { |
1640 | DO(CheckParseInputSize(input, error_collector_)); |
1641 | io::ArrayInputStream input_stream(input.data(), input.size()); |
1642 | return Parse(input: &input_stream, output); |
1643 | } |
1644 | |
1645 | bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, |
1646 | Message* output) { |
1647 | ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, |
1648 | parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, |
1649 | allow_case_insensitive_field_, allow_unknown_field_, |
1650 | allow_unknown_extension_, allow_unknown_enum_, |
1651 | allow_field_number_, allow_relaxed_whitespace_, |
1652 | allow_partial_, recursion_limit_); |
1653 | return MergeUsingImpl(input, output, parser_impl: &parser); |
1654 | } |
1655 | |
1656 | bool TextFormat::Parser::MergeFromString(ConstStringParam input, |
1657 | Message* output) { |
1658 | DO(CheckParseInputSize(input, error_collector_)); |
1659 | io::ArrayInputStream input_stream(input.data(), input.size()); |
1660 | return Merge(input: &input_stream, output); |
1661 | } |
1662 | |
1663 | bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, |
1664 | Message* output, |
1665 | ParserImpl* parser_impl) { |
1666 | if (!parser_impl->Parse(output)) return false; |
1667 | if (!allow_partial_ && !output->IsInitialized()) { |
1668 | std::vector<std::string> missing_fields; |
1669 | output->FindInitializationErrors(errors: &missing_fields); |
1670 | parser_impl->ReportError(line: -1, col: 0, |
1671 | message: "Message missing required fields: " + |
1672 | Join(components: missing_fields, delim: ", " )); |
1673 | return false; |
1674 | } |
1675 | return true; |
1676 | } |
1677 | |
1678 | bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, |
1679 | const FieldDescriptor* field, |
1680 | Message* output) { |
1681 | io::ArrayInputStream input_stream(input.data(), input.size()); |
1682 | ParserImpl parser( |
1683 | output->GetDescriptor(), &input_stream, error_collector_, finder_, |
1684 | parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, |
1685 | allow_case_insensitive_field_, allow_unknown_field_, |
1686 | allow_unknown_extension_, allow_unknown_enum_, allow_field_number_, |
1687 | allow_relaxed_whitespace_, allow_partial_, recursion_limit_); |
1688 | return parser.ParseField(field, output); |
1689 | } |
1690 | |
1691 | /* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, |
1692 | Message* output) { |
1693 | return Parser().Parse(input, output); |
1694 | } |
1695 | |
1696 | /* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input, |
1697 | Message* output) { |
1698 | return Parser().Merge(input, output); |
1699 | } |
1700 | |
1701 | /* static */ bool TextFormat::ParseFromString(ConstStringParam input, |
1702 | Message* output) { |
1703 | return Parser().ParseFromString(input, output); |
1704 | } |
1705 | |
1706 | /* static */ bool TextFormat::MergeFromString(ConstStringParam input, |
1707 | Message* output) { |
1708 | return Parser().MergeFromString(input, output); |
1709 | } |
1710 | |
1711 | #undef DO |
1712 | |
1713 | // =========================================================================== |
1714 | |
1715 | TextFormat::BaseTextGenerator::~BaseTextGenerator() {} |
1716 | |
1717 | namespace { |
1718 | |
1719 | // A BaseTextGenerator that writes to a string. |
1720 | class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { |
1721 | public: |
1722 | void Print(const char* text, size_t size) override { |
1723 | output_.append(s: text, n: size); |
1724 | } |
1725 | |
1726 | // Some compilers do not support ref-qualifiers even in C++11 mode. |
1727 | // Disable the optimization for now and revisit it later. |
1728 | #if 0 // LANG_CXX11 |
1729 | std::string Consume() && { return std::move(output_); } |
1730 | #else // !LANG_CXX11 |
1731 | const std::string& Get() { return output_; } |
1732 | #endif // LANG_CXX11 |
1733 | |
1734 | private: |
1735 | std::string output_; |
1736 | }; |
1737 | |
1738 | } // namespace |
1739 | |
1740 | // The default implementation for FieldValuePrinter. We just delegate the |
1741 | // implementation to the default FastFieldValuePrinter to avoid duplicating the |
1742 | // logic. |
1743 | TextFormat::FieldValuePrinter::FieldValuePrinter() {} |
1744 | TextFormat::FieldValuePrinter::~FieldValuePrinter() {} |
1745 | |
1746 | #if 0 // LANG_CXX11 |
1747 | #define FORWARD_IMPL(fn, ...) \ |
1748 | StringBaseTextGenerator generator; \ |
1749 | delegate_.fn(__VA_ARGS__, &generator); \ |
1750 | return std::move(generator).Consume() |
1751 | #else // !LANG_CXX11 |
1752 | #define FORWARD_IMPL(fn, ...) \ |
1753 | StringBaseTextGenerator generator; \ |
1754 | delegate_.fn(__VA_ARGS__, &generator); \ |
1755 | return generator.Get() |
1756 | #endif // LANG_CXX11 |
1757 | |
1758 | std::string TextFormat::FieldValuePrinter::PrintBool(bool val) const { |
1759 | FORWARD_IMPL(PrintBool, val); |
1760 | } |
1761 | std::string TextFormat::FieldValuePrinter::PrintInt32(int32_t val) const { |
1762 | FORWARD_IMPL(PrintInt32, val); |
1763 | } |
1764 | std::string TextFormat::FieldValuePrinter::PrintUInt32(uint32_t val) const { |
1765 | FORWARD_IMPL(PrintUInt32, val); |
1766 | } |
1767 | std::string TextFormat::FieldValuePrinter::PrintInt64(int64_t val) const { |
1768 | FORWARD_IMPL(PrintInt64, val); |
1769 | } |
1770 | std::string TextFormat::FieldValuePrinter::PrintUInt64(uint64_t val) const { |
1771 | FORWARD_IMPL(PrintUInt64, val); |
1772 | } |
1773 | std::string TextFormat::FieldValuePrinter::PrintFloat(float val) const { |
1774 | FORWARD_IMPL(PrintFloat, val); |
1775 | } |
1776 | std::string TextFormat::FieldValuePrinter::PrintDouble(double val) const { |
1777 | FORWARD_IMPL(PrintDouble, val); |
1778 | } |
1779 | std::string TextFormat::FieldValuePrinter::PrintString( |
1780 | const std::string& val) const { |
1781 | FORWARD_IMPL(PrintString, val); |
1782 | } |
1783 | std::string TextFormat::FieldValuePrinter::PrintBytes( |
1784 | const std::string& val) const { |
1785 | return PrintString(val); |
1786 | } |
1787 | std::string TextFormat::FieldValuePrinter::PrintEnum( |
1788 | int32_t val, const std::string& name) const { |
1789 | FORWARD_IMPL(PrintEnum, val, name); |
1790 | } |
1791 | std::string TextFormat::FieldValuePrinter::PrintFieldName( |
1792 | const Message& message, const Reflection* reflection, |
1793 | const FieldDescriptor* field) const { |
1794 | FORWARD_IMPL(PrintFieldName, message, reflection, field); |
1795 | } |
1796 | std::string TextFormat::FieldValuePrinter::PrintMessageStart( |
1797 | const Message& message, int field_index, int field_count, |
1798 | bool single_line_mode) const { |
1799 | FORWARD_IMPL(PrintMessageStart, message, field_index, field_count, |
1800 | single_line_mode); |
1801 | } |
1802 | std::string TextFormat::FieldValuePrinter::PrintMessageEnd( |
1803 | const Message& message, int field_index, int field_count, |
1804 | bool single_line_mode) const { |
1805 | FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count, |
1806 | single_line_mode); |
1807 | } |
1808 | #undef FORWARD_IMPL |
1809 | |
1810 | TextFormat::FastFieldValuePrinter::FastFieldValuePrinter() {} |
1811 | TextFormat::FastFieldValuePrinter::~FastFieldValuePrinter() {} |
1812 | void TextFormat::FastFieldValuePrinter::PrintBool( |
1813 | bool val, BaseTextGenerator* generator) const { |
1814 | if (val) { |
1815 | generator->PrintLiteral(text: "true" ); |
1816 | } else { |
1817 | generator->PrintLiteral(text: "false" ); |
1818 | } |
1819 | } |
1820 | void TextFormat::FastFieldValuePrinter::PrintInt32( |
1821 | int32_t val, BaseTextGenerator* generator) const { |
1822 | generator->PrintString(str: StrCat(a: val)); |
1823 | } |
1824 | void TextFormat::FastFieldValuePrinter::PrintUInt32( |
1825 | uint32_t val, BaseTextGenerator* generator) const { |
1826 | generator->PrintString(str: StrCat(a: val)); |
1827 | } |
1828 | void TextFormat::FastFieldValuePrinter::PrintInt64( |
1829 | int64_t val, BaseTextGenerator* generator) const { |
1830 | generator->PrintString(str: StrCat(a: val)); |
1831 | } |
1832 | void TextFormat::FastFieldValuePrinter::PrintUInt64( |
1833 | uint64_t val, BaseTextGenerator* generator) const { |
1834 | generator->PrintString(str: StrCat(a: val)); |
1835 | } |
1836 | void TextFormat::FastFieldValuePrinter::PrintFloat( |
1837 | float val, BaseTextGenerator* generator) const { |
1838 | generator->PrintString(str: !std::isnan(x: val) ? SimpleFtoa(value: val) : "nan" ); |
1839 | } |
1840 | void TextFormat::FastFieldValuePrinter::PrintDouble( |
1841 | double val, BaseTextGenerator* generator) const { |
1842 | generator->PrintString(str: !std::isnan(x: val) ? SimpleDtoa(value: val) : "nan" ); |
1843 | } |
1844 | void TextFormat::FastFieldValuePrinter::PrintEnum( |
1845 | int32_t /*val*/, const std::string& name, |
1846 | BaseTextGenerator* generator) const { |
1847 | generator->PrintString(str: name); |
1848 | } |
1849 | |
1850 | void TextFormat::FastFieldValuePrinter::PrintString( |
1851 | const std::string& val, BaseTextGenerator* generator) const { |
1852 | generator->PrintLiteral(text: "\"" ); |
1853 | generator->PrintString(str: CEscape(src: val)); |
1854 | generator->PrintLiteral(text: "\"" ); |
1855 | } |
1856 | void TextFormat::FastFieldValuePrinter::PrintBytes( |
1857 | const std::string& val, BaseTextGenerator* generator) const { |
1858 | PrintString(val, generator); |
1859 | } |
1860 | void TextFormat::FastFieldValuePrinter::PrintFieldName( |
1861 | const Message& message, int /*field_index*/, int /*field_count*/, |
1862 | const Reflection* reflection, const FieldDescriptor* field, |
1863 | BaseTextGenerator* generator) const { |
1864 | PrintFieldName(message, reflection, field, generator); |
1865 | } |
1866 | void TextFormat::FastFieldValuePrinter::PrintFieldName( |
1867 | const Message& /*message*/, const Reflection* /*reflection*/, |
1868 | const FieldDescriptor* field, BaseTextGenerator* generator) const { |
1869 | if (field->is_extension()) { |
1870 | generator->PrintLiteral(text: "[" ); |
1871 | generator->PrintString(str: field->PrintableNameForExtension()); |
1872 | generator->PrintLiteral(text: "]" ); |
1873 | } else if (field->type() == FieldDescriptor::TYPE_GROUP) { |
1874 | // Groups must be serialized with their original capitalization. |
1875 | generator->PrintString(str: field->message_type()->name()); |
1876 | } else { |
1877 | generator->PrintString(str: field->name()); |
1878 | } |
1879 | } |
1880 | void TextFormat::FastFieldValuePrinter::PrintMessageStart( |
1881 | const Message& /*message*/, int /*field_index*/, int /*field_count*/, |
1882 | bool single_line_mode, BaseTextGenerator* generator) const { |
1883 | if (single_line_mode) { |
1884 | generator->PrintLiteral(text: " { " ); |
1885 | } else { |
1886 | generator->PrintLiteral(text: " {\n" ); |
1887 | } |
1888 | } |
1889 | bool TextFormat::FastFieldValuePrinter::PrintMessageContent( |
1890 | const Message& /*message*/, int /*field_index*/, int /*field_count*/, |
1891 | bool /*single_line_mode*/, BaseTextGenerator* /*generator*/) const { |
1892 | return false; // Use the default printing function. |
1893 | } |
1894 | void TextFormat::FastFieldValuePrinter::PrintMessageEnd( |
1895 | const Message& /*message*/, int /*field_index*/, int /*field_count*/, |
1896 | bool single_line_mode, BaseTextGenerator* generator) const { |
1897 | if (single_line_mode) { |
1898 | generator->PrintLiteral(text: "} " ); |
1899 | } else { |
1900 | generator->PrintLiteral(text: "}\n" ); |
1901 | } |
1902 | } |
1903 | |
1904 | namespace { |
1905 | |
1906 | // A legacy compatibility wrapper. Takes ownership of the delegate. |
1907 | class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter { |
1908 | public: |
1909 | explicit FieldValuePrinterWrapper( |
1910 | const TextFormat::FieldValuePrinter* delegate) |
1911 | : delegate_(delegate) {} |
1912 | |
1913 | void SetDelegate(const TextFormat::FieldValuePrinter* delegate) { |
1914 | delegate_.reset(p: delegate); |
1915 | } |
1916 | |
1917 | void PrintBool(bool val, |
1918 | TextFormat::BaseTextGenerator* generator) const override { |
1919 | generator->PrintString(str: delegate_->PrintBool(val)); |
1920 | } |
1921 | void PrintInt32(int32_t val, |
1922 | TextFormat::BaseTextGenerator* generator) const override { |
1923 | generator->PrintString(str: delegate_->PrintInt32(val)); |
1924 | } |
1925 | void PrintUInt32(uint32_t val, |
1926 | TextFormat::BaseTextGenerator* generator) const override { |
1927 | generator->PrintString(str: delegate_->PrintUInt32(val)); |
1928 | } |
1929 | void PrintInt64(int64_t val, |
1930 | TextFormat::BaseTextGenerator* generator) const override { |
1931 | generator->PrintString(str: delegate_->PrintInt64(val)); |
1932 | } |
1933 | void PrintUInt64(uint64_t val, |
1934 | TextFormat::BaseTextGenerator* generator) const override { |
1935 | generator->PrintString(str: delegate_->PrintUInt64(val)); |
1936 | } |
1937 | void PrintFloat(float val, |
1938 | TextFormat::BaseTextGenerator* generator) const override { |
1939 | generator->PrintString(str: delegate_->PrintFloat(val)); |
1940 | } |
1941 | void PrintDouble(double val, |
1942 | TextFormat::BaseTextGenerator* generator) const override { |
1943 | generator->PrintString(str: delegate_->PrintDouble(val)); |
1944 | } |
1945 | void PrintString(const std::string& val, |
1946 | TextFormat::BaseTextGenerator* generator) const override { |
1947 | generator->PrintString(str: delegate_->PrintString(val)); |
1948 | } |
1949 | void PrintBytes(const std::string& val, |
1950 | TextFormat::BaseTextGenerator* generator) const override { |
1951 | generator->PrintString(str: delegate_->PrintBytes(val)); |
1952 | } |
1953 | void PrintEnum(int32_t val, const std::string& name, |
1954 | TextFormat::BaseTextGenerator* generator) const override { |
1955 | generator->PrintString(str: delegate_->PrintEnum(val, name)); |
1956 | } |
1957 | void PrintFieldName(const Message& message, int /*field_index*/, |
1958 | int /*field_count*/, const Reflection* reflection, |
1959 | const FieldDescriptor* field, |
1960 | TextFormat::BaseTextGenerator* generator) const override { |
1961 | generator->PrintString( |
1962 | str: delegate_->PrintFieldName(message, reflection, field)); |
1963 | } |
1964 | void PrintFieldName(const Message& message, const Reflection* reflection, |
1965 | const FieldDescriptor* field, |
1966 | TextFormat::BaseTextGenerator* generator) const override { |
1967 | generator->PrintString( |
1968 | str: delegate_->PrintFieldName(message, reflection, field)); |
1969 | } |
1970 | void PrintMessageStart( |
1971 | const Message& message, int field_index, int field_count, |
1972 | bool single_line_mode, |
1973 | TextFormat::BaseTextGenerator* generator) const override { |
1974 | generator->PrintString(str: delegate_->PrintMessageStart( |
1975 | message, field_index, field_count, single_line_mode)); |
1976 | } |
1977 | void PrintMessageEnd( |
1978 | const Message& message, int field_index, int field_count, |
1979 | bool single_line_mode, |
1980 | TextFormat::BaseTextGenerator* generator) const override { |
1981 | generator->PrintString(str: delegate_->PrintMessageEnd( |
1982 | message, field_index, field_count, single_line_mode)); |
1983 | } |
1984 | |
1985 | private: |
1986 | std::unique_ptr<const TextFormat::FieldValuePrinter> delegate_; |
1987 | }; |
1988 | |
1989 | } // namespace |
1990 | |
1991 | const char* const TextFormat::Printer::kDoNotParse = |
1992 | "DO NOT PARSE: fields may be stripped and missing.\n" ; |
1993 | |
1994 | TextFormat::Printer::Printer() |
1995 | : initial_indent_level_(0), |
1996 | single_line_mode_(false), |
1997 | use_field_number_(false), |
1998 | use_short_repeated_primitives_(false), |
1999 | insert_silent_marker_(false), |
2000 | hide_unknown_fields_(false), |
2001 | print_message_fields_in_index_order_(false), |
2002 | expand_any_(false), |
2003 | truncate_string_field_longer_than_(0LL), |
2004 | finder_(nullptr) { |
2005 | SetUseUtf8StringEscaping(false); |
2006 | } |
2007 | |
2008 | void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { |
2009 | SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping() |
2010 | : new DebugStringFieldValuePrinter()); |
2011 | } |
2012 | |
2013 | void TextFormat::Printer::SetDefaultFieldValuePrinter( |
2014 | const FieldValuePrinter* printer) { |
2015 | default_field_value_printer_.reset(p: new FieldValuePrinterWrapper(printer)); |
2016 | } |
2017 | |
2018 | void TextFormat::Printer::SetDefaultFieldValuePrinter( |
2019 | const FastFieldValuePrinter* printer) { |
2020 | default_field_value_printer_.reset(p: printer); |
2021 | } |
2022 | |
2023 | bool TextFormat::Printer::RegisterFieldValuePrinter( |
2024 | const FieldDescriptor* field, const FieldValuePrinter* printer) { |
2025 | if (field == nullptr || printer == nullptr) { |
2026 | return false; |
2027 | } |
2028 | std::unique_ptr<FieldValuePrinterWrapper> wrapper( |
2029 | new FieldValuePrinterWrapper(nullptr)); |
2030 | auto pair = custom_printers_.insert(x: std::make_pair(x&: field, y: nullptr)); |
2031 | if (pair.second) { |
2032 | wrapper->SetDelegate(printer); |
2033 | pair.first->second = std::move(wrapper); |
2034 | return true; |
2035 | } else { |
2036 | return false; |
2037 | } |
2038 | } |
2039 | |
2040 | bool TextFormat::Printer::RegisterFieldValuePrinter( |
2041 | const FieldDescriptor* field, const FastFieldValuePrinter* printer) { |
2042 | if (field == nullptr || printer == nullptr) { |
2043 | return false; |
2044 | } |
2045 | auto pair = custom_printers_.insert(x: std::make_pair(x&: field, y: nullptr)); |
2046 | if (pair.second) { |
2047 | pair.first->second.reset(p: printer); |
2048 | return true; |
2049 | } else { |
2050 | return false; |
2051 | } |
2052 | } |
2053 | |
2054 | bool TextFormat::Printer::RegisterMessagePrinter( |
2055 | const Descriptor* descriptor, const MessagePrinter* printer) { |
2056 | if (descriptor == nullptr || printer == nullptr) { |
2057 | return false; |
2058 | } |
2059 | auto pair = |
2060 | custom_message_printers_.insert(x: std::make_pair(x&: descriptor, y: nullptr)); |
2061 | if (pair.second) { |
2062 | pair.first->second.reset(p: printer); |
2063 | return true; |
2064 | } else { |
2065 | return false; |
2066 | } |
2067 | } |
2068 | |
2069 | bool TextFormat::Printer::PrintToString(const Message& message, |
2070 | std::string* output) const { |
2071 | GOOGLE_DCHECK(output) << "output specified is nullptr" ; |
2072 | |
2073 | output->clear(); |
2074 | io::StringOutputStream output_stream(output); |
2075 | |
2076 | return Print(message, output: &output_stream); |
2077 | } |
2078 | |
2079 | bool TextFormat::Printer::PrintUnknownFieldsToString( |
2080 | const UnknownFieldSet& unknown_fields, std::string* output) const { |
2081 | GOOGLE_DCHECK(output) << "output specified is nullptr" ; |
2082 | |
2083 | output->clear(); |
2084 | io::StringOutputStream output_stream(output); |
2085 | return PrintUnknownFields(unknown_fields, output: &output_stream); |
2086 | } |
2087 | |
2088 | bool TextFormat::Printer::Print(const Message& message, |
2089 | io::ZeroCopyOutputStream* output) const { |
2090 | TextGenerator generator(output, insert_silent_marker_, initial_indent_level_); |
2091 | |
2092 | Print(message, generator: &generator); |
2093 | |
2094 | // Output false if the generator failed internally. |
2095 | return !generator.failed(); |
2096 | } |
2097 | |
2098 | // Maximum recursion depth for heuristically printing out length-delimited |
2099 | // unknown fields as messages. |
2100 | static constexpr int kUnknownFieldRecursionLimit = 10; |
2101 | |
2102 | bool TextFormat::Printer::PrintUnknownFields( |
2103 | const UnknownFieldSet& unknown_fields, |
2104 | io::ZeroCopyOutputStream* output) const { |
2105 | TextGenerator generator(output, initial_indent_level_); |
2106 | |
2107 | PrintUnknownFields(unknown_fields, generator: &generator, recursion_budget: kUnknownFieldRecursionLimit); |
2108 | |
2109 | // Output false if the generator failed internally. |
2110 | return !generator.failed(); |
2111 | } |
2112 | |
2113 | namespace { |
2114 | // Comparison functor for sorting FieldDescriptors by field index. |
2115 | // Normal fields have higher precedence than extensions. |
2116 | struct FieldIndexSorter { |
2117 | bool operator()(const FieldDescriptor* left, |
2118 | const FieldDescriptor* right) const { |
2119 | if (left->is_extension() && right->is_extension()) { |
2120 | return left->number() < right->number(); |
2121 | } else if (left->is_extension()) { |
2122 | return false; |
2123 | } else if (right->is_extension()) { |
2124 | return true; |
2125 | } else { |
2126 | return left->index() < right->index(); |
2127 | } |
2128 | } |
2129 | }; |
2130 | |
2131 | } // namespace |
2132 | |
2133 | bool TextFormat::Printer::PrintAny(const Message& message, |
2134 | TextGenerator* generator) const { |
2135 | const FieldDescriptor* type_url_field; |
2136 | const FieldDescriptor* value_field; |
2137 | if (!internal::GetAnyFieldDescriptors(message, type_url_field: &type_url_field, |
2138 | value_field: &value_field)) { |
2139 | return false; |
2140 | } |
2141 | |
2142 | const Reflection* reflection = message.GetReflection(); |
2143 | |
2144 | // Extract the full type name from the type_url field. |
2145 | const std::string& type_url = reflection->GetString(message, field: type_url_field); |
2146 | std::string url_prefix; |
2147 | std::string full_type_name; |
2148 | if (!internal::ParseAnyTypeUrl(type_url, url_prefix: &url_prefix, full_type_name: &full_type_name)) { |
2149 | return false; |
2150 | } |
2151 | |
2152 | // Print the "value" in text. |
2153 | const Descriptor* value_descriptor = |
2154 | finder_ ? finder_->FindAnyType(message, prefix: url_prefix, name: full_type_name) |
2155 | : DefaultFinderFindAnyType(message, prefix: url_prefix, name: full_type_name); |
2156 | if (value_descriptor == nullptr) { |
2157 | GOOGLE_LOG(WARNING) << "Can't print proto content: proto type " << type_url |
2158 | << " not found" ; |
2159 | return false; |
2160 | } |
2161 | DynamicMessageFactory factory; |
2162 | std::unique_ptr<Message> value_message( |
2163 | factory.GetPrototype(type: value_descriptor)->New()); |
2164 | std::string serialized_value = reflection->GetString(message, field: value_field); |
2165 | if (!value_message->ParseFromString(data: serialized_value)) { |
2166 | GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents" ; |
2167 | return false; |
2168 | } |
2169 | generator->PrintLiteral(text: "[" ); |
2170 | generator->PrintString(str: type_url); |
2171 | generator->PrintLiteral(text: "]" ); |
2172 | const FastFieldValuePrinter* printer = GetFieldPrinter(field: value_field); |
2173 | printer->PrintMessageStart(message, -1, 0, single_line_mode: single_line_mode_, generator); |
2174 | generator->Indent(); |
2175 | Print(message: *value_message, generator); |
2176 | generator->Outdent(); |
2177 | printer->PrintMessageEnd(message, -1, 0, single_line_mode: single_line_mode_, generator); |
2178 | return true; |
2179 | } |
2180 | |
2181 | void TextFormat::Printer::Print(const Message& message, |
2182 | TextGenerator* generator) const { |
2183 | const Reflection* reflection = message.GetReflection(); |
2184 | if (!reflection) { |
2185 | // This message does not provide any way to describe its structure. |
2186 | // Parse it again in an UnknownFieldSet, and display this instead. |
2187 | UnknownFieldSet unknown_fields; |
2188 | { |
2189 | std::string serialized = message.SerializeAsString(); |
2190 | io::ArrayInputStream input(serialized.data(), serialized.size()); |
2191 | unknown_fields.ParseFromZeroCopyStream(input: &input); |
2192 | } |
2193 | PrintUnknownFields(unknown_fields, generator, recursion_budget: kUnknownFieldRecursionLimit); |
2194 | return; |
2195 | } |
2196 | const Descriptor* descriptor = message.GetDescriptor(); |
2197 | auto itr = custom_message_printers_.find(x: descriptor); |
2198 | if (itr != custom_message_printers_.end()) { |
2199 | itr->second->Print(message, single_line_mode: single_line_mode_, generator); |
2200 | return; |
2201 | } |
2202 | if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ && |
2203 | PrintAny(message, generator)) { |
2204 | return; |
2205 | } |
2206 | std::vector<const FieldDescriptor*> fields; |
2207 | if (descriptor->options().map_entry()) { |
2208 | fields.push_back(x: descriptor->field(index: 0)); |
2209 | fields.push_back(x: descriptor->field(index: 1)); |
2210 | } else { |
2211 | reflection->ListFieldsOmitStripped(message, output: &fields); |
2212 | if (reflection->IsMessageStripped(descriptor: message.GetDescriptor())) { |
2213 | generator->Print(text: kDoNotParse, size: std::strlen(s: kDoNotParse)); |
2214 | } |
2215 | } |
2216 | |
2217 | if (print_message_fields_in_index_order_) { |
2218 | std::sort(first: fields.begin(), last: fields.end(), comp: FieldIndexSorter()); |
2219 | } |
2220 | for (const FieldDescriptor* field : fields) { |
2221 | PrintField(message, reflection, field, generator); |
2222 | } |
2223 | if (!hide_unknown_fields_) { |
2224 | PrintUnknownFields(unknown_fields: reflection->GetUnknownFields(message), generator, |
2225 | recursion_budget: kUnknownFieldRecursionLimit); |
2226 | } |
2227 | } |
2228 | |
2229 | void TextFormat::Printer::PrintFieldValueToString(const Message& message, |
2230 | const FieldDescriptor* field, |
2231 | int index, |
2232 | std::string* output) const { |
2233 | GOOGLE_DCHECK(output) << "output specified is nullptr" ; |
2234 | |
2235 | output->clear(); |
2236 | io::StringOutputStream output_stream(output); |
2237 | TextGenerator generator(&output_stream, initial_indent_level_); |
2238 | |
2239 | PrintFieldValue(message, reflection: message.GetReflection(), field, index, generator: &generator); |
2240 | } |
2241 | |
2242 | class MapEntryMessageComparator { |
2243 | public: |
2244 | explicit MapEntryMessageComparator(const Descriptor* descriptor) |
2245 | : field_(descriptor->field(index: 0)) {} |
2246 | |
2247 | bool operator()(const Message* a, const Message* b) { |
2248 | const Reflection* reflection = a->GetReflection(); |
2249 | switch (field_->cpp_type()) { |
2250 | case FieldDescriptor::CPPTYPE_BOOL: { |
2251 | bool first = reflection->GetBool(message: *a, field: field_); |
2252 | bool second = reflection->GetBool(message: *b, field: field_); |
2253 | return first < second; |
2254 | } |
2255 | case FieldDescriptor::CPPTYPE_INT32: { |
2256 | int32_t first = reflection->GetInt32(message: *a, field: field_); |
2257 | int32_t second = reflection->GetInt32(message: *b, field: field_); |
2258 | return first < second; |
2259 | } |
2260 | case FieldDescriptor::CPPTYPE_INT64: { |
2261 | int64_t first = reflection->GetInt64(message: *a, field: field_); |
2262 | int64_t second = reflection->GetInt64(message: *b, field: field_); |
2263 | return first < second; |
2264 | } |
2265 | case FieldDescriptor::CPPTYPE_UINT32: { |
2266 | uint32_t first = reflection->GetUInt32(message: *a, field: field_); |
2267 | uint32_t second = reflection->GetUInt32(message: *b, field: field_); |
2268 | return first < second; |
2269 | } |
2270 | case FieldDescriptor::CPPTYPE_UINT64: { |
2271 | uint64_t first = reflection->GetUInt64(message: *a, field: field_); |
2272 | uint64_t second = reflection->GetUInt64(message: *b, field: field_); |
2273 | return first < second; |
2274 | } |
2275 | case FieldDescriptor::CPPTYPE_STRING: { |
2276 | std::string first = reflection->GetString(message: *a, field: field_); |
2277 | std::string second = reflection->GetString(message: *b, field: field_); |
2278 | return first < second; |
2279 | } |
2280 | default: |
2281 | GOOGLE_LOG(DFATAL) << "Invalid key for map field." ; |
2282 | return true; |
2283 | } |
2284 | } |
2285 | |
2286 | private: |
2287 | const FieldDescriptor* field_; |
2288 | }; |
2289 | |
2290 | namespace internal { |
2291 | class MapFieldPrinterHelper { |
2292 | public: |
2293 | // DynamicMapSorter::Sort cannot be used because it enfores syncing with |
2294 | // repeated field. |
2295 | static bool SortMap(const Message& message, const Reflection* reflection, |
2296 | const FieldDescriptor* field, |
2297 | std::vector<const Message*>* sorted_map_field); |
2298 | static void CopyKey(const MapKey& key, Message* message, |
2299 | const FieldDescriptor* field_desc); |
2300 | static void CopyValue(const MapValueRef& value, Message* message, |
2301 | const FieldDescriptor* field_desc); |
2302 | }; |
2303 | |
2304 | // Returns true if elements contained in sorted_map_field need to be released. |
2305 | bool MapFieldPrinterHelper::SortMap( |
2306 | const Message& message, const Reflection* reflection, |
2307 | const FieldDescriptor* field, |
2308 | std::vector<const Message*>* sorted_map_field) { |
2309 | bool need_release = false; |
2310 | const MapFieldBase& base = *reflection->GetMapData(message, field); |
2311 | |
2312 | if (base.IsRepeatedFieldValid()) { |
2313 | const RepeatedPtrField<Message>& map_field = |
2314 | reflection->GetRepeatedPtrFieldInternal<Message>(message, field); |
2315 | for (int i = 0; i < map_field.size(); ++i) { |
2316 | sorted_map_field->push_back( |
2317 | x: const_cast<RepeatedPtrField<Message>*>(&map_field)->Mutable(index: i)); |
2318 | } |
2319 | } else { |
2320 | // TODO(teboring): For performance, instead of creating map entry message |
2321 | // for each element, just store map keys and sort them. |
2322 | const Descriptor* map_entry_desc = field->message_type(); |
2323 | const Message* prototype = |
2324 | reflection->GetMessageFactory()->GetPrototype(type: map_entry_desc); |
2325 | for (MapIterator iter = |
2326 | reflection->MapBegin(message: const_cast<Message*>(&message), field); |
2327 | iter != reflection->MapEnd(message: const_cast<Message*>(&message), field); |
2328 | ++iter) { |
2329 | Message* map_entry_message = prototype->New(); |
2330 | CopyKey(key: iter.GetKey(), message: map_entry_message, field_desc: map_entry_desc->field(index: 0)); |
2331 | CopyValue(value: iter.GetValueRef(), message: map_entry_message, |
2332 | field_desc: map_entry_desc->field(index: 1)); |
2333 | sorted_map_field->push_back(x: map_entry_message); |
2334 | } |
2335 | need_release = true; |
2336 | } |
2337 | |
2338 | MapEntryMessageComparator comparator(field->message_type()); |
2339 | std::stable_sort(first: sorted_map_field->begin(), last: sorted_map_field->end(), |
2340 | comp: comparator); |
2341 | return need_release; |
2342 | } |
2343 | |
2344 | void MapFieldPrinterHelper::CopyKey(const MapKey& key, Message* message, |
2345 | const FieldDescriptor* field_desc) { |
2346 | const Reflection* reflection = message->GetReflection(); |
2347 | switch (field_desc->cpp_type()) { |
2348 | case FieldDescriptor::CPPTYPE_DOUBLE: |
2349 | case FieldDescriptor::CPPTYPE_FLOAT: |
2350 | case FieldDescriptor::CPPTYPE_ENUM: |
2351 | case FieldDescriptor::CPPTYPE_MESSAGE: |
2352 | GOOGLE_LOG(ERROR) << "Not supported." ; |
2353 | break; |
2354 | case FieldDescriptor::CPPTYPE_STRING: |
2355 | reflection->SetString(message, field: field_desc, value: key.GetStringValue()); |
2356 | return; |
2357 | case FieldDescriptor::CPPTYPE_INT64: |
2358 | reflection->SetInt64(message, field: field_desc, value: key.GetInt64Value()); |
2359 | return; |
2360 | case FieldDescriptor::CPPTYPE_INT32: |
2361 | reflection->SetInt32(message, field: field_desc, value: key.GetInt32Value()); |
2362 | return; |
2363 | case FieldDescriptor::CPPTYPE_UINT64: |
2364 | reflection->SetUInt64(message, field: field_desc, value: key.GetUInt64Value()); |
2365 | return; |
2366 | case FieldDescriptor::CPPTYPE_UINT32: |
2367 | reflection->SetUInt32(message, field: field_desc, value: key.GetUInt32Value()); |
2368 | return; |
2369 | case FieldDescriptor::CPPTYPE_BOOL: |
2370 | reflection->SetBool(message, field: field_desc, value: key.GetBoolValue()); |
2371 | return; |
2372 | } |
2373 | } |
2374 | |
2375 | void MapFieldPrinterHelper::CopyValue(const MapValueRef& value, |
2376 | Message* message, |
2377 | const FieldDescriptor* field_desc) { |
2378 | const Reflection* reflection = message->GetReflection(); |
2379 | switch (field_desc->cpp_type()) { |
2380 | case FieldDescriptor::CPPTYPE_DOUBLE: |
2381 | reflection->SetDouble(message, field: field_desc, value: value.GetDoubleValue()); |
2382 | return; |
2383 | case FieldDescriptor::CPPTYPE_FLOAT: |
2384 | reflection->SetFloat(message, field: field_desc, value: value.GetFloatValue()); |
2385 | return; |
2386 | case FieldDescriptor::CPPTYPE_ENUM: |
2387 | reflection->SetEnumValue(message, field: field_desc, value: value.GetEnumValue()); |
2388 | return; |
2389 | case FieldDescriptor::CPPTYPE_MESSAGE: { |
2390 | Message* sub_message = value.GetMessageValue().New(); |
2391 | sub_message->CopyFrom(from: value.GetMessageValue()); |
2392 | reflection->SetAllocatedMessage(message, sub_message, field: field_desc); |
2393 | return; |
2394 | } |
2395 | case FieldDescriptor::CPPTYPE_STRING: |
2396 | reflection->SetString(message, field: field_desc, value: value.GetStringValue()); |
2397 | return; |
2398 | case FieldDescriptor::CPPTYPE_INT64: |
2399 | reflection->SetInt64(message, field: field_desc, value: value.GetInt64Value()); |
2400 | return; |
2401 | case FieldDescriptor::CPPTYPE_INT32: |
2402 | reflection->SetInt32(message, field: field_desc, value: value.GetInt32Value()); |
2403 | return; |
2404 | case FieldDescriptor::CPPTYPE_UINT64: |
2405 | reflection->SetUInt64(message, field: field_desc, value: value.GetUInt64Value()); |
2406 | return; |
2407 | case FieldDescriptor::CPPTYPE_UINT32: |
2408 | reflection->SetUInt32(message, field: field_desc, value: value.GetUInt32Value()); |
2409 | return; |
2410 | case FieldDescriptor::CPPTYPE_BOOL: |
2411 | reflection->SetBool(message, field: field_desc, value: value.GetBoolValue()); |
2412 | return; |
2413 | } |
2414 | } |
2415 | } // namespace internal |
2416 | |
2417 | void TextFormat::Printer::PrintField(const Message& message, |
2418 | const Reflection* reflection, |
2419 | const FieldDescriptor* field, |
2420 | TextGenerator* generator) const { |
2421 | if (use_short_repeated_primitives_ && field->is_repeated() && |
2422 | field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && |
2423 | field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
2424 | PrintShortRepeatedField(message, reflection, field, generator); |
2425 | return; |
2426 | } |
2427 | |
2428 | int count = 0; |
2429 | |
2430 | if (field->is_repeated()) { |
2431 | count = reflection->FieldSize(message, field); |
2432 | } else if (reflection->HasField(message, field) || |
2433 | field->containing_type()->options().map_entry()) { |
2434 | count = 1; |
2435 | } |
2436 | |
2437 | std::vector<const Message*> sorted_map_field; |
2438 | bool need_release = false; |
2439 | bool is_map = field->is_map(); |
2440 | if (is_map) { |
2441 | need_release = internal::MapFieldPrinterHelper::SortMap( |
2442 | message, reflection, field, sorted_map_field: &sorted_map_field); |
2443 | } |
2444 | |
2445 | for (int j = 0; j < count; ++j) { |
2446 | const int field_index = field->is_repeated() ? j : -1; |
2447 | |
2448 | PrintFieldName(message, field_index, field_count: count, reflection, field, generator); |
2449 | |
2450 | if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
2451 | const FastFieldValuePrinter* printer = GetFieldPrinter(field); |
2452 | const Message& sub_message = |
2453 | field->is_repeated() |
2454 | ? (is_map ? *sorted_map_field[j] |
2455 | : reflection->GetRepeatedMessage(message, field, index: j)) |
2456 | : reflection->GetMessage(message, field); |
2457 | printer->PrintMessageStart(sub_message, field_index, count, |
2458 | single_line_mode: single_line_mode_, generator); |
2459 | generator->Indent(); |
2460 | if (!printer->PrintMessageContent(sub_message, field_index, count, |
2461 | single_line_mode_, generator)) { |
2462 | Print(message: sub_message, generator); |
2463 | } |
2464 | generator->Outdent(); |
2465 | printer->PrintMessageEnd(sub_message, field_index, count, |
2466 | single_line_mode: single_line_mode_, generator); |
2467 | } else { |
2468 | generator->PrintMaybeWithMarker(text: ": " ); |
2469 | // Write the field value. |
2470 | PrintFieldValue(message, reflection, field, index: field_index, generator); |
2471 | if (single_line_mode_) { |
2472 | generator->PrintLiteral(text: " " ); |
2473 | } else { |
2474 | generator->PrintLiteral(text: "\n" ); |
2475 | } |
2476 | } |
2477 | } |
2478 | |
2479 | if (need_release) { |
2480 | for (const Message* message_to_delete : sorted_map_field) { |
2481 | delete message_to_delete; |
2482 | } |
2483 | } |
2484 | } |
2485 | |
2486 | void TextFormat::Printer::PrintShortRepeatedField( |
2487 | const Message& message, const Reflection* reflection, |
2488 | const FieldDescriptor* field, TextGenerator* generator) const { |
2489 | // Print primitive repeated field in short form. |
2490 | int size = reflection->FieldSize(message, field); |
2491 | PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection, |
2492 | field, generator); |
2493 | generator->PrintMaybeWithMarker(text_head: ": " , text_tail: "[" ); |
2494 | for (int i = 0; i < size; i++) { |
2495 | if (i > 0) generator->PrintLiteral(text: ", " ); |
2496 | PrintFieldValue(message, reflection, field, index: i, generator); |
2497 | } |
2498 | if (single_line_mode_) { |
2499 | generator->PrintLiteral(text: "] " ); |
2500 | } else { |
2501 | generator->PrintLiteral(text: "]\n" ); |
2502 | } |
2503 | } |
2504 | |
2505 | void TextFormat::Printer::PrintFieldName(const Message& message, |
2506 | int field_index, int field_count, |
2507 | const Reflection* reflection, |
2508 | const FieldDescriptor* field, |
2509 | TextGenerator* generator) const { |
2510 | // if use_field_number_ is true, prints field number instead |
2511 | // of field name. |
2512 | if (use_field_number_) { |
2513 | generator->PrintString(str: StrCat(a: field->number())); |
2514 | return; |
2515 | } |
2516 | |
2517 | const FastFieldValuePrinter* printer = GetFieldPrinter(field); |
2518 | printer->PrintFieldName(message, field_index, field_count, reflection, field, |
2519 | generator); |
2520 | } |
2521 | |
2522 | void TextFormat::Printer::PrintFieldValue(const Message& message, |
2523 | const Reflection* reflection, |
2524 | const FieldDescriptor* field, |
2525 | int index, |
2526 | TextGenerator* generator) const { |
2527 | GOOGLE_DCHECK(field->is_repeated() || (index == -1)) |
2528 | << "Index must be -1 for non-repeated fields" ; |
2529 | |
2530 | const FastFieldValuePrinter* printer = GetFieldPrinter(field); |
2531 | |
2532 | switch (field->cpp_type()) { |
2533 | #define OUTPUT_FIELD(CPPTYPE, METHOD) \ |
2534 | case FieldDescriptor::CPPTYPE_##CPPTYPE: \ |
2535 | printer->Print##METHOD( \ |
2536 | field->is_repeated() \ |
2537 | ? reflection->GetRepeated##METHOD(message, field, index) \ |
2538 | : reflection->Get##METHOD(message, field), \ |
2539 | generator); \ |
2540 | break |
2541 | |
2542 | OUTPUT_FIELD(INT32, Int32); |
2543 | OUTPUT_FIELD(INT64, Int64); |
2544 | OUTPUT_FIELD(UINT32, UInt32); |
2545 | OUTPUT_FIELD(UINT64, UInt64); |
2546 | OUTPUT_FIELD(FLOAT, Float); |
2547 | OUTPUT_FIELD(DOUBLE, Double); |
2548 | OUTPUT_FIELD(BOOL, Bool); |
2549 | #undef OUTPUT_FIELD |
2550 | |
2551 | case FieldDescriptor::CPPTYPE_STRING: { |
2552 | std::string scratch; |
2553 | const std::string& value = |
2554 | field->is_repeated() |
2555 | ? reflection->GetRepeatedStringReference(message, field, index, |
2556 | scratch: &scratch) |
2557 | : reflection->GetStringReference(message, field, scratch: &scratch); |
2558 | const std::string* value_to_print = &value; |
2559 | std::string truncated_value; |
2560 | if (truncate_string_field_longer_than_ > 0 && |
2561 | static_cast<size_t>(truncate_string_field_longer_than_) < |
2562 | value.size()) { |
2563 | truncated_value = value.substr(pos: 0, n: truncate_string_field_longer_than_) + |
2564 | "...<truncated>..." ; |
2565 | value_to_print = &truncated_value; |
2566 | } |
2567 | if (field->type() == FieldDescriptor::TYPE_STRING) { |
2568 | printer->PrintString(val: *value_to_print, generator); |
2569 | } else { |
2570 | GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES); |
2571 | printer->PrintBytes(val: *value_to_print, generator); |
2572 | } |
2573 | break; |
2574 | } |
2575 | |
2576 | case FieldDescriptor::CPPTYPE_ENUM: { |
2577 | int enum_value = |
2578 | field->is_repeated() |
2579 | ? reflection->GetRepeatedEnumValue(message, field, index) |
2580 | : reflection->GetEnumValue(message, field); |
2581 | const EnumValueDescriptor* enum_desc = |
2582 | field->enum_type()->FindValueByNumber(number: enum_value); |
2583 | if (enum_desc != nullptr) { |
2584 | printer->PrintEnum(enum_value, name: enum_desc->name(), generator); |
2585 | } else { |
2586 | // Ordinarily, enum_desc should not be null, because proto2 has the |
2587 | // invariant that set enum field values must be in-range, but with the |
2588 | // new integer-based API for enums (or the RepeatedField<int> loophole), |
2589 | // it is possible for the user to force an unknown integer value. So we |
2590 | // simply use the integer value itself as the enum value name in this |
2591 | // case. |
2592 | printer->PrintEnum(enum_value, name: StrCat(a: enum_value), generator); |
2593 | } |
2594 | break; |
2595 | } |
2596 | |
2597 | case FieldDescriptor::CPPTYPE_MESSAGE: |
2598 | Print(message: field->is_repeated() |
2599 | ? reflection->GetRepeatedMessage(message, field, index) |
2600 | : reflection->GetMessage(message, field), |
2601 | generator); |
2602 | break; |
2603 | } |
2604 | } |
2605 | |
2606 | /* static */ bool TextFormat::Print(const Message& message, |
2607 | io::ZeroCopyOutputStream* output) { |
2608 | return Printer().Print(message, output); |
2609 | } |
2610 | |
2611 | /* static */ bool TextFormat::PrintUnknownFields( |
2612 | const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output) { |
2613 | return Printer().PrintUnknownFields(unknown_fields, output); |
2614 | } |
2615 | |
2616 | /* static */ bool TextFormat::PrintToString(const Message& message, |
2617 | std::string* output) { |
2618 | return Printer().PrintToString(message, output); |
2619 | } |
2620 | |
2621 | /* static */ bool TextFormat::PrintUnknownFieldsToString( |
2622 | const UnknownFieldSet& unknown_fields, std::string* output) { |
2623 | return Printer().PrintUnknownFieldsToString(unknown_fields, output); |
2624 | } |
2625 | |
2626 | /* static */ void TextFormat::PrintFieldValueToString( |
2627 | const Message& message, const FieldDescriptor* field, int index, |
2628 | std::string* output) { |
2629 | return Printer().PrintFieldValueToString(message, field, index, output); |
2630 | } |
2631 | |
2632 | /* static */ bool TextFormat::ParseFieldValueFromString( |
2633 | const std::string& input, const FieldDescriptor* field, Message* message) { |
2634 | return Parser().ParseFieldValueFromString(input, field, output: message); |
2635 | } |
2636 | |
2637 | void TextFormat::Printer::PrintUnknownFields( |
2638 | const UnknownFieldSet& unknown_fields, TextGenerator* generator, |
2639 | int recursion_budget) const { |
2640 | for (int i = 0; i < unknown_fields.field_count(); i++) { |
2641 | const UnknownField& field = unknown_fields.field(index: i); |
2642 | std::string field_number = StrCat(a: field.number()); |
2643 | |
2644 | switch (field.type()) { |
2645 | case UnknownField::TYPE_VARINT: |
2646 | generator->PrintString(str: field_number); |
2647 | generator->PrintMaybeWithMarker(text: ": " ); |
2648 | generator->PrintString(str: StrCat(a: field.varint())); |
2649 | if (single_line_mode_) { |
2650 | generator->PrintLiteral(text: " " ); |
2651 | } else { |
2652 | generator->PrintLiteral(text: "\n" ); |
2653 | } |
2654 | break; |
2655 | case UnknownField::TYPE_FIXED32: { |
2656 | generator->PrintString(str: field_number); |
2657 | generator->PrintMaybeWithMarker(text_head: ": " , text_tail: "0x" ); |
2658 | generator->PrintString( |
2659 | str: StrCat(a: strings::Hex(field.fixed32(), strings::ZERO_PAD_8))); |
2660 | if (single_line_mode_) { |
2661 | generator->PrintLiteral(text: " " ); |
2662 | } else { |
2663 | generator->PrintLiteral(text: "\n" ); |
2664 | } |
2665 | break; |
2666 | } |
2667 | case UnknownField::TYPE_FIXED64: { |
2668 | generator->PrintString(str: field_number); |
2669 | generator->PrintMaybeWithMarker(text_head: ": " , text_tail: "0x" ); |
2670 | generator->PrintString( |
2671 | str: StrCat(a: strings::Hex(field.fixed64(), strings::ZERO_PAD_16))); |
2672 | if (single_line_mode_) { |
2673 | generator->PrintLiteral(text: " " ); |
2674 | } else { |
2675 | generator->PrintLiteral(text: "\n" ); |
2676 | } |
2677 | break; |
2678 | } |
2679 | case UnknownField::TYPE_LENGTH_DELIMITED: { |
2680 | generator->PrintString(str: field_number); |
2681 | const std::string& value = field.length_delimited(); |
2682 | // We create a CodedInputStream so that we can adhere to our recursion |
2683 | // budget when we attempt to parse the data. UnknownFieldSet parsing is |
2684 | // recursive because of groups. |
2685 | io::CodedInputStream input_stream( |
2686 | reinterpret_cast<const uint8_t*>(value.data()), value.size()); |
2687 | input_stream.SetRecursionLimit(recursion_budget); |
2688 | UnknownFieldSet embedded_unknown_fields; |
2689 | if (!value.empty() && recursion_budget > 0 && |
2690 | embedded_unknown_fields.ParseFromCodedStream(input: &input_stream)) { |
2691 | // This field is parseable as a Message. |
2692 | // So it is probably an embedded message. |
2693 | if (single_line_mode_) { |
2694 | generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{ " ); |
2695 | } else { |
2696 | generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{\n" ); |
2697 | generator->Indent(); |
2698 | } |
2699 | PrintUnknownFields(unknown_fields: embedded_unknown_fields, generator, |
2700 | recursion_budget: recursion_budget - 1); |
2701 | if (single_line_mode_) { |
2702 | generator->PrintLiteral(text: "} " ); |
2703 | } else { |
2704 | generator->Outdent(); |
2705 | generator->PrintLiteral(text: "}\n" ); |
2706 | } |
2707 | } else { |
2708 | // This field is not parseable as a Message (or we ran out of |
2709 | // recursion budget). So it is probably just a plain string. |
2710 | generator->PrintMaybeWithMarker(text_head: ": " , text_tail: "\"" ); |
2711 | generator->PrintString(str: CEscape(src: value)); |
2712 | if (single_line_mode_) { |
2713 | generator->PrintLiteral(text: "\" " ); |
2714 | } else { |
2715 | generator->PrintLiteral(text: "\"\n" ); |
2716 | } |
2717 | } |
2718 | break; |
2719 | } |
2720 | case UnknownField::TYPE_GROUP: |
2721 | generator->PrintString(str: field_number); |
2722 | if (single_line_mode_) { |
2723 | generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{ " ); |
2724 | } else { |
2725 | generator->PrintMaybeWithMarker(text_head: " " , text_tail: "{\n" ); |
2726 | generator->Indent(); |
2727 | } |
2728 | // For groups, we recurse without checking the budget. This is OK, |
2729 | // because if the groups were too deeply nested then we would have |
2730 | // already rejected the message when we originally parsed it. |
2731 | PrintUnknownFields(unknown_fields: field.group(), generator, recursion_budget: recursion_budget - 1); |
2732 | if (single_line_mode_) { |
2733 | generator->PrintLiteral(text: "} " ); |
2734 | } else { |
2735 | generator->Outdent(); |
2736 | generator->PrintLiteral(text: "}\n" ); |
2737 | } |
2738 | break; |
2739 | } |
2740 | } |
2741 | } |
2742 | |
2743 | } // namespace protobuf |
2744 | } // namespace google |
2745 | |
2746 | #include <google/protobuf/port_undef.inc> |
2747 | |