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: kenton@google.com (Kenton Varda)
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 <algorithm>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/hash.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_message.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_field.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_enum.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_extension.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_helpers.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/printer.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/coded_stream.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/wire_format.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
513d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cpp {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using internal::WireFormat;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using internal::WireFormatLite;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print the field's proto-syntax definition as a comment.  We don't want to
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // print group bodies so we cut off after the first line.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string def = field->DebugString();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("// $def$\n",
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "def", def.substr(0, def.find_first_of('\n')));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FieldOrderingByNumber {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool operator()(const FieldDescriptor* a,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const FieldDescriptor* b) const {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return a->number() < b->number();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* kWireTypeNames[] = {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "VARINT",
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "FIXED64",
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "LENGTH_DELIMITED",
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "START_GROUP",
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "END_GROUP",
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "FIXED32",
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sort the fields of the given Descriptor by number into a new[]'d array
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and return it.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FieldDescriptor** fields =
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new const FieldDescriptor*[descriptor->field_count()];
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor->field_count(); i++) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields[i] = descriptor->field(i);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sort(fields, fields + descriptor->field_count(),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       FieldOrderingByNumber());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fields;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functor for sorting extension ranges by their "start" field number.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionRangeSorter {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const Descriptor::ExtensionRange* left,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const Descriptor::ExtensionRange* right) const {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return left->start < right->start;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1073d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// Returns true if the "required" restriction check should be ignored for the
1083d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch// given field.
1093d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdochinline static bool ShouldIgnoreRequiredFieldCheck(
1103d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    const FieldDescriptor* field) {
1113d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  return false;
1123d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch}
1133d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the message type has any required fields.  If it doesn't,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can optimize out calls to its IsInitialized() method.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already_seen is used to avoid checking the same type multiple times
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (and also to protect against recursion).
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool HasRequiredFields(
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* type,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hash_set<const Descriptor*>* already_seen) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (already_seen->count(type) > 0) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since the first occurrence of a required field causes the whole
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // function to return true, we can assume that if the type is already
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the cache it didn't have any required fields.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  already_seen->insert(type);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the type has extensions, an extension with message type could contain
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // required fields, so we have to be conservative and assume such an
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension exists.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type->extension_range_count() > 0) return true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < type->field_count(); i++) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = type->field(i);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_required()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1403d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1413d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        !ShouldIgnoreRequiredFieldCheck(field)) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (HasRequiredFields(field->message_type(), already_seen)) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool HasRequiredFields(const Descriptor* type) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hash_set<const Descriptor*> already_seen;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HasRequiredFields(type, &already_seen);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This returns an estimate of the compiler's alignment for the field.  This
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can't guarantee to be correct because the generated code could be compiled on
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different systems with different alignment rules.  The estimates below assume
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 64-bit pointers.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int EstimateAlignmentSize(const FieldDescriptor* field) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field == NULL) return 0;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (field->is_repeated()) return 8;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (field->cpp_type()) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_BOOL:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT32:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT32:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_ENUM:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_FLOAT:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 4;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_INT64:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_UINT64:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_DOUBLE:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_STRING:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FieldDescriptor::CPPTYPE_MESSAGE:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 8;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_LOG(FATAL) << "Can't get here.";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return -1;  // Make compiler happy.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FieldGroup is just a helper for OptimizePadding below.  It holds a vector of
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fields that are grouped together because they have compatible alignment, and
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a preferred location in the final field ordering.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FieldGroup {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldGroup()
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : preferred_location_(0) {}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A group with a single field.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldGroup(float preferred_location, const FieldDescriptor* field)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : preferred_location_(preferred_location),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fields_(1, field) {}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Append the fields in 'other' to this group.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Append(const FieldGroup& other) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (other.fields_.empty()) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Preferred location is the average among all the fields, so we weight by
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the number of fields on each FieldGroup object.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preferred_location_ =
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (preferred_location_ * fields_.size() +
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (other.preferred_location_ * other.fields_.size())) /
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (fields_.size() + other.fields_.size());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPreferredLocation(float location) { preferred_location_ = location; }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const vector<const FieldDescriptor*>& fields() const { return fields_; }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FieldGroup objects sort by their preferred location.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const FieldGroup& other) const {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return preferred_location_ < other.preferred_location_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "preferred_location_" is an estimate of where this group should go in the
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // final list of fields.  We compute this by taking the average index of each
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // field in this group in the original ordering of fields.  This is very
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // approximate, but should put this group close to where its member fields
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // originally went.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float preferred_location_;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> fields_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We rely on the default copy constructor and operator= so this type can be
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used in a vector.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reorder 'fields' so that if the fields are output into a c++ class in the new
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// order, the alignment padding is minimized.  We try to do this while keeping
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each field as close as possible to its original position so that we don't
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reduce cache locality much for function that access each field in order.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OptimizePadding(vector<const FieldDescriptor*>* fields) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < fields->size(); ++i) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (EstimateAlignmentSize((*fields)[i])) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GOOGLE_LOG(FATAL) << "Unknown alignment size.";
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now group fields aligned to 1 byte into sets of 4, and treat those like a
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single field aligned to 4 bytes.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < aligned_to_1.size(); i += 4) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldGroup field_group;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_group.Append(aligned_to_1[j]);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aligned_to_4.push_back(field_group);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort by preferred location to keep fields as close to their original
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // location as possible.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sort(aligned_to_4.begin(), aligned_to_4.end());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now group fields aligned to 4 bytes (or the 4-field groups created above)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // into pairs, and treat those like a single field aligned to 8 bytes.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < aligned_to_4.size(); i += 2) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FieldGroup field_group;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_group.Append(aligned_to_4[j]);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == aligned_to_4.size() - 1) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Move incomplete 4-byte block to the end.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_group.SetPreferredLocation(fields->size() + 1);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aligned_to_8.push_back(field_group);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort by preferred location to keep fields as close to their original
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // location as possible.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sort(aligned_to_8.begin(), aligned_to_8.end());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now pull out all the FieldDescriptors in order.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fields->clear();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < aligned_to_8.size(); ++i) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields->insert(fields->end(),
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   aligned_to_8[i].fields().begin(),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   aligned_to_8[i].fields().end());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ===================================================================
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageGenerator::MessageGenerator(const Descriptor* descriptor,
2923d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch                                   const Options& options)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : descriptor_(descriptor),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classname_(ClassName(descriptor, false)),
2953d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    options_(options),
2963d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    field_generators_(descriptor, options),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_(new scoped_ptr<MessageGenerator>[
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor->nested_type_count()]),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_(new scoped_ptr<EnumGenerator>[
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor->enum_type_count()]),
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_generators_(new scoped_ptr<ExtensionGenerator>[
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor->extension_count()]) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor->nested_type_count(); i++) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i].reset(
3063d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      new MessageGenerator(descriptor->nested_type(i), options));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor->enum_type_count(); i++) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i].reset(
3113d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      new EnumGenerator(descriptor->enum_type(i), options));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor->extension_count(); i++) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_generators_[i].reset(
3163d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch      new ExtensionGenerator(descriptor->extension(i), options));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageGenerator::~MessageGenerator() {}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateForwardDeclaration(io::Printer* printer) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("class $classname$;\n",
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "classname", classname_);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateForwardDeclaration(printer);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateEnumDefinitions(io::Printer* printer) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateEnumDefinitions(printer);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i]->GenerateDefinition(printer);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateFieldAccessorDeclarations(io::Printer* printer) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldComment(printer, field);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    map<string, string> vars;
3613d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    SetCommonFieldVariables(field, &vars, options_);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["constant_name"] = FieldConstantName(field);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars, "static const int $constant_name$ = $number$;\n");
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate type-specific accessor declarations.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(field).GenerateAccessorDeclarations(printer);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate accessors for extensions.  We just call a macro located in
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension_set.h since the accessors about 80 lines of static code.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n",
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateFieldAccessorDefinitions(io::Printer* printer) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("// $classname$\n\n", "classname", classname_);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintFieldComment(printer, field);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    map<string, string> vars;
3983d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    SetCommonFieldVariables(field, &vars, options_);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate has_$name$() or $name$_size().
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline int $classname$::$name$_size() const {\n"
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  return $name$_.size();\n"
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n");
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Singular field.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char buffer[kFastToBufferSize];
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vars["has_array_index"] = SimpleItoa(field->index() / 32);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline bool $classname$::has_$name$() const {\n"
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n"
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline void $classname$::set_has_$name$() {\n"
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n"
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline void $classname$::clear_has_$name$() {\n"
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n"
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate clear_$name$()
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline void $classname$::clear_$name$() {\n");
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(field).GenerateClearingCode(printer);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated()) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "  clear_has_$name$();\n");
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate type-specific accessors.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateClassDefinition(io::Printer* printer) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateClassDefinition(printer);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(kThinSeparator);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["field_count"] = SimpleItoa(descriptor_->field_count());
4583d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  if (options_.dllexport_decl.empty()) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["dllexport"] = "";
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4613d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    vars["dllexport"] = options_.dllexport_decl + " ";
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["superclass"] = SuperClassName(descriptor_);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "class $dllexport$$classname$ : public $superclass$ {\n"
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    " public:\n");
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$();\n"
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "virtual ~$classname$();\n"
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$(const $classname$& from);\n"
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "inline $classname$& operator=(const $classname$& from) {\n"
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  CopyFrom(from);\n"
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return *this;\n"
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return _unknown_fields_;\n"
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n"
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return &_unknown_fields_;\n"
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only generate this member if it's not disabled.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file()) &&
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !descriptor_->options().no_standard_descriptor_accessor()) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static const ::google::protobuf::Descriptor* descriptor();\n");
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static const $classname$& default_instance();\n"
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StaticInitializersForced(descriptor_->file())) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "// Returns the internal default instance pointer. This function can\n"
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "// return NULL thus should not be used by the user. This is intended\n"
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "// for Protobuf internal code. Please use default_instance() declared\n"
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "// above instead.\n"
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static inline const $classname$* internal_default_instance() {\n"
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return default_instance_;\n"
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "#endif\n"
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5193d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void Swap($classname$* other);\n"
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// implements Message ----------------------------------------------\n"
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$* New() const;\n");
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasGeneratedMethods(descriptor_->file())) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasDescriptorMethods(descriptor_->file())) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "void CopyFrom(const ::google::protobuf::Message& from);\n"
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "void MergeFrom(const ::google::protobuf::Message& from);\n");
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void CopyFrom(const $classname$& from);\n"
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void MergeFrom(const $classname$& from);\n"
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void Clear();\n"
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "bool IsInitialized() const;\n"
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n"
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "int ByteSize() const;\n"
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "bool MergePartialFromCodedStream(\n"
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    ::google::protobuf::io::CodedInputStream* input);\n"
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void SerializeWithCachedSizes(\n"
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    ::google::protobuf::io::CodedOutputStream* output) const;\n");
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasFastArraySerialization(descriptor_->file())) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "int GetCachedSize() const { return _cached_size_; }\n"
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "private:\n"
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void SharedCtor();\n"
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void SharedDtor();\n"
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void SetCachedSize(int size) const;\n"
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "public:\n"
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::Metadata GetMetadata() const;\n"
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::std::string GetTypeName() const;\n"
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// nested types ----------------------------------------------------\n"
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Import all nested message classes into this class's scope with typedefs.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Descriptor* nested_type = descriptor_->nested_type(i);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("typedef $nested_full_name$ $nested_name$;\n",
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "nested_name", nested_type->name(),
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "nested_full_name", ClassName(nested_type, false));
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->nested_type_count() > 0) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Import all nested enums and their values into this class's scope with
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // typedefs and constants.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i]->GenerateSymbolImports(printer);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// accessors -------------------------------------------------------\n"
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate accessor methods for all fields.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateFieldAccessorDeclarations(printer);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Declare extension identifiers.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->extension_count(); i++) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_generators_[i]->GenerateDeclaration(printer);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// @@protoc_insertion_point(class_scope:$full_name$)\n",
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "full_name", descriptor_->full_name());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate private members.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(" private:\n");
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6183d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!descriptor_->field(i)->is_repeated()) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline void set_has_$name$();\n",
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name", FieldName(descriptor_->field(i)));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "inline void clear_has_$name$();\n",
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name", FieldName(descriptor_->field(i)));
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To minimize padding, data members are divided into three sections:
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (1) members assumed to align to 8 bytes
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (2) members corresponding to message fields, re-ordered to optimize
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     alignment.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (3) members assumed to align to 4 bytes.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members assumed to align to 8 bytes:
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::internal::ExtensionSet _extensions_;\n"
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Field members:
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> fields;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fields.push_back(descriptor_->field(i));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OptimizePadding(&fields);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < fields.size(); ++i) {
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(fields[i]).GeneratePrivateMembers(printer);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members assumed to align to 4 bytes:
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  Make _cached_size_ an atomic<int> when C++ supports it.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n"
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "mutable int _cached_size_;\n");
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate _has_bits_.
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->field_count() > 0) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Zero-size arrays aren't technically allowed, and MSVC in particular
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't like them.  We still need to declare these arrays to make
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // other code compile.  Since this is an uncommon case, we'll just declare
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // them with size 1 and waste some space.  Oh well.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::uint32 _has_bits_[1];\n"
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // friends so that they can access private static variables like
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default_instance_ and reflection_.
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintHandlingOptionalStaticInitializers(
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    descriptor_->file(), printer,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // With static initializers.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "friend void $dllexport_decl$ $adddescriptorsname$();\n",
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Without.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Vars.
6943d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    "dllexport_decl", options_.dllexport_decl,
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "adddescriptorsname",
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GlobalAddDescriptorsName(descriptor_->file()->name()));
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "friend void $assigndescriptorsname$();\n"
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "friend void $shutdownfilename$();\n"
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n",
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "assigndescriptorsname",
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GlobalAssignDescriptorsName(descriptor_->file()->name()),
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void InitAsDefaultInstance();\n"
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static $classname$* default_instance_;\n",
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars, "};");
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateInlineMethods(io::Printer* printer) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateInlineMethods(printer);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(kThinSeparator);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateFieldAccessorDefinitions(printer);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateDescriptorDeclarations(io::Printer* printer) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const ::google::protobuf::internal::GeneratedMessageReflection*\n"
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $name$_reflection_ = NULL;\n",
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "name", classname_);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateDescriptorDeclarations(printer);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name", ClassName(descriptor_->enum_type(i), false));
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateDescriptorInitializer(io::Printer* printer, int index) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  Passing the index to this method is redundant; just use
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   descriptor_->index() instead.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["index"] = SimpleItoa(index);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the descriptor from the parent's descriptor.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->containing_type() == NULL) {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$classname$_descriptor_ = file->message_type($index$);\n");
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["parent"] = ClassName(descriptor_->containing_type(), false);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$classname$_descriptor_ = "
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "$parent$_descriptor_->nested_type($index$);\n");
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the offsets.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateOffsets(printer);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the reflection object.
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$_reflection_ =\n"
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  new ::google::protobuf::internal::GeneratedMessageReflection(\n"
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    $classname$_descriptor_,\n"
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    $classname$::default_instance_,\n"
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    $classname$_offsets_,\n"
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$classname$, _unknown_fields_),\n");
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "$classname$, _extensions_),\n");
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No extensions.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    -1,\n");
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7863d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  printer->Print(
7873d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    "    ::google::protobuf::DescriptorPool::generated_pool(),\n");
7883d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  printer->Print(vars,
7893d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    "    ::google::protobuf::MessageFactory::generated_factory(),\n");
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    sizeof($classname$));\n");
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle nested types.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateTypeRegistrations(io::Printer* printer) {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register this message type with the message factory.
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $classname$_descriptor_, &$classname$::default_instance());\n",
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle nested types.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateTypeRegistrations(printer);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateDefaultInstanceAllocator(io::Printer* printer) {
8193d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // Construct the default instances of all fields, as they will be used
8203d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // when creating the default instance of the entire message.
8213d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  for (int i = 0; i < descriptor_->field_count(); i++) {
8223d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    field_generators_.get(descriptor_->field(i))
8233d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch                     .GenerateDefaultInstanceAllocator(printer);
8243d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  }
8253d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the default instance.  We can't call InitAsDefaultInstance() yet
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because we need to make sure all default instances that this one might
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // depend on are constructed first.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$::default_instance_ = new $classname$();\n",
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle nested types.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateDefaultInstanceInitializer(io::Printer* printer) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$::default_instance_->InitAsDefaultInstance();\n",
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register extensions.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->extension_count(); i++) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_generators_[i]->GenerateRegistration(printer);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle nested types.
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateShutdownCode(io::Printer* printer) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "delete $classname$::default_instance_;\n",
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "delete $classname$_reflection_;\n",
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8693d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  // Handle default instances of fields.
8703d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  for (int i = 0; i < descriptor_->field_count(); i++) {
8713d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch    field_generators_.get(descriptor_->field(i))
8723d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch                     .GenerateShutdownCode(printer);
8733d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch  }
8743d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle nested types.
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateShutdownCode(printer);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateClassMethods(io::Printer* printer) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum_generators_[i]->GenerateMethods(printer);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nested_generators_[i]->GenerateClassMethods(printer);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(kThinSeparator);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate non-inline field definitions.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(descriptor_->field(i))
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     .GenerateNonInlineAccessorDefinitions(printer);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate field number constants.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("#ifndef _MSC_VER\n");
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor *field = descriptor_->field(i);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const int $classname$::$constant_name$;\n",
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", ClassName(FieldScope(field), false),
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "constant_name", FieldConstantName(field));
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "#endif  // !_MSC_VER\n"
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Define extension identifiers.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->extension_count(); i++) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_generators_[i]->GenerateDefinition(printer);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateStructors(printer);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasGeneratedMethods(descriptor_->file())) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateClear(printer);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateMergeFromCodedStream(printer);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateSerializeWithCachedSizes(printer);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasFastArraySerialization(descriptor_->file())) {
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSerializeWithCachedSizesToArray(printer);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("\n");
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateByteSize(printer);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateMergeFrom(printer);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateCopyFrom(printer);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateIsInitialized(printer);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\n");
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateSwap(printer);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  protobuf_AssignDescriptorsOnce();\n"
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  ::google::protobuf::Metadata metadata;\n"
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  metadata.descriptor = $classname$_descriptor_;\n"
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  metadata.reflection = $classname$_reflection_;\n"
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return metadata;\n"
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::std::string $classname$::GetTypeName() const {\n"
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return \"$type_name$\";\n"
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_,
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "type_name", descriptor_->full_name());
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateOffsets(io::Printer* printer) {
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static const int $classname$_offsets_[$field_count$] = {\n",
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_,
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "field_count", SimpleItoa(max(1, descriptor_->field_count())));
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_,
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name", FieldName(field));
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("};\n");
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSharedConstructorCode(io::Printer* printer) {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::SharedCtor() {\n",
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "_cached_size_ = 0;\n");
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(descriptor_->field(i))
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     .GenerateConstructorCode(printer);
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n\n");
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSharedDestructorCode(io::Printer* printer) {
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::SharedDtor() {\n",
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the destructors for each field.
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(descriptor_->field(i))
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     .GenerateDestructorCode(printer);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintHandlingOptionalStaticInitializers(
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    descriptor_->file(), printer,
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // With static initializers.
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "if (this != default_instance_) {\n",
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Without.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "if (this != &default_instance()) {\n");
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to delete all embedded messages.
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  If we make unset messages point at default instances
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   instead of NULL, then it would make sense to move this code into
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   MessageFieldGenerator::GenerateDestructorCode().
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated() &&
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("  delete $name$_;\n",
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "name", FieldName(field));
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  }\n"
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateStructors(io::Printer* printer) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string superclass = SuperClassName(descriptor_);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the default constructor.
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$::$classname$()\n"
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  : $superclass$() {\n"
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  SharedCtor();\n"
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n",
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_,
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "superclass", superclass);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::InitAsDefaultInstance() {\n",
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The default instance needs all of its embedded message pointers
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cross-linked to other default instances.  We can't do this initialization
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the constructor because some other default instances may not have been
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // constructed yet at that time.
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(kenton):  Maybe all message fields (even for non-default messages)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   should be initialized to point at default instances rather than NULL?
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated() &&
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintHandlingOptionalStaticInitializers(
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        descriptor_->file(), printer,
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // With static initializers.
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Without.
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  $name$_ = const_cast< $type$*>(\n"
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "      $type$::internal_default_instance());\n",
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Vars.
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name", FieldName(field),
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "type", FieldMessageTypeName(field));
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the copy constructor.
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$::$classname$(const $classname$& from)\n"
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  : $superclass$() {\n"
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  SharedCtor();\n"
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  MergeFrom(from);\n"
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n",
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_,
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "superclass", superclass);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the shared constructor code.
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateSharedConstructorCode(printer);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the destructor.
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$::~$classname$() {\n"
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  SharedDtor();\n"
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n",
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the shared destructor code.
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateSharedDestructorCode(printer);
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate SetCachedSize.
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::SetCachedSize(int size) const {\n"
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  _cached_size_ = size;\n"
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n",
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only generate this member if it's not disabled.
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file()) &&
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !descriptor_->options().no_standard_descriptor_accessor()) {
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  protobuf_AssignDescriptorsOnce();\n"
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_descriptor_;\n"
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_,
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "adddescriptorsname",
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GlobalAddDescriptorsName(descriptor_->file()->name()));
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const $classname$& $classname$::default_instance() {\n",
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintHandlingOptionalStaticInitializers(
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    descriptor_->file(), printer,
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // With static initializers.
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  if (default_instance_ == NULL) $adddescriptorsname$();\n",
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Without.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $adddescriptorsname$();\n",
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Vars.
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "adddescriptorsname",
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GlobalAddDescriptorsName(descriptor_->file()->name()));
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return *default_instance_;\n"
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$* $classname$::default_instance_ = NULL;\n"
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$classname$* $classname$::New() const {\n"
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return new $classname$;\n"
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n",
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_,
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "adddescriptorsname",
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GlobalAddDescriptorsName(descriptor_->file()->name()));
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateClear(io::Printer* printer) {
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("void $classname$::Clear() {\n",
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "classname", classname_);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_index = -1;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("_extensions_.Clear();\n");
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated()) {
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We can use the fact that _has_bits_ is a giant bitfield to our
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // advantage:  We can check up to 32 bits at a time for equality to
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // zero, and skip the whole range if so.  This can improve the speed
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // of Clear() for messages which contain a very large number of
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // optional fields of which only a few are used at a time.  Here,
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // we've chosen to check 8 bits at a time rather than 32.
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i / 8 != last_index / 8 || last_index < 0) {
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (last_index >= 0) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Outdent();
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Print("}\n");
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "index", SimpleItoa(field->index()));
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_index = i;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It's faster to just overwrite primitive types, but we should
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // only clear strings and messages if they were set.
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(kenton):  Let the CppFieldGenerator decide this somehow.
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool should_check_bit =
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (should_check_bit) {
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (has_$name$()) {\n",
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "name", FieldName(field));
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateClearingCode(printer);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (should_check_bit) {
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Outdent();
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print("}\n");
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_index >= 0) {
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeated fields don't use _has_bits_ so we clear them in a separate
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pass.
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateClearingCode(printer);
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "mutable_unknown_fields()->Clear();\n");
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSwap(io::Printer* printer) {
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the Swap member function.
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("void $classname$::Swap($classname$* other) {\n",
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "classname", classname_);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("if (other != this) {\n");
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasGeneratedMethods(descriptor_->file())) {
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < descriptor_->field_count(); i++) {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const FieldDescriptor* field = descriptor_->field(i);
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateSwappingCode(printer);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "i", SimpleItoa(i));
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasUnknownFields(descriptor_->file())) {
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (descriptor_->extension_range_count() > 0) {
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("_extensions_.Swap(&other->_extensions_);\n");
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("GetReflection()->Swap(this, other);");
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateMergeFrom(io::Printer* printer) {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate the generalized MergeFrom (aka that which takes in the Message
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // base class as a parameter).
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  GOOGLE_CHECK_NE(&from, this);\n",
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cast the message to the proper type. If we find that the message is
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // *not* of the proper type, we can still call Merge via the reflection
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // system, as the GOOGLE_CHECK above ensured that we have the same descriptor
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for each message.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const $classname$* source =\n"
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    &from);\n"
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "if (source == NULL) {\n"
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "} else {\n"
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  MergeFrom(*source);\n"
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n",
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n\n");
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate CheckTypeAndMergeFrom().
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void $classname$::CheckTypeAndMergeFrom(\n"
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    const ::google::protobuf::MessageLite& from) {\n"
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n"
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::MergeFrom(const $classname$& from) {\n"
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  GOOGLE_CHECK_NE(&from, this);\n",
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Merge Repeated fields. These fields do not require a
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // check as we can simply iterate over them.
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); ++i) {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateMergingCode(printer);
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Merge Optional and Required fields (after a _has_bit check).
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_index = -1;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); ++i) {
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated()) {
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See above in GenerateClear for an explanation of this.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i / 8 != last_index / 8 || last_index < 0) {
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (last_index >= 0) {
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Outdent();
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Print("}\n");
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "index", SimpleItoa(field->index()));
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_index = i;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (from.has_$name$()) {\n",
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name", FieldName(field));
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Indent();
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateMergingCode(printer);
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Outdent();
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("}\n");
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_index >= 0) {
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateCopyFrom(io::Printer* printer) {
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Generate the generalized CopyFrom (aka that which takes in the Message
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // base class as a parameter).
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "if (&from == this) return;\n"
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Clear();\n"
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "MergeFrom(from);\n");
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n\n");
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the class-specific CopyFrom.
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::CopyFrom(const $classname$& from) {\n",
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "if (&from == this) return;\n"
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Clear();\n"
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "MergeFrom(from);\n");
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateMergeFromCodedStream(io::Printer* printer) {
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->options().message_set_wire_format()) {
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special-case MessageSet.
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "bool $classname$::MergePartialFromCodedStream(\n"
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    ::google::protobuf::io::CodedInputStream* input) {\n",
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintHandlingOptionalStaticInitializers(
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor_->file(), printer,
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // With static initializers.
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return _extensions_.ParseMessageSet(input, default_instance_,\n"
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "                                      mutable_unknown_fields());\n",
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Without.
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return _extensions_.ParseMessageSet(input, &default_instance(),\n"
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "                                      mutable_unknown_fields());\n",
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Vars.
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "bool $classname$::MergePartialFromCodedStream(\n"
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    ::google::protobuf::io::CodedInputStream* input) {\n"
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n"
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  ::google::protobuf::uint32 tag;\n"
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  while ((tag = input->ReadTag()) != 0) {\n",
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->field_count() > 0) {
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't even want to print the switch() if we have no fields because
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // MSVC dislikes switch() statements that contain only a default value.
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note:  If we just switched on the tag rather than the field number, we
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // could avoid the need for the if() to check the wire type at the beginning
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of each case.  However, this is actually a bit slower in practice as it
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // creates a jump table that is 8x larger and sparser, and meanwhile the
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if()s are highly predictable.
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n");
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_array<const FieldDescriptor*> ordered_fields(
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SortFieldsByNumber(descriptor_));
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < descriptor_->field_count(); i++) {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const FieldDescriptor* field = ordered_fields[i];
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintFieldComment(printer, field);
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "case $number$: {\n",
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "number", SimpleItoa(field->number()));
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Indent();
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const FieldGenerator& field_generator = field_generators_.get(field);
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Emit code to parse the common, expected case.
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n",
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]);
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > 0 || (field->is_repeated() && !field->options().packed())) {
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          " parse_$name$:\n",
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "name", field->name());
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Indent();
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->options().packed()) {
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_generator.GenerateMergeFromCodedStream(printer);
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Outdent();
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Emit code to parse unexpectedly packed or unpacked values.
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->is_packable() && field->options().packed()) {
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "           == ::google::protobuf::internal::WireFormatLite::\n"
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "              WIRETYPE_$wiretype$) {\n",
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "wiretype",
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]);
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_generator.GenerateMergeFromCodedStream(printer);
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Outdent();
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (field->is_packable() && !field->options().packed()) {
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "           == ::google::protobuf::internal::WireFormatLite::\n"
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "              WIRETYPE_LENGTH_DELIMITED) {\n");
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Outdent();
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "} else {\n"
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  goto handle_uninterpreted;\n"
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n");
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // switch() is slow since it can't be predicted well.  Insert some if()s
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // here that attempt to predict the next tag.
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->is_repeated() && !field->options().packed()) {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expect repeats of this field.
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (input->ExpectTag($tag$)) goto parse_$name$;\n",
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "tag", SimpleItoa(WireFormat::MakeTag(field)),
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "name", field->name());
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i + 1 < descriptor_->field_count()) {
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expect the next field in order.
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const FieldDescriptor* next_field = ordered_fields[i + 1];
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "next_name", next_field->name());
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expect EOF.
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(kenton):  Expect group end-tag?
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (input->ExpectAtEnd()) return true;\n");
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "break;\n");
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Outdent();
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("}\n\n");
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "default: {\n"
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "handle_uninterpreted:\n");
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Is this an end-group tag?  If so, this must be the end of the message.
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return true;\n"
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle extension ranges.
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "if (");
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < descriptor_->extension_range_count(); i++) {
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Descriptor::ExtensionRange* range =
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        descriptor_->extension_range(i);
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > 0) printer->Print(" ||\n    ");
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 start_tag = WireFormatLite::MakeTag(
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        range->start, static_cast<WireFormatLite::WireType>(0));
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 end_tag = WireFormatLite::MakeTag(
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        range->end, static_cast<WireFormatLite::WireType>(0));
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (range->end > FieldDescriptor::kMaxNumber) {
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "($start$u <= tag)",
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "start", SimpleItoa(start_tag));
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "($start$u <= tag && tag < $end$u)",
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "start", SimpleItoa(start_tag),
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "end", SimpleItoa(end_tag));
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(") {\n");
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasUnknownFields(descriptor_->file())) {
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintHandlingOptionalStaticInitializers(
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        descriptor_->file(), printer,
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // With static initializers.
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "                              mutable_unknown_fields()));\n",
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Without.
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "                              mutable_unknown_fields()));\n");
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintHandlingOptionalStaticInitializers(
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        descriptor_->file(), printer,
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // With static initializers.
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  DO_(_extensions_.ParseField(tag, input, default_instance_, NULL));\n",
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Without.
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  DO_(_extensions_.ParseField(tag, input, &default_instance(), NULL));\n");
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  continue;\n"
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We really don't recognize this tag.  Skip it.
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));\n");
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, NULL));\n");
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->field_count() > 0) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("break;\n");
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");    // default:
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");    // switch
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  }\n"                   // while
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return true;\n"
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "#undef DO_\n"
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::GenerateSerializeOneField(
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::Printer* printer, const FieldDescriptor* field, bool to_array) {
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrintFieldComment(printer, field);
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!field->is_repeated()) {
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "if (has_$name$()) {\n",
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "name", FieldName(field));
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (to_array) {
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer);
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!field->is_repeated()) {
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::GenerateSerializeOneExtensionRange(
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::Printer* printer, const Descriptor::ExtensionRange* range,
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool to_array) {
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["start"] = SimpleItoa(range->start);
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["end"] = SimpleItoa(range->end);
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// Extension range [$start$, $end$)\n");
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (to_array) {
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "target = _extensions_.SerializeWithCachedSizesToArray(\n"
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    $start$, $end$, target);\n\n");
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "_extensions_.SerializeWithCachedSizes(\n"
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    $start$, $end$, output);\n\n");
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSerializeWithCachedSizes(io::Printer* printer) {
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->options().message_set_wire_format()) {
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special-case MessageSet.
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "void $classname$::SerializeWithCachedSizes(\n"
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    ::google::protobuf::io::CodedOutputStream* output) const {\n"
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasUnknownFields(descriptor_->file())) {
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  ::google::protobuf::internal::WireFormatLite::SerializeUnknownMessageSetItems(\n"
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "      unknown_fields(), output);\n");
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "void $classname$::SerializeWithCachedSizes(\n"
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    ::google::protobuf::io::CodedOutputStream* output) const {\n",
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateSerializeWithCachedSizesBody(printer, false);
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->options().message_set_wire_format()) {
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special-case MessageSet.
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    ::google::protobuf::uint8* target) const {\n"
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  target =\n"
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "      _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasUnknownFields(descriptor_->file())) {
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  target = ::google::protobuf::internal::WireFormatLite::\n"
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "             SerializeUnknownMessageSetItemsToArray(\n"
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "               unknown_fields(), target);\n");
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return target;\n"
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    ::google::protobuf::uint8* target) const {\n",
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateSerializeWithCachedSizesBody(printer, true);
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return target;\n"
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_array<const FieldDescriptor*> ordered_fields(
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SortFieldsByNumber(descriptor_));
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const Descriptor::ExtensionRange*> sorted_extensions;
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sorted_extensions.push_back(descriptor_->extension_range(i));
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sort(sorted_extensions.begin(), sorted_extensions.end(),
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ExtensionRangeSorter());
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Merge the fields and the extension ranges, both sorted by field number.
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, j;
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0, j = 0;
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i < descriptor_->field_count() || j < sorted_extensions.size();
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ) {
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == descriptor_->field_count()) {
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSerializeOneExtensionRange(printer,
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sorted_extensions[j++],
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         to_array);
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (j == sorted_extensions.size()) {
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSerializeOneExtensionRange(printer,
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sorted_extensions[j++],
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         to_array);
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("if (!unknown_fields().empty()) {\n");
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (to_array) {
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "target = "
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(\n"
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "    unknown_fields(), target);\n");
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(\n"
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "    unknown_fields(), output);\n");
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateByteSize(io::Printer* printer) {
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->options().message_set_wire_format()) {
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Special-case MessageSet.
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "int $classname$::ByteSize() const {\n"
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  int total_size = _extensions_.MessageSetByteSize();\n",
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", classname_);
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasUnknownFields(descriptor_->file())) {
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "  total_size += ::google::protobuf::internal::WireFormatLite::\n"
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "      ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  _cached_size_ = total_size;\n"
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return total_size;\n"
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "int $classname$::ByteSize() const {\n",
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "int total_size = 0;\n"
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_index = -1;
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!field->is_repeated()) {
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See above in GenerateClear for an explanation of this.
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(kenton):  Share code?  Unclear how to do so without
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   over-engineering.
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((i / 8) != (last_index / 8) ||
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          last_index < 0) {
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (last_index >= 0) {
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Outdent();
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          printer->Print("}\n");
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "index", SimpleItoa(field->index()));
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Indent();
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_index = i;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintFieldComment(printer, field);
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if (has_$name$()) {\n",
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "name", FieldName(field));
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Indent();
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateByteSize(printer);
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Outdent();
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "}\n"
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "\n");
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (last_index >= 0) {
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeated fields don't use _has_bits_ so we count them in a separate
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pass.
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->is_repeated()) {
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PrintFieldComment(printer, field);
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_generators_.get(field).GenerateByteSize(printer);
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print("\n");
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "total_size += _extensions_.ByteSize();\n"
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n");
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasUnknownFields(descriptor_->file())) {
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("if (!unknown_fields().empty()) {\n");
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "total_size +=\n"
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  ::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(\n"
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    unknown_fields());\n");
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("}\n");
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We update _cached_size_ even though this is a const method.  In theory,
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is not thread-compatible, because concurrent writes have undefined
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // results.  In practice, since any concurrent writes will be writing the
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exact same value, it works on all common processors.  In a future version
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of C++, _cached_size_ should be made into an atomic<int>.
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "_cached_size_ = total_size;\n"
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "return total_size;\n");
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageGenerator::
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateIsInitialized(io::Printer* printer) {
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "bool $classname$::IsInitialized() const {\n",
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that all required fields in this message are set.  We can do this
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // most efficiently by checking 32 "has bits" at a time.
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < has_bits_array_size; i++) {
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 mask = 0;
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int bit = 0; bit < 32; bit++) {
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int index = i * 32 + bit;
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index >= descriptor_->field_count()) break;
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const FieldDescriptor* field = descriptor_->field(index);
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->is_required()) {
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mask |= 1 << bit;
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mask != 0) {
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char buffer[kFastToBufferSize];
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "i", SimpleItoa(i),
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "mask", FastHex32ToBuffer(mask, buffer));
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now check that all embedded messages are initialized.
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->field_count(); i++) {
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FieldDescriptor* field = descriptor_->field(i);
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
19853d4dfb6f11fb4e934d658743a8efc26d5490fdb0Ben Murdoch        !ShouldIgnoreRequiredFieldCheck(field) &&
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HasRequiredFields(field->message_type())) {
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (field->is_repeated()) {
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "for (int i = 0; i < $name$_size(); i++) {\n"
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "  if (!this->$name$(i).IsInitialized()) return false;\n"
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "}\n",
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "name", FieldName(field));
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "if (has_$name$()) {\n"
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "  if (!this->$name$().IsInitialized()) return false;\n"
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "}\n",
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "name", FieldName(field));
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->extension_range_count() > 0) {
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n"
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "if (!_extensions_.IsInitialized()) return false;");
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return true;\n"
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace cpp
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace compiler
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
2020