Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : // Author: 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 <memory>
37 : #ifndef _SHARED_PTR_H
38 : #include <google/protobuf/stubs/shared_ptr.h>
39 : #endif
40 :
41 : #include <google/protobuf/compiler/cpp/cpp_helpers.h>
42 : #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
43 : #include <google/protobuf/compiler/cpp/cpp_string_field.h>
44 : #include <google/protobuf/compiler/cpp/cpp_enum_field.h>
45 : #include <google/protobuf/compiler/cpp/cpp_map_field.h>
46 : #include <google/protobuf/compiler/cpp/cpp_message_field.h>
47 : #include <google/protobuf/descriptor.pb.h>
48 : #include <google/protobuf/wire_format.h>
49 : #include <google/protobuf/io/printer.h>
50 : #include <google/protobuf/stubs/logging.h>
51 : #include <google/protobuf/stubs/common.h>
52 : #include <google/protobuf/stubs/strutil.h>
53 :
54 : namespace google {
55 : namespace protobuf {
56 : namespace compiler {
57 : namespace cpp {
58 :
59 : using internal::WireFormat;
60 :
61 65534 : void SetCommonFieldVariables(const FieldDescriptor* descriptor,
62 : map<string, string>* variables,
63 : const Options& options) {
64 28086 : (*variables)["name"] = FieldName(descriptor);
65 28086 : (*variables)["index"] = SimpleItoa(descriptor->index());
66 28086 : (*variables)["number"] = SimpleItoa(descriptor->number());
67 28086 : (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
68 18724 : (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
69 :
70 : // non_null_ptr_to_name is usable only if has_$name$ is true. It yields a
71 : // pointer that will not be NULL. Subclasses of FieldGenerator may set
72 : // (*variables)["non_null_ptr_to_name"] differently.
73 46810 : (*variables)["non_null_ptr_to_name"] =
74 : StrCat("&this->", FieldName(descriptor), "()");
75 :
76 46810 : (*variables)["tag_size"] = SimpleItoa(
77 : WireFormat::TagSize(descriptor->number(), descriptor->type()));
78 18724 : (*variables)["deprecation"] = descriptor->options().deprecated()
79 : ? " PROTOBUF_DEPRECATED" : "";
80 :
81 18724 : (*variables)["cppget"] = "Get";
82 :
83 18724 : if (HasFieldPresence(descriptor->file())) {
84 13792 : (*variables)["set_hasbit"] =
85 27584 : "set_has_" + FieldName(descriptor) + "();";
86 13792 : (*variables)["clear_hasbit"] =
87 27584 : "clear_has_" + FieldName(descriptor) + "();";
88 : } else {
89 4932 : (*variables)["set_hasbit"] = "";
90 4932 : (*variables)["clear_hasbit"] = "";
91 : }
92 :
93 : // By default, empty string, so that generic code used for both oneofs and
94 : // singular fields can be written.
95 18724 : (*variables)["oneof_prefix"] = "";
96 9362 : }
97 :
98 182 : void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
99 : map<string, string>* variables) {
100 91 : const string prefix = descriptor->containing_oneof()->name() + "_.";
101 182 : (*variables)["oneof_prefix"] = prefix;
102 182 : (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
103 364 : (*variables)["non_null_ptr_to_name"] =
104 182 : StrCat(prefix, (*variables)["name"], "_");
105 91 : }
106 :
107 2525 : FieldGenerator::~FieldGenerator() {}
108 :
109 0 : void FieldGenerator::
110 : GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
111 : // Reaching here indicates a bug. Cases are:
112 : // - This FieldGenerator should support packing, but this method should be
113 : // overridden.
114 : // - This FieldGenerator doesn't support packing, and this method should
115 : // never have been called.
116 0 : GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
117 0 : << "called on field generator that does not support packing.";
118 :
119 0 : }
120 :
121 6292 : FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
122 : const Options& options)
123 : : descriptor_(descriptor),
124 : field_generators_(
125 3353 : new google::protobuf::scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
126 : // Construct all the FieldGenerators.
127 5878 : for (int i = 0; i < descriptor->field_count(); i++) {
128 7575 : field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
129 : }
130 414 : }
131 :
132 8303 : FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
133 : const Options& options) {
134 2525 : if (field->is_repeated()) {
135 938 : switch (field->cpp_type()) {
136 : case FieldDescriptor::CPPTYPE_MESSAGE:
137 217 : if (field->is_map()) {
138 123 : return new MapFieldGenerator(field, options);
139 : } else {
140 94 : return new RepeatedMessageFieldGenerator(field, options);
141 : }
142 : case FieldDescriptor::CPPTYPE_STRING:
143 38 : switch (field->options().ctype()) {
144 : default: // RepeatedStringFieldGenerator handles unknown ctypes.
145 : case FieldOptions::STRING:
146 38 : return new RepeatedStringFieldGenerator(field, options);
147 : }
148 : case FieldDescriptor::CPPTYPE_ENUM:
149 30 : return new RepeatedEnumFieldGenerator(field, options);
150 : default:
151 184 : return new RepeatedPrimitiveFieldGenerator(field, options);
152 : }
153 2056 : } else if (field->containing_oneof()) {
154 182 : switch (field->cpp_type()) {
155 : case FieldDescriptor::CPPTYPE_MESSAGE:
156 44 : return new MessageOneofFieldGenerator(field, options);
157 : case FieldDescriptor::CPPTYPE_STRING:
158 24 : switch (field->options().ctype()) {
159 : default: // StringOneofFieldGenerator handles unknown ctypes.
160 : case FieldOptions::STRING:
161 24 : return new StringOneofFieldGenerator(field, options);
162 : }
163 : case FieldDescriptor::CPPTYPE_ENUM:
164 10 : return new EnumOneofFieldGenerator(field, options);
165 : default:
166 13 : return new PrimitiveOneofFieldGenerator(field, options);
167 : }
168 : } else {
169 3930 : switch (field->cpp_type()) {
170 : case FieldDescriptor::CPPTYPE_MESSAGE:
171 243 : return new MessageFieldGenerator(field, options);
172 : case FieldDescriptor::CPPTYPE_STRING:
173 1135 : switch (field->options().ctype()) {
174 : default: // StringFieldGenerator handles unknown ctypes.
175 : case FieldOptions::STRING:
176 1135 : return new StringFieldGenerator(field, options);
177 : }
178 : case FieldDescriptor::CPPTYPE_ENUM:
179 57 : return new EnumFieldGenerator(field, options);
180 : default:
181 530 : return new PrimitiveFieldGenerator(field, options);
182 : }
183 : }
184 : }
185 :
186 414 : FieldGeneratorMap::~FieldGeneratorMap() {}
187 :
188 34359 : const FieldGenerator& FieldGeneratorMap::get(
189 34359 : const FieldDescriptor* field) const {
190 34359 : GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
191 103077 : return *field_generators_[field->index()];
192 : }
193 :
194 :
195 : } // namespace cpp
196 : } // namespace compiler
197 : } // namespace protobuf
198 : } // namespace google
|