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                             const Options& options) {
57  (*variables)["name"] = FieldName(descriptor);
58  (*variables)["index"] = SimpleItoa(descriptor->index());
59  (*variables)["number"] = SimpleItoa(descriptor->number());
60  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
61  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
62
63  (*variables)["tag_size"] = SimpleItoa(
64    WireFormat::TagSize(descriptor->number(), descriptor->type()));
65  (*variables)["deprecation"] = descriptor->options().deprecated()
66      ? " PROTOBUF_DEPRECATED" : "";
67
68  (*variables)["cppget"] = "Get";
69}
70
71FieldGenerator::~FieldGenerator() {}
72
73void FieldGenerator::
74GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
75  // Reaching here indicates a bug. Cases are:
76  //   - This FieldGenerator should support packing, but this method should be
77  //     overridden.
78  //   - This FieldGenerator doesn't support packing, and this method should
79  //     never have been called.
80  GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
81             << "called on field generator that does not support packing.";
82
83}
84
85FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
86                                     const Options& options)
87  : descriptor_(descriptor),
88    field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
89  // Construct all the FieldGenerators.
90  for (int i = 0; i < descriptor->field_count(); i++) {
91    field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
92  }
93}
94
95FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
96                                                 const Options& options) {
97  if (field->is_repeated()) {
98    switch (field->cpp_type()) {
99      case FieldDescriptor::CPPTYPE_MESSAGE:
100        return new RepeatedMessageFieldGenerator(field, options);
101      case FieldDescriptor::CPPTYPE_STRING:
102        switch (field->options().ctype()) {
103          default:  // RepeatedStringFieldGenerator handles unknown ctypes.
104          case FieldOptions::STRING:
105            return new RepeatedStringFieldGenerator(field, options);
106        }
107      case FieldDescriptor::CPPTYPE_ENUM:
108        return new RepeatedEnumFieldGenerator(field, options);
109      default:
110        return new RepeatedPrimitiveFieldGenerator(field, options);
111    }
112  } else {
113    switch (field->cpp_type()) {
114      case FieldDescriptor::CPPTYPE_MESSAGE:
115        return new MessageFieldGenerator(field, options);
116      case FieldDescriptor::CPPTYPE_STRING:
117        switch (field->options().ctype()) {
118          default:  // StringFieldGenerator handles unknown ctypes.
119          case FieldOptions::STRING:
120            return new StringFieldGenerator(field, options);
121        }
122      case FieldDescriptor::CPPTYPE_ENUM:
123        return new EnumFieldGenerator(field, options);
124      default:
125        return new PrimitiveFieldGenerator(field, options);
126    }
127  }
128}
129
130FieldGeneratorMap::~FieldGeneratorMap() {}
131
132const FieldGenerator& FieldGeneratorMap::get(
133    const FieldDescriptor* field) const {
134  GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
135  return *field_generators_[field->index()];
136}
137
138
139}  // namespace cpp
140}  // namespace compiler
141}  // namespace protobuf
142}  // namespace google
143