15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: jschorr@google.com (Joseph Schorr)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <float.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stack>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/text_format.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/coded_stream.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream_impl.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/unknown_field_set.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/tokenizer.h>
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/map-util.h>
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/stubs/stl_util.h>
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Message::DebugString() const {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string debug_string;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextFormat::PrintToString(*this, &debug_string);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return debug_string;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Message::ShortDebugString() const {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string debug_string;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextFormat::Printer printer;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.SetSingleLineMode(true);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.PrintToString(*this, &debug_string);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Single line mode currently might have an extra space at the end.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (debug_string.size() > 0 &&
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_string[debug_string.size() - 1] == ' ') {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    debug_string.resize(debug_string.size() - 1);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return debug_string;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Message::Utf8DebugString() const {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string debug_string;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextFormat::Printer printer;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.SetUseUtf8StringEscaping(true);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.PrintToString(*this, &debug_string);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return debug_string;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::PrintDebugString() const {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("%s", DebugString().c_str());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===========================================================================
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Implementation of the parse information tree class.
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTextFormat::ParseInfoTree::ParseInfoTree() { }
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTextFormat::ParseInfoTree::~ParseInfoTree() {
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Remove any nested information trees, as they are owned by this tree.
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) {
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    STLDeleteElements(&(it->second));
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid TextFormat::ParseInfoTree::RecordLocation(
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor* field,
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    TextFormat::ParseLocation location) {
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  locations_[field].push_back(location);
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested(
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor* field) {
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Owned by us in the map.
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree();
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<TextFormat::ParseInfoTree*>* trees = &nested_[field];
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  GOOGLE_CHECK(trees);
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  trees->push_back(instance);
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return instance;
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid CheckFieldIndex(const FieldDescriptor* field, int index) {
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (field == NULL) { return; }
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (field->is_repeated() && index == -1) {
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. "
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                << "Field: " << field->name();
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else if (!field->is_repeated() && index != -1) {
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields."
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                << "Field: " << field->name();
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation(
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor* field, int index) const {
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CheckFieldIndex(field, index);
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (index == -1) { index = 0; }
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const vector<TextFormat::ParseLocation>* locations =
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FindOrNull(locations_, field);
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (locations == NULL || index >= locations->size()) {
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return TextFormat::ParseLocation();
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return (*locations)[index];
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const FieldDescriptor* field, int index) const {
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CheckFieldIndex(field, index);
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (index == -1) { index = 0; }
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field);
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (trees == NULL || index >= trees->size()) {
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return NULL;
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return (*trees)[index];
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// ===========================================================================
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal class for parsing an ASCII representation of a Protocol Message.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class makes use of the Protocol Message compiler's tokenizer found
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in //google/protobuf/io/tokenizer.h. Note that class's Parse
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// method is *not* thread-safe and should only be used in a single thread at
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a time.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Makes code slightly more readable.  The meaning of "DO(foo)" is
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "Execute foo and fail if it fails.", where failure is indicated by
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returning false. Borrowed from parser.cc (Thanks Kenton!).
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DO(STATEMENT) if (STATEMENT) {} else return false
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TextFormat::Parser::ParserImpl {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determines if repeated values for a non-repeated field are
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permitted, e.g., the string "foo: 1 foo: 2" for a
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // required/optional field named "foo".
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum SingularOverwritePolicy {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ALLOW_SINGULAR_OVERWRITES = 0,   // the last value is retained
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORBID_SINGULAR_OVERWRITES = 1,  // an error is issued
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParserImpl(const Descriptor* root_message_type,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             io::ZeroCopyInputStream* input_stream,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             io::ErrorCollector* error_collector,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             TextFormat::Finder* finder,
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch             ParseInfoTree* parse_info_tree,
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch             SingularOverwritePolicy singular_overwrite_policy,
194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch             bool allow_unknown_field)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : error_collector_(error_collector),
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      finder_(finder),
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      parse_info_tree_(parse_info_tree),
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tokenizer_error_collector_(this),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tokenizer_(input_stream, &tokenizer_error_collector_),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      root_message_type_(root_message_type),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      singular_overwrite_policy_(singular_overwrite_policy),
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      allow_unknown_field_(allow_unknown_field),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      had_errors_(false) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For backwards-compatibility with proto1, we need to allow the 'f' suffix
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for floats.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.set_allow_f_after_float(true);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // '#' starts a comment.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Consume the starting token.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.Next();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ParserImpl() { }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parses the ASCII representation specified in input and saves the
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // information into the output pointer (a Message). Returns
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // false if an error occurs (an error will also be logged to
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GOOGLE_LOG(ERROR)).
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Parse(Message* output) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Consume fields until we cannot do so anymore.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(true) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (LookingAtType(io::Tokenizer::TYPE_END)) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return !had_errors_;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeField(output));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseField(const FieldDescriptor* field, Message* output) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool suc;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      suc = ConsumeFieldMessage(output, output->GetReflection(), field);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      suc = ConsumeFieldValue(output, output->GetReflection(), field);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return suc && LookingAtType(io::Tokenizer::TYPE_END);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReportError(int line, int col, const string& message) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    had_errors_ = true;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_collector_ == NULL) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (line >= 0) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(ERROR) << "Error parsing text-format "
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << root_message_type_->full_name()
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << ": " << (line + 1) << ":"
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << (col + 1) << ": " << message;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(ERROR) << "Error parsing text-format "
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << root_message_type_->full_name()
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << ": " << message;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_collector_->AddError(line, col, message);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReportWarning(int line, int col, const string& message) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_collector_ == NULL) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (line >= 0) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(WARNING) << "Warning parsing text-format "
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << root_message_type_->full_name()
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << ": " << (line + 1) << ":"
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << (col + 1) << ": " << message;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(WARNING) << "Warning parsing text-format "
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << root_message_type_->full_name()
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     << ": " << message;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_collector_->AddWarning(line, col, message);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reports an error with the given message with information indicating
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the position (as derived from the current token).
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReportError(const string& message) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportError(tokenizer_.current().line, tokenizer_.current().column,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                message);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reports a warning with the given message with information indicating
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the position (as derived from the current token).
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReportWarning(const string& message) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportWarning(tokenizer_.current().line, tokenizer_.current().column,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  message);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes the specified message with the given starting delimeter.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method checks to see that the end delimeter at the conclusion of
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the consumption matches the starting delimeter passed in here.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeMessage(Message* message, const string delimeter) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!LookingAt(">") &&  !LookingAt("}")) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeField(message));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Confirm that we have a valid ending delimeter.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DO(Consume(delimeter));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes the current field (as returned by the tokenizer) on the
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // passed in message.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeField(Message* message) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Reflection* reflection = message->GetReflection();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* descriptor = message->GetDescriptor();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string field_name;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = NULL;
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int start_line = tokenizer_.current().line;
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int start_column = tokenizer_.current().column;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (TryConsume("[")) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Extension.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeIdentifier(&field_name));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (TryConsume(".")) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string part;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeIdentifier(&part));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_name += ".";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_name += part;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(Consume("]"));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field = (finder_ != NULL
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ? finder_->FindExtension(message, field_name)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               : reflection->FindKnownExtensionByName(field_name));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field == NULL) {
335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        if (!allow_unknown_field_) {
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ReportError("Extension \"" + field_name + "\" is not defined or "
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      "is not an extension of \"" +
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      descriptor->full_name() + "\".");
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          return false;
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        } else {
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ReportWarning("Extension \"" + field_name + "\" is not defined or "
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        "is not an extension of \"" +
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        descriptor->full_name() + "\".");
344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeIdentifier(&field_name));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field = descriptor->FindFieldByName(field_name);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Group names are expected to be capitalized as they appear in the
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // .proto file, which actually matches their type names, not their field
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // names.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field == NULL) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string lower_field_name = field_name;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LowerString(&lower_field_name);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field = descriptor->FindFieldByName(lower_field_name);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the case-insensitive match worked but the field is NOT a group,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          field = NULL;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Again, special-case group names as described above.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          && field->message_type()->name() != field_name) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field = NULL;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field == NULL) {
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        if (!allow_unknown_field_) {
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ReportError("Message type \"" + descriptor->full_name() +
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                      "\" has no field named \"" + field_name + "\".");
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          return false;
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        } else {
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          ReportWarning("Message type \"" + descriptor->full_name() +
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                        "\" has no field named \"" + field_name + "\".");
376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        }
377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Skips unknown field.
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (field == NULL) {
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      GOOGLE_CHECK(allow_unknown_field_);
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Try to guess the type of this field.
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // If this field is not a message, there should be a ":" between the
385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // field name and the field value and also the field value should not
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // start with "{" or "<" which indicates the begining of a message body.
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // If there is no ":" or there is a "{" or "<" after ":", this field has
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // to be a message or the input is ill-formed.
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return SkipFieldValue();
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return SkipFieldMessage();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fail if the field is not repeated and it has already been specified.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) &&
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !field->is_repeated() && reflection->HasField(*message, field)) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Non-repeated field \"" + field_name +
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "\" is specified multiple times.");
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Perform special handling for embedded message types.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ':' is optional here.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TryConsume(":");
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeFieldMessage(message, reflection, field));
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(Consume(":"));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->is_repeated() && TryConsume("[")) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Short repeated format, e.g.  "foo: [1, 2, 3]"
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (true) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(ConsumeFieldValue(message, reflection, field));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (TryConsume("]")) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(Consume(","));
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeFieldValue(message, reflection, field));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For historical reasons, fields may optionally be separated by commas or
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // semicolons.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryConsume(";") || TryConsume(",");
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->options().deprecated()) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportWarning("text format contains deprecated field \""
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    + field_name + "\"");
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If a parse info tree exists, add the location for the parsed
435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // field.
436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (parse_info_tree_ != NULL) {
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      RecordLocation(parse_info_tree_, field,
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     ParseLocation(start_line, start_column));
439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
441ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return true;
442ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Skips the next field including the field's name and value.
445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool SkipField() {
446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string field_name;
447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (TryConsume("[")) {
448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Extension name.
449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(ConsumeIdentifier(&field_name));
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      while (TryConsume(".")) {
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        string part;
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        DO(ConsumeIdentifier(&part));
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        field_name += ".";
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        field_name += part;
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(Consume("]"));
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(ConsumeIdentifier(&field_name));
459ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Try to guess the type of this field.
462ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If this field is not a message, there should be a ":" between the
463ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // field name and the field value and also the field value should not
464ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // start with "{" or "<" which indicates the begining of a message body.
465ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If there is no ":" or there is a "{" or "<" after ":", this field has
466ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // to be a message or the input is ill-formed.
467ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(SkipFieldValue());
469ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
470ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(SkipFieldMessage());
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
472ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // For historical reasons, fields may optionally be separated by commas or
473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // semicolons.
474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    TryConsume(";") || TryConsume(",");
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeFieldMessage(Message* message,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const Reflection* reflection,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const FieldDescriptor* field) {
481ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // If the parse information tree is not NULL, create a nested one
483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // for the nested message.
484ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ParseInfoTree* parent = parse_info_tree_;
485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (parent != NULL) {
4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      parse_info_tree_ = CreateNested(parent, field);
487ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
488ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string delimeter;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (TryConsume("<")) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delimeter = ">";
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(Consume("{"));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delimeter = "}";
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeMessage(reflection->MutableMessage(message, field),
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        delimeter));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Reset the parse information tree.
505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    parse_info_tree_ = parent;
506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return true;
507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Skips the whole body of a message including the begining delimeter and
510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the ending delimeter.
511ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool SkipFieldMessage() {
512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    string delimeter;
513ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (TryConsume("<")) {
514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      delimeter = ">";
515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    } else {
516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(Consume("{"));
517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      delimeter = "}";
518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    while (!LookingAt(">") &&  !LookingAt("}")) {
520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      DO(SkipField());
521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DO(Consume(delimeter));
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeFieldValue(Message* message,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const Reflection* reflection,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const FieldDescriptor* field) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define an easy to use macro for setting fields. This macro checks
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to see if the field is repeated (in which case we need to use the Add
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// methods or not (in which case we need to use the Set methods).
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SET_FIELD(CPPTYPE, VALUE)                                  \
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (field->is_repeated()) {                                \
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->Add##CPPTYPE(message, field, VALUE);         \
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {                                                   \
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->Set##CPPTYPE(message, field, VALUE);         \
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }                                                          \
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch(field->cpp_type()) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_INT32: {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64 value;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeSignedInteger(&value, kint32max));
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(Int32, static_cast<int32>(value));
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_UINT32: {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint64 value;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeUnsignedInteger(&value, kuint32max));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(UInt32, static_cast<uint32>(value));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_INT64: {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64 value;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeSignedInteger(&value, kint64max));
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(Int64, value);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_UINT64: {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint64 value;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeUnsignedInteger(&value, kuint64max));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(UInt64, value);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_FLOAT: {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double value;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeDouble(&value));
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(Float, static_cast<float>(value));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_DOUBLE: {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double value;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeDouble(&value));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(Double, value);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_STRING: {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string value;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DO(ConsumeString(&value));
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(String, value);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_BOOL: {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          uint64 value;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(ConsumeUnsignedInteger(&value, 1));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SET_FIELD(Bool, value);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          string value;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(ConsumeIdentifier(&value));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (value == "true" || value == "t") {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SET_FIELD(Bool, true);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else if (value == "false" || value == "f") {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SET_FIELD(Bool, false);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ReportError("Invalid value for boolean field \"" + field->name()
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        + "\". Value: \"" + value  + "\".");
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_ENUM: {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string value;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const EnumDescriptor* enum_type = field->enum_type();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const EnumValueDescriptor* enum_value = NULL;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(ConsumeIdentifier(&value));
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Find the enumeration value.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          enum_value = enum_type->FindValueByName(value);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (LookingAt("-") ||
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int64 int_value;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DO(ConsumeSignedInteger(&int_value, kint32max));
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          value = SimpleItoa(int_value);        // for error reporting
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          enum_value = enum_type->FindValueByNumber(int_value);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReportError("Expected integer or identifier.");
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (enum_value == NULL) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ReportError("Unknown enumeration value of \"" + value  + "\" for "
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "field \"" + field->name() + "\".");
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SET_FIELD(Enum, enum_value);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_MESSAGE: {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We should never get here. Put here instead of a default
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // so that if new types are added, we get a nice compiler warning.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE";
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SET_FIELD
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool SkipFieldValue() {
654ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
655ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
656ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        tokenizer_.Next();
657ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
658ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return true;
659ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
660ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Possible field values other than string:
661ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   12345        => TYPE_INTEGER
662ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   -12345       => TYPE_SYMBOL + TYPE_INTEGER
663ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   1.2345       => TYPE_FLOAT
664ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
665ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   inf          => TYPE_IDENTIFIER
666ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
667ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   TYPE_INTEGER => TYPE_IDENTIFIER
668ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Divides them into two group, one with TYPE_SYMBOL
669ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // and the other without:
670ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   Group one:
671ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     12345        => TYPE_INTEGER
672ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     1.2345       => TYPE_FLOAT
673ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     inf          => TYPE_IDENTIFIER
674ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     TYPE_INTEGER => TYPE_IDENTIFIER
675ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   Group two:
676ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     -12345       => TYPE_SYMBOL + TYPE_INTEGER
677ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     -1.2345      => TYPE_SYMBOL + TYPE_FLOAT
678ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //     -inf         => TYPE_SYMBOL + TYPE_IDENTIFIER
679ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // As we can see, the field value consists of an optional '-' and one of
680ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER.
681ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bool has_minus = TryConsume("-");
682ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) &&
683ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        !LookingAtType(io::Tokenizer::TYPE_FLOAT) &&
684ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
685ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return false;
686ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
687ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field
688ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // value while other combinations all generate valid values.
689ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // We check if the value of this combination is valid here.
690ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // TYPE_IDENTIFIER after a '-' should be one of the float values listed
691ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // below:
692ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   inf, inff, infinity, nan
693ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
694ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      string text = tokenizer_.current().text;
695ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      LowerString(&text);
696ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (text != "inf" &&
697ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          text != "infinity" &&
698ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          text != "nan") {
699ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        ReportError("Invalid float number: " + text);
700ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return false;
701ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
702ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
703ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    tokenizer_.Next();
704ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return true;
705ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
706ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the current token's text is equal to that specified.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool LookingAt(const string& text) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tokenizer_.current().text == text;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the current token's type is equal to that specified.
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool LookingAtType(io::Tokenizer::TokenType token_type) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tokenizer_.current().type == token_type;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes an identifier and saves its value in the identifier parameter.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns false if the token is not of type IDENTFIER.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeIdentifier(string* identifier) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Expected identifier.");
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *identifier = tokenizer_.current().text;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.Next();
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes a string and saves its value in the text parameter.
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns false if the token is not of type STRING.
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeString(string* text) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!LookingAtType(io::Tokenizer::TYPE_STRING)) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Expected string.");
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    text->clear();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io::Tokenizer::ParseStringAppend(tokenizer_.current().text, text);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tokenizer_.Next();
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes a uint64 and saves its value in the value parameter.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns false if the token is not of type INTEGER.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeUnsignedInteger(uint64* value, uint64 max_value) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Expected integer.");
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!io::Tokenizer::ParseInteger(tokenizer_.current().text,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     max_value, value)) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Integer out of range.");
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.Next();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes an int64 and saves its value in the value parameter.
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that since the tokenizer does not support negative numbers,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we actually may consume an additional token (for the minus sign) in this
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method. Returns false if the token is not an integer
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (signed or otherwise).
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeSignedInteger(int64* value, uint64 max_value) {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool negative = false;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (TryConsume("-")) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      negative = true;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Two's complement always allows one more negative integer than
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // positive.
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++max_value;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 unsigned_value;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DO(ConsumeUnsignedInteger(&unsigned_value, max_value));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *value = static_cast<int64>(unsigned_value);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (negative) {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value = -*value;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes a double and saves its value in the value parameter.
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that since the tokenizer does not support negative numbers,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we actually may consume an additional token (for the minus sign) in this
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method. Returns false if the token is not a double
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (signed or otherwise).
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeDouble(double* value) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool negative = false;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (TryConsume("-")) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      negative = true;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A double can actually be an integer, according to the tokenizer.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Therefore, we must check both cases here.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have found an integer value for the double.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint64 integer_value;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DO(ConsumeUnsignedInteger(&integer_value, kuint64max));
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value = static_cast<double>(integer_value);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have found a float value for the double.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value = io::Tokenizer::ParseFloat(tokenizer_.current().text);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Mark the current token as consumed.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tokenizer_.Next();
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string text = tokenizer_.current().text;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LowerString(&text);
824ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (text == "inf" ||
825ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          text == "infinity") {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *value = std::numeric_limits<double>::infinity();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tokenizer_.Next();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (text == "nan") {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *value = std::numeric_limits<double>::quiet_NaN();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tokenizer_.Next();
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReportError("Expected double.");
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Expected double.");
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (negative) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *value = -*value;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consumes a token and confirms that it matches that specified in the
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value parameter. Returns false if the token found does not match that
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which was specified.
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Consume(const string& value) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& current_value = tokenizer_.current().text;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_value != value) {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReportError("Expected \"" + value + "\", found \"" + current_value
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  + "\".");
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tokenizer_.Next();
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to consume the supplied value. Returns false if a the
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // token found does not match the value specified.
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TryConsume(const string& value) {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tokenizer_.current().text == value) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tokenizer_.Next();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An internal instance of the Tokenizer's error collector, used to
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // collect any base-level parse errors and feed them to the ParserImpl.
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ParserErrorCollector : public io::ErrorCollector {
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) :
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parser_(parser) { }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~ParserErrorCollector() { };
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void AddError(int line, int column, const string& message) {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser_->ReportError(line, column, message);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void AddWarning(int line, int column, const string& message) {
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parser_->ReportWarning(line, column, message);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TextFormat::Parser::ParserImpl* parser_;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ErrorCollector* error_collector_;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextFormat::Finder* finder_;
899ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ParseInfoTree* parse_info_tree_;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParserErrorCollector tokenizer_error_collector_;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::Tokenizer tokenizer_;
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Descriptor* root_message_type_;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SingularOverwritePolicy singular_overwrite_policy_;
904ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool allow_unknown_field_;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_errors_;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef DO
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===========================================================================
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the Printer found in //google/protobuf/io/printer.h
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TextFormat::Printer::TextGenerator {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TextGenerator(io::ZeroCopyOutputStream* output,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int initial_indent_level)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : output_(output),
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_(NULL),
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_size_(0),
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      at_start_of_line_(true),
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failed_(false),
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      indent_(""),
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_indent_level_(initial_indent_level) {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    indent_.resize(initial_indent_level_ * 2, ' ');
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TextGenerator() {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only BackUp() if we're sure we've successfully called Next() at least
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // once.
930ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!failed_ && buffer_size_ > 0) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_->BackUp(buffer_size_);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indent text by two spaces.  After calling Indent(), two spaces will be
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inserted at the beginning of each line of text.  Indent() may be called
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multiple times to produce deeper indents.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Indent() {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    indent_ += "  ";
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reduces the current indent level by two spaces, or crashes if the indent
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // level is zero.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Outdent() {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (indent_.empty() ||
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        indent_.size() < initial_indent_level_ * 2) {
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    indent_.resize(indent_.size() - 2);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print text to the output stream.
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Print(const string& str) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Print(str.data(), str.size());
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print text to the output stream.
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Print(const char* text) {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Print(text, strlen(text));
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print text to the output stream.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Print(const char* text, int size) {
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pos = 0;  // The number of bytes we've written so far.
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < size; i++) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (text[i] == '\n') {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Saw newline.  If there is more text, we may need to insert an indent
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // here.  So, write what we have so far, including the '\n'.
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Write(text + pos, i - pos + 1);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pos = i + 1;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Setting this true will cause the next Write() to insert an indent
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // first.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        at_start_of_line_ = true;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Write the rest.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Write(text + pos, size - pos);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if any write to the underlying stream failed.  (We don't just
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // crash in this case because this is an I/O failure, not a programming
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // error.)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool failed() const { return failed_; }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Write(const char* data, int size) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (failed_) return;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size == 0) return;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (at_start_of_line_) {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Insert an indent.
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      at_start_of_line_ = false;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Write(indent_.data(), indent_.size());
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (failed_) return;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (size > buffer_size_) {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Data exceeds space in the buffer.  Copy what we can and request a
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // new buffer.
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(buffer_, data, buffer_size_);
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data += buffer_size_;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size -= buffer_size_;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* void_buffer;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failed_ = !output_->Next(&void_buffer, &buffer_size_);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (failed_) return;
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_ = reinterpret_cast<char*>(void_buffer);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Buffer is big enough to receive the data; copy it.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buffer_, data, size);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_ += size;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_size_ -= size;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ZeroCopyOutputStream* const output_;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buffer_;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buffer_size_;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool at_start_of_line_;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool failed_;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string indent_;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int initial_indent_level_;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===========================================================================
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextFormat::Finder::~Finder() {
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextFormat::Parser::Parser()
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : error_collector_(NULL),
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    finder_(NULL),
1040ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    parse_info_tree_(NULL),
1041ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    allow_partial_(false),
1042ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    allow_unknown_field_(false) {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextFormat::Parser::~Parser() {}
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input,
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               Message* output) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->Clear();
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParserImpl parser(output->GetDescriptor(), input, error_collector_,
1051ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    finder_, parse_info_tree_,
1052ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    ParserImpl::FORBID_SINGULAR_OVERWRITES,
1053ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    allow_unknown_field_);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MergeUsingImpl(input, output, &parser);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::ParseFromString(const string& input,
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Message* output) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ArrayInputStream input_stream(input.data(), input.size());
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parse(&input_stream, output);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               Message* output) {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParserImpl parser(output->GetDescriptor(), input, error_collector_,
1066ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    finder_, parse_info_tree_,
1067ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
1068ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    allow_unknown_field_);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MergeUsingImpl(input, output, &parser);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::MergeFromString(const string& input,
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Message* output) {
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ArrayInputStream input_stream(input.data(), input.size());
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Merge(&input_stream, output);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        Message* output,
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        ParserImpl* parser_impl) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parser_impl->Parse(output)) return false;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allow_partial_ && !output->IsInitialized()) {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vector<string> missing_fields;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->FindInitializationErrors(&missing_fields);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parser_impl->ReportError(-1, 0, "Message missing required fields: " +
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    JoinStrings(missing_fields, ", "));
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Parser::ParseFieldValueFromString(
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& input,
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* output) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ArrayInputStream input_stream(input.data(), input.size());
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
1098ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    finder_, parse_info_tree_,
1099ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    ParserImpl::ALLOW_SINGULAR_OVERWRITES,
1100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    allow_unknown_field_);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return parser.ParseField(field, output);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input,
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Message* output) {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parser().Parse(input, output);
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input,
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    Message* output) {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parser().Merge(input, output);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::ParseFromString(const string& input,
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Message* output) {
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parser().ParseFromString(input, output);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::MergeFromString(const string& input,
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Message* output) {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parser().MergeFromString(input, output);
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===========================================================================
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextFormat::Printer::Printer()
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : initial_indent_level_(0),
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    single_line_mode_(false),
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    use_short_repeated_primitives_(false),
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    utf8_string_escaping_(false) {}
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextFormat::Printer::~Printer() {}
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Printer::PrintToString(const Message& message,
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        string* output) const {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DCHECK(output) << "output specified is NULL";
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->clear();
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::StringOutputStream output_stream(output);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = Print(message, &output_stream);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Printer::PrintUnknownFieldsToString(
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields,
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string* output) const {
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DCHECK(output) << "output specified is NULL";
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->clear();
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::StringOutputStream output_stream(output);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PrintUnknownFields(unknown_fields, &output_stream);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Printer::Print(const Message& message,
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                io::ZeroCopyOutputStream* output) const {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextGenerator generator(output, initial_indent_level_);
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Print(message, generator);
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Output false if the generator failed internally.
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !generator.failed();
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TextFormat::Printer::PrintUnknownFields(
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields,
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::ZeroCopyOutputStream* output) const {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextGenerator generator(output, initial_indent_level_);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintUnknownFields(unknown_fields, generator);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Output false if the generator failed internally.
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !generator.failed();
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::Print(const Message& message,
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                TextGenerator& generator) const {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Reflection* reflection = message.GetReflection();
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> fields;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reflection->ListFields(message, &fields);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < fields.size(); i++) {
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintField(message, reflection, fields[i], generator);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintUnknownFields(reflection->GetUnknownFields(message), generator);
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintFieldValueToString(
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& message,
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index,
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string* output) const {
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DCHECK(output) << "output specified is NULL";
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->clear();
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::StringOutputStream output_stream(output);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TextGenerator generator(&output_stream, initial_indent_level_);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldValue(message, message.GetReflection(), field, index, generator);
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintField(const Message& message,
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const Reflection* reflection,
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const FieldDescriptor* field,
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     TextGenerator& generator) const {
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_short_repeated_primitives_ &&
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->is_repeated() &&
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintShortRepeatedField(message, reflection, field, generator);
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->is_repeated()) {
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = reflection->FieldSize(message, field);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (reflection->HasField(message, field)) {
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count = 1;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 0; j < count; ++j) {
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldName(message, reflection, field, generator);
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (single_line_mode_) {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(" { ");
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(" {\n");
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Indent();
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator.Print(": ");
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Write the field value.
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int field_index = j;
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated()) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_index = -1;
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldValue(message, reflection, field, field_index, generator);
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (single_line_mode_) {
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print("} ");
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Outdent();
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print("}\n");
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (single_line_mode_) {
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(" ");
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print("\n");
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintShortRepeatedField(
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& message,
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Reflection* reflection,
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TextGenerator& generator) const {
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print primitive repeated field in short form.
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldName(message, reflection, field, generator);
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size = reflection->FieldSize(message, field);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generator.Print(": [");
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < size; i++) {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0) generator.Print(", ");
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldValue(message, reflection, field, i, generator);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (single_line_mode_) {
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generator.Print("] ");
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generator.Print("]\n");
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintFieldName(const Message& message,
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const Reflection* reflection,
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const FieldDescriptor* field,
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         TextGenerator& generator) const {
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->is_extension()) {
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generator.Print("[");
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We special-case MessageSet elements for compatibility with proto1.
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->containing_type()->options().message_set_wire_format()
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && field->type() == FieldDescriptor::TYPE_MESSAGE
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && field->is_optional()
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && field->extension_scope() == field->message_type()) {
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator.Print(field->message_type()->full_name());
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator.Print(field->full_name());
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generator.Print("]");
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->type() == FieldDescriptor::TYPE_GROUP) {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Groups must be serialized with their original capitalization.
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator.Print(field->message_type()->name());
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator.Print(field->name());
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintFieldValue(
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& message,
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Reflection* reflection,
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index,
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TextGenerator& generator) const {
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DCHECK(field->is_repeated() || (index == -1))
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Index must be -1 for non-repeated fields";
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (field->cpp_type()) {
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OUTPUT_FIELD(CPPTYPE, METHOD, TO_STRING)                             \
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_##CPPTYPE:                               \
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(TO_STRING(field->is_repeated() ?                     \
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->GetRepeated##METHOD(message, field, index) :           \
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->Get##METHOD(message, field)));                         \
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;                                                               \
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD( INT32,  Int32, SimpleItoa);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD( INT64,  Int64, SimpleItoa);
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD(UINT32, UInt32, SimpleItoa);
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD(UINT64, UInt64, SimpleItoa);
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD( FLOAT,  Float, SimpleFtoa);
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OUTPUT_FIELD(DOUBLE, Double, SimpleDtoa);
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef OUTPUT_FIELD
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_STRING: {
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string scratch;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const string& value = field->is_repeated() ?
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reflection->GetRepeatedStringReference(
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              message, field, index, &scratch) :
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reflection->GetStringReference(message, field, &scratch);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print("\"");
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (utf8_string_escaping_) {
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(strings::Utf8SafeCEscape(value));
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(CEscape(value));
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print("\"");
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_BOOL:
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (field->is_repeated()) {
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(reflection->GetRepeatedBool(message, field, index)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ? "true" : "false");
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(reflection->GetBool(message, field)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ? "true" : "false");
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_ENUM:
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field->is_repeated() ?
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->GetRepeatedEnum(message, field, index)->name() :
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reflection->GetEnum(message, field)->name());
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case FieldDescriptor::CPPTYPE_MESSAGE:
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Print(field->is_repeated() ?
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                reflection->GetRepeatedMessage(message, field, index) :
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                reflection->GetMessage(message, field),
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              generator);
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::Print(const Message& message,
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    io::ZeroCopyOutputStream* output) {
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Printer().Print(message, output);
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::PrintUnknownFields(
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields,
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::ZeroCopyOutputStream* output) {
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Printer().PrintUnknownFields(unknown_fields, output);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::PrintToString(
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& message, string* output) {
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Printer().PrintToString(message, output);
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::PrintUnknownFieldsToString(
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields, string* output) {
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Printer().PrintUnknownFieldsToString(unknown_fields, output);
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ void TextFormat::PrintFieldValueToString(
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Message& message,
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index,
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string* output) {
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Printer().PrintFieldValueToString(message, field, index, output);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ bool TextFormat::ParseFieldValueFromString(
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string& input,
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field,
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Message* message) {
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Parser().ParseFieldValueFromString(input, field, message);
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints an integer as hex with a fixed number of digits dependent on the
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// integer type.
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename IntType>
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static string PaddedHex(IntType value) {
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string result;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.reserve(sizeof(value) * 2);
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = sizeof(value) * 2 - 1; i >= 0; i--) {
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.push_back(int_to_hex_digit(value >> (i*4) & 0x0F));
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TextFormat::Printer::PrintUnknownFields(
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < unknown_fields.field_count(); i++) {
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const UnknownField& field = unknown_fields.field(i);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    string field_number = SimpleItoa(field.number());
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (field.type()) {
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UnknownField::TYPE_VARINT:
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field_number);
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(": ");
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(SimpleItoa(field.varint()));
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (single_line_mode_) {
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(" ");
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("\n");
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UnknownField::TYPE_FIXED32: {
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field_number);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(": 0x");
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char buffer[kFastToBufferSize];
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(FastHex32ToBuffer(field.fixed32(), buffer));
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (single_line_mode_) {
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(" ");
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("\n");
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UnknownField::TYPE_FIXED64: {
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field_number);
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(": 0x");
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char buffer[kFastToBufferSize];
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(FastHex64ToBuffer(field.fixed64(), buffer));
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (single_line_mode_) {
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(" ");
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("\n");
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UnknownField::TYPE_LENGTH_DELIMITED: {
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field_number);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const string& value = field.length_delimited();
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UnknownFieldSet embedded_unknown_fields;
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // This field is parseable as a Message.
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // So it is probably an embedded message.
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (single_line_mode_) {
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print(" { ");
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print(" {\n");
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Indent();
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintUnknownFields(embedded_unknown_fields, generator);
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (single_line_mode_) {
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print("} ");
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Outdent();
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print("}\n");
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // This field is not parseable as a Message.
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // So it is probably just a plain string.
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(": \"");
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(CEscape(value));
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("\"");
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (single_line_mode_) {
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print(" ");
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            generator.Print("\n");
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UnknownField::TYPE_GROUP:
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        generator.Print(field_number);
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (single_line_mode_) {
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(" { ");
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print(" {\n");
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Indent();
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PrintUnknownFields(field.group(), generator);
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (single_line_mode_) {
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("} ");
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Outdent();
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          generator.Print("}\n");
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
1522