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: [email protected] (Joseph Schorr)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// Utilities for printing and parsing protocol messages in a human-readable,
36// text-based format.
37
38#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
39#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
40
41#include <map>
42#include <memory>
43#include <string>
44#include <vector>
45
46#include <google/protobuf/stubs/common.h>
47#include <google/protobuf/descriptor.h>
48#include <google/protobuf/message.h>
49#include <google/protobuf/message_lite.h>
50#include <google/protobuf/port.h>
51
52#include <google/protobuf/port_def.inc>
53
54#ifdef SWIG
55#error "You cannot SWIG proto headers"
56#endif
57
58namespace google {
59namespace protobuf {
60
61namespace io {
62class ErrorCollector; // tokenizer.h
63}
64
65// This class implements protocol buffer text format. Printing and parsing
66// protocol messages in text format is useful for debugging and human editing
67// of messages.
68//
69// This class is really a namespace that contains only static methods.
70class PROTOBUF_EXPORT TextFormat {
71 public:
72 // Outputs a textual representation of the given message to the given
73 // output stream. Returns false if printing fails.
74 static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
75
76 // Print the fields in an UnknownFieldSet. They are printed by tag number
77 // only. Embedded messages are heuristically identified by attempting to
78 // parse them. Returns false if printing fails.
79 static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
80 io::ZeroCopyOutputStream* output);
81
82 // Like Print(), but outputs directly to a string.
83 // Note: output will be cleared prior to printing, and will be left empty
84 // even if printing fails. Returns false if printing fails.
85 static bool PrintToString(const Message& message, std::string* output);
86
87 // Like PrintUnknownFields(), but outputs directly to a string. Returns
88 // false if printing fails.
89 static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
90 std::string* output);
91
92 // Outputs a textual representation of the value of the field supplied on
93 // the message supplied. For non-repeated fields, an index of -1 must
94 // be supplied. Note that this method will print the default value for a
95 // field if it is not set.
96 static void PrintFieldValueToString(const Message& message,
97 const FieldDescriptor* field, int index,
98 std::string* output);
99
100 class PROTOBUF_EXPORT BaseTextGenerator {
101 public:
102 virtual ~BaseTextGenerator();
103
104 virtual void Indent() {}
105 virtual void Outdent() {}
106
107 // Print text to the output stream.
108 virtual void Print(const char* text, size_t size) = 0;
109
110 void PrintString(const std::string& str) { Print(str.data(), str.size()); }
111
112 template <size_t n>
113 void PrintLiteral(const char (&text)[n]) {
114 Print(text, n - 1); // n includes the terminating zero character.
115 }
116 };
117
118 // The default printer that converts scalar values from fields into their
119 // string representation.
120 // You can derive from this FastFieldValuePrinter if you want to have fields
121 // to be printed in a different way and register it at the Printer.
122 class PROTOBUF_EXPORT FastFieldValuePrinter {
123 public:
124 FastFieldValuePrinter();
125 virtual ~FastFieldValuePrinter();
126 virtual void PrintBool(bool val, BaseTextGenerator* generator) const;
127 virtual void PrintInt32(int32 val, BaseTextGenerator* generator) const;
128 virtual void PrintUInt32(uint32 val, BaseTextGenerator* generator) const;
129 virtual void PrintInt64(int64 val, BaseTextGenerator* generator) const;
130 virtual void PrintUInt64(uint64 val, BaseTextGenerator* generator) const;
131 virtual void PrintFloat(float val, BaseTextGenerator* generator) const;
132 virtual void PrintDouble(double val, BaseTextGenerator* generator) const;
133 virtual void PrintString(const std::string& val,
134 BaseTextGenerator* generator) const;
135 virtual void PrintBytes(const std::string& val,
136 BaseTextGenerator* generator) const;
137 virtual void PrintEnum(int32 val, const std::string& name,
138 BaseTextGenerator* generator) const;
139 virtual void PrintFieldName(const Message& message, int field_index,
140 int field_count, const Reflection* reflection,
141 const FieldDescriptor* field,
142 BaseTextGenerator* generator) const;
143 virtual void PrintFieldName(const Message& message,
144 const Reflection* reflection,
145 const FieldDescriptor* field,
146 BaseTextGenerator* generator) const;
147 virtual void PrintMessageStart(const Message& message, int field_index,
148 int field_count, bool single_line_mode,
149 BaseTextGenerator* generator) const;
150 virtual void PrintMessageEnd(const Message& message, int field_index,
151 int field_count, bool single_line_mode,
152 BaseTextGenerator* generator) const;
153
154 private:
155 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter);
156 };
157
158 class PROTOBUF_EXPORT PROTOBUF_DEPRECATED_MSG(
159 "Please use FastFieldValuePrinter") FieldValuePrinter {
160 public:
161 FieldValuePrinter();
162 virtual ~FieldValuePrinter();
163 virtual std::string PrintBool(bool val) const;
164 virtual std::string PrintInt32(int32 val) const;
165 virtual std::string PrintUInt32(uint32 val) const;
166 virtual std::string PrintInt64(int64 val) const;
167 virtual std::string PrintUInt64(uint64 val) const;
168 virtual std::string PrintFloat(float val) const;
169 virtual std::string PrintDouble(double val) const;
170 virtual std::string PrintString(const std::string& val) const;
171 virtual std::string PrintBytes(const std::string& val) const;
172 virtual std::string PrintEnum(int32 val, const std::string& name) const;
173 virtual std::string PrintFieldName(const Message& message,
174 const Reflection* reflection,
175 const FieldDescriptor* field) const;
176 virtual std::string PrintMessageStart(const Message& message,
177 int field_index, int field_count,
178 bool single_line_mode) const;
179 virtual std::string PrintMessageEnd(const Message& message, int field_index,
180 int field_count,
181 bool single_line_mode) const;
182
183 private:
184 FastFieldValuePrinter delegate_;
185 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
186 };
187
188 class PROTOBUF_EXPORT MessagePrinter {
189 public:
190 MessagePrinter() {}
191 virtual ~MessagePrinter() {}
192 virtual void Print(const Message& message, bool single_line_mode,
193 BaseTextGenerator* generator) const = 0;
194
195 private:
196 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter);
197 };
198
199 // Interface that Printers or Parsers can use to find extensions, or types
200 // referenced in Any messages.
201 class PROTOBUF_EXPORT Finder {
202 public:
203 virtual ~Finder();
204
205 // Try to find an extension of *message by fully-qualified field
206 // name. Returns NULL if no extension is known for this name or number.
207 // The base implementation uses the extensions already known by the message.
208 virtual const FieldDescriptor* FindExtension(Message* message,
209 const std::string& name) const;
210
211 // Similar to FindExtension, but uses a Descriptor and the extension number
212 // instead of using a Message and the name when doing the look up.
213 virtual const FieldDescriptor* FindExtensionByNumber(
214 const Descriptor* descriptor, int number) const;
215
216 // Find the message type for an Any proto.
217 // Returns NULL if no message is known for this name.
218 // The base implementation only accepts prefixes of type.googleprod.com/ or
219 // type.googleapis.com/, and searches the DescriptorPool of the parent
220 // message.
221 virtual const Descriptor* FindAnyType(const Message& message,
222 const std::string& prefix,
223 const std::string& name) const;
224
225 // Find the message factory for the given extension field. This can be used
226 // to generalize the Parser to add extension fields to a message in the same
227 // way as the "input" message for the Parser.
228 virtual MessageFactory* FindExtensionFactory(
229 const FieldDescriptor* field) const;
230 };
231
232 // Class for those users which require more fine-grained control over how
233 // a protobuffer message is printed out.
234 class PROTOBUF_EXPORT Printer {
235 public:
236 Printer();
237 ~Printer();
238
239 // Like TextFormat::Print
240 bool Print(const Message& message, io::ZeroCopyOutputStream* output) const;
241 // Like TextFormat::PrintUnknownFields
242 bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
243 io::ZeroCopyOutputStream* output) const;
244 // Like TextFormat::PrintToString
245 bool PrintToString(const Message& message, std::string* output) const;
246 // Like TextFormat::PrintUnknownFieldsToString
247 bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
248 std::string* output) const;
249 // Like TextFormat::PrintFieldValueToString
250 void PrintFieldValueToString(const Message& message,
251 const FieldDescriptor* field, int index,
252 std::string* output) const;
253
254 // Adjust the initial indent level of all output. Each indent level is
255 // equal to two spaces.
256 void SetInitialIndentLevel(int indent_level) {
257 initial_indent_level_ = indent_level;
258 }
259
260 // If printing in single line mode, then the entire message will be output
261 // on a single line with no line breaks.
262 void SetSingleLineMode(bool single_line_mode) {
263 single_line_mode_ = single_line_mode;
264 }
265
266 bool IsInSingleLineMode() const { return single_line_mode_; }
267
268 // If use_field_number is true, uses field number instead of field name.
269 void SetUseFieldNumber(bool use_field_number) {
270 use_field_number_ = use_field_number;
271 }
272
273 // Set true to print repeated primitives in a format like:
274 // field_name: [1, 2, 3, 4]
275 // instead of printing each value on its own line. Short format applies
276 // only to primitive values -- i.e. everything except strings and
277 // sub-messages/groups.
278 void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
279 use_short_repeated_primitives_ = use_short_repeated_primitives;
280 }
281
282 // Set true to output UTF-8 instead of ASCII. The only difference
283 // is that bytes >= 0x80 in string fields will not be escaped,
284 // because they are assumed to be part of UTF-8 multi-byte
285 // sequences. This will change the default FastFieldValuePrinter.
286 void SetUseUtf8StringEscaping(bool as_utf8);
287
288 // Set the default (Fast)FieldValuePrinter that is used for all fields that
289 // don't have a field-specific printer registered.
290 // Takes ownership of the printer.
291 void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer);
292 void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer);
293
294 // Sets whether we want to hide unknown fields or not.
295 // Usually unknown fields are printed in a generic way that includes the
296 // tag number of the field instead of field name. However, sometimes it
297 // is useful to be able to print the message without unknown fields (e.g.
298 // for the python protobuf version to maintain consistency between its pure
299 // python and c++ implementations).
300 void SetHideUnknownFields(bool hide) { hide_unknown_fields_ = hide; }
301
302 // If print_message_fields_in_index_order is true, fields of a proto message
303 // will be printed using the order defined in source code instead of the
304 // field number, extensions will be printed at the end of the message
305 // and their relative order is determined by the extension number.
306 // By default, use the field number order.
307 void SetPrintMessageFieldsInIndexOrder(
308 bool print_message_fields_in_index_order) {
309 print_message_fields_in_index_order_ =
310 print_message_fields_in_index_order;
311 }
312
313 // If expand==true, expand google.protobuf.Any payloads. The output
314 // will be of form
315 // [type_url] { <value_printed_in_text> }
316 //
317 // If expand==false, print Any using the default printer. The output will
318 // look like
319 // type_url: "<type_url>" value: "serialized_content"
320 void SetExpandAny(bool expand) { expand_any_ = expand; }
321
322 // Set how parser finds message for Any payloads.
323 void SetFinder(const Finder* finder) { finder_ = finder; }
324
325 // If non-zero, we truncate all string fields that are longer than
326 // this threshold. This is useful when the proto message has very long
327 // strings, e.g., dump of encoded image file.
328 //
329 // NOTE(hfgong): Setting a non-zero value breaks round-trip safe
330 // property of TextFormat::Printer. That is, from the printed message, we
331 // cannot fully recover the original string field any more.
332 void SetTruncateStringFieldLongerThan(
333 const int64 truncate_string_field_longer_than) {
334 truncate_string_field_longer_than_ = truncate_string_field_longer_than;
335 }
336
337 // Register a custom field-specific (Fast)FieldValuePrinter for fields
338 // with a particular FieldDescriptor.
339 // Returns "true" if the registration succeeded, or "false", if there is
340 // already a printer for that FieldDescriptor.
341 // Takes ownership of the printer on successful registration.
342 bool RegisterFieldValuePrinter(const FieldDescriptor* field,
343 const FieldValuePrinter* printer);
344 bool RegisterFieldValuePrinter(const FieldDescriptor* field,
345 const FastFieldValuePrinter* printer);
346
347 // Register a custom message-specific MessagePrinter for messages with a
348 // particular Descriptor.
349 // Returns "true" if the registration succeeded, or "false" if there is
350 // already a printer for that Descriptor.
351 bool RegisterMessagePrinter(const Descriptor* descriptor,
352 const MessagePrinter* printer);
353
354 private:
355 // Forward declaration of an internal class used to print the text
356 // output to the OutputStream (see text_format.cc for implementation).
357 class TextGenerator;
358
359 // Internal Print method, used for writing to the OutputStream via
360 // the TextGenerator class.
361 void Print(const Message& message, TextGenerator* generator) const;
362
363 // Print a single field.
364 void PrintField(const Message& message, const Reflection* reflection,
365 const FieldDescriptor* field,
366 TextGenerator* generator) const;
367
368 // Print a repeated primitive field in short form.
369 void PrintShortRepeatedField(const Message& message,
370 const Reflection* reflection,
371 const FieldDescriptor* field,
372 TextGenerator* generator) const;
373
374 // Print the name of a field -- i.e. everything that comes before the
375 // ':' for a single name/value pair.
376 void PrintFieldName(const Message& message, int field_index,
377 int field_count, const Reflection* reflection,
378 const FieldDescriptor* field,
379 TextGenerator* generator) const;
380
381 // Outputs a textual representation of the value of the field supplied on
382 // the message supplied or the default value if not set.
383 void PrintFieldValue(const Message& message, const Reflection* reflection,
384 const FieldDescriptor* field, int index,
385 TextGenerator* generator) const;
386
387 // Print the fields in an UnknownFieldSet. They are printed by tag number
388 // only. Embedded messages are heuristically identified by attempting to
389 // parse them.
390 void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
391 TextGenerator* generator) const;
392
393 bool PrintAny(const Message& message, TextGenerator* generator) const;
394
395 int initial_indent_level_;
396
397 bool single_line_mode_;
398
399 bool use_field_number_;
400
401 bool use_short_repeated_primitives_;
402
403 bool hide_unknown_fields_;
404
405 bool print_message_fields_in_index_order_;
406
407 bool expand_any_;
408
409 int64 truncate_string_field_longer_than_;
410
411 std::unique_ptr<const FastFieldValuePrinter> default_field_value_printer_;
412 typedef std::map<const FieldDescriptor*, const FastFieldValuePrinter*>
413 CustomPrinterMap;
414 CustomPrinterMap custom_printers_;
415
416 typedef std::map<const Descriptor*, const MessagePrinter*>
417 CustomMessagePrinterMap;
418 CustomMessagePrinterMap custom_message_printers_;
419
420 const Finder* finder_;
421 };
422
423 // Parses a text-format protocol message from the given input stream to
424 // the given message object. This function parses the human-readable format
425 // written by Print(). Returns true on success. The message is cleared first,
426 // even if the function fails -- See Merge() to avoid this behavior.
427 //
428 // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
429 //
430 // One use for this function is parsing handwritten strings in test code.
431 // Another use is to parse the output from google::protobuf::Message::DebugString()
432 // (or ShortDebugString()), because these functions output using
433 // google::protobuf::TextFormat::Print().
434 //
435 // If you would like to read a protocol buffer serialized in the
436 // (non-human-readable) binary wire format, see
437 // google::protobuf::MessageLite::ParseFromString().
438 static bool Parse(io::ZeroCopyInputStream* input, Message* output);
439 // Like Parse(), but reads directly from a string.
440 static bool ParseFromString(const std::string& input, Message* output);
441
442 // Like Parse(), but the data is merged into the given message, as if
443 // using Message::MergeFrom().
444 static bool Merge(io::ZeroCopyInputStream* input, Message* output);
445 // Like Merge(), but reads directly from a string.
446 static bool MergeFromString(const std::string& input, Message* output);
447
448 // Parse the given text as a single field value and store it into the
449 // given field of the given message. If the field is a repeated field,
450 // the new value will be added to the end
451 static bool ParseFieldValueFromString(const std::string& input,
452 const FieldDescriptor* field,
453 Message* message);
454
455 // A location in the parsed text.
456 struct ParseLocation {
457 int line;
458 int column;
459
460 ParseLocation() : line(-1), column(-1) {}
461 ParseLocation(int line_param, int column_param)
462 : line(line_param), column(column_param) {}
463 };
464
465 // Data structure which is populated with the locations of each field
466 // value parsed from the text.
467 class PROTOBUF_EXPORT ParseInfoTree {
468 public:
469 ParseInfoTree();
470 ~ParseInfoTree();
471
472 // Returns the parse location for index-th value of the field in the parsed
473 // text. If none exists, returns a location with line = -1. Index should be
474 // -1 for not-repeated fields.
475 ParseLocation GetLocation(const FieldDescriptor* field, int index) const;
476
477 // Returns the parse info tree for the given field, which must be a message
478 // type. The nested information tree is owned by the root tree and will be
479 // deleted when it is deleted.
480 ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
481 int index) const;
482
483 private:
484 // Allow the text format parser to record information into the tree.
485 friend class TextFormat;
486
487 // Records the starting location of a single value for a field.
488 void RecordLocation(const FieldDescriptor* field, ParseLocation location);
489
490 // Create and records a nested tree for a nested message field.
491 ParseInfoTree* CreateNested(const FieldDescriptor* field);
492
493 // Defines the map from the index-th field descriptor to its parse location.
494 typedef std::map<const FieldDescriptor*, std::vector<ParseLocation> >
495 LocationMap;
496
497 // Defines the map from the index-th field descriptor to the nested parse
498 // info tree.
499 typedef std::map<const FieldDescriptor*, std::vector<ParseInfoTree*> >
500 NestedMap;
501
502 LocationMap locations_;
503 NestedMap nested_;
504
505 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree);
506 };
507
508 // For more control over parsing, use this class.
509 class PROTOBUF_EXPORT Parser {
510 public:
511 Parser();
512 ~Parser();
513
514 // Like TextFormat::Parse().
515 bool Parse(io::ZeroCopyInputStream* input, Message* output);
516 // Like TextFormat::ParseFromString().
517 bool ParseFromString(const std::string& input, Message* output);
518 // Like TextFormat::Merge().
519 bool Merge(io::ZeroCopyInputStream* input, Message* output);
520 // Like TextFormat::MergeFromString().
521 bool MergeFromString(const std::string& input, Message* output);
522
523 // Set where to report parse errors. If NULL (the default), errors will
524 // be printed to stderr.
525 void RecordErrorsTo(io::ErrorCollector* error_collector) {
526 error_collector_ = error_collector;
527 }
528
529 // Set how parser finds extensions. If NULL (the default), the
530 // parser will use the standard Reflection object associated with
531 // the message being parsed.
532 void SetFinder(const Finder* finder) { finder_ = finder; }
533
534 // Sets where location information about the parse will be written. If NULL
535 // (the default), then no location will be written.
536 void WriteLocationsTo(ParseInfoTree* tree) { parse_info_tree_ = tree; }
537
538 // Normally parsing fails if, after parsing, output->IsInitialized()
539 // returns false. Call AllowPartialMessage(true) to skip this check.
540 void AllowPartialMessage(bool allow) { allow_partial_ = allow; }
541
542 // Allow field names to be matched case-insensitively.
543 // This is not advisable if there are fields that only differ in case, or
544 // if you want to enforce writing in the canonical form.
545 // This is 'false' by default.
546 void AllowCaseInsensitiveField(bool allow) {
547 allow_case_insensitive_field_ = allow;
548 }
549
550 // Like TextFormat::ParseFieldValueFromString
551 bool ParseFieldValueFromString(const std::string& input,
552 const FieldDescriptor* field,
553 Message* output);
554
555 // When an unknown extension is met, parsing will fail if this option is set
556 // to false (the default). If true, unknown extensions will be ignored and
557 // a warning message will be generated.
558 void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; }
559
560 // When an unknown field is met, parsing will fail if this option is set
561 // to false(the default). If true, unknown fields will be ignored and
562 // a warning message will be generated.
563 // Please aware that set this option true may hide some errors (e.g.
564 // spelling error on field name). Avoid to use this option if possible.
565 void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; }
566
567
568 void AllowFieldNumber(bool allow) { allow_field_number_ = allow; }
569
570 // Sets maximum recursion depth which parser can use. This is effectively
571 // the maximum allowed nesting of proto messages.
572 void SetRecursionLimit(int limit) { recursion_limit_ = limit; }
573
574 private:
575 // Forward declaration of an internal class used to parse text
576 // representations (see text_format.cc for implementation).
577 class ParserImpl;
578
579 // Like TextFormat::Merge(). The provided implementation is used
580 // to do the parsing.
581 bool MergeUsingImpl(io::ZeroCopyInputStream* input, Message* output,
582 ParserImpl* parser_impl);
583
584 io::ErrorCollector* error_collector_;
585 const Finder* finder_;
586 ParseInfoTree* parse_info_tree_;
587 bool allow_partial_;
588 bool allow_case_insensitive_field_;
589 bool allow_unknown_field_;
590 bool allow_unknown_extension_;
591 bool allow_unknown_enum_;
592 bool allow_field_number_;
593 bool allow_relaxed_whitespace_;
594 bool allow_singular_overwrites_;
595 int recursion_limit_;
596 };
597
598
599 private:
600 // Hack: ParseInfoTree declares TextFormat as a friend which should extend
601 // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some
602 // old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide
603 // helpers for ParserImpl to call methods of ParseInfoTree.
604 static inline void RecordLocation(ParseInfoTree* info_tree,
605 const FieldDescriptor* field,
606 ParseLocation location);
607 static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
608 const FieldDescriptor* field);
609
610 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
611};
612
613inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
614 const FieldDescriptor* field,
615 ParseLocation location) {
616 info_tree->RecordLocation(field, location);
617}
618
619inline TextFormat::ParseInfoTree* TextFormat::CreateNested(
620 ParseInfoTree* info_tree, const FieldDescriptor* field) {
621 return info_tree->CreateNested(field);
622}
623
624} // namespace protobuf
625} // namespace google
626
627#include <google/protobuf/port_undef.inc>
628
629#endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__
630