cpp_field.cc revision d0332953cda33fb4f8e24ebff9c49159b69c43d6
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32//  Based on original Protocol Buffers design by
33//  Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <google/protobuf/compiler/cpp/cpp_field.h>
36#include <google/protobuf/compiler/cpp/cpp_helpers.h>
37#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
38#include <google/protobuf/compiler/cpp/cpp_string_field.h>
39#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
40#include <google/protobuf/compiler/cpp/cpp_message_field.h>
41#include <google/protobuf/descriptor.pb.h>
42#include <google/protobuf/wire_format.h>
43#include <google/protobuf/io/printer.h>
44#include <google/protobuf/stubs/common.h>
45#include <google/protobuf/stubs/strutil.h>
46
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace cpp {
51
52using internal::WireFormat;
53
54void SetCommonFieldVariables(const FieldDescriptor* descriptor,
55                             map<string, string>* variables) {
56  (*variables)["name"] = FieldName(descriptor);
57  (*variables)["index"] = SimpleItoa(descriptor->index());
58  (*variables)["number"] = SimpleItoa(descriptor->number());
59  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
60  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
61
62  (*variables)["tag_size"] = SimpleItoa(
63    WireFormat::TagSize(descriptor->number(), descriptor->type()));
64  (*variables)["deprecation"] = descriptor->options().deprecated()
65      ? " PROTOBUF_DEPRECATED" : "";
66
67}
68
69FieldGenerator::~FieldGenerator() {}
70
71void FieldGenerator::
72GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
73  // Reaching here indicates a bug. Cases are:
74  //   - This FieldGenerator should support packing, but this method should be
75  //     overridden.
76  //   - This FieldGenerator doesn't support packing, and this method should
77  //     never have been called.
78  GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
79             << "called on field generator that does not support packing.";
80
81}
82
83FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
84  : descriptor_(descriptor),
85    field_generators_(
86      new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
87  // Construct all the FieldGenerators.
88  for (int i = 0; i < descriptor->field_count(); i++) {
89    field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
90  }
91}
92
93FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
94  if (field->is_repeated()) {
95    switch (field->cpp_type()) {
96      case FieldDescriptor::CPPTYPE_MESSAGE:
97        return new RepeatedMessageFieldGenerator(field);
98      case FieldDescriptor::CPPTYPE_STRING:
99        switch (field->options().ctype()) {
100          default:  // RepeatedStringFieldGenerator handles unknown ctypes.
101          case FieldOptions::STRING:
102            return new RepeatedStringFieldGenerator(field);
103        }
104      case FieldDescriptor::CPPTYPE_ENUM:
105        return new RepeatedEnumFieldGenerator(field);
106      default:
107        return new RepeatedPrimitiveFieldGenerator(field);
108    }
109  } else {
110    switch (field->cpp_type()) {
111      case FieldDescriptor::CPPTYPE_MESSAGE:
112        return new MessageFieldGenerator(field);
113      case FieldDescriptor::CPPTYPE_STRING:
114        switch (field->options().ctype()) {
115          default:  // StringFieldGenerator handles unknown ctypes.
116          case FieldOptions::STRING:
117            return new StringFieldGenerator(field);
118        }
119      case FieldDescriptor::CPPTYPE_ENUM:
120        return new EnumFieldGenerator(field);
121      default:
122        return new PrimitiveFieldGenerator(field);
123    }
124  }
125}
126
127FieldGeneratorMap::~FieldGeneratorMap() {}
128
129const FieldGenerator& FieldGeneratorMap::get(
130    const FieldDescriptor* field) const {
131  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
132  return *field_generators_[field->index()];
133}
134
135
136}  // namespace cpp
137}  // namespace compiler
138}  // namespace protobuf
139}  // namespace google
140