blob: a369f41781833842d825d310717d5447b0e8e642 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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_enum_field.h>
36#include <google/protobuf/compiler/cpp/cpp_helpers.h>
37#include <google/protobuf/io/printer.h>
kenton@google.com80b1d622009-07-29 01:13:20 +000038#include <google/protobuf/descriptor.pb.h>
temporal40ee5512008-07-10 02:12:20 +000039#include <google/protobuf/stubs/strutil.h>
40
41namespace google {
42namespace protobuf {
43namespace compiler {
44namespace cpp {
45
temporal40ee5512008-07-10 02:12:20 +000046namespace {
47
temporal40ee5512008-07-10 02:12:20 +000048void SetEnumVariables(const FieldDescriptor* descriptor,
49 map<string, string>* variables) {
kenton@google.com80b1d622009-07-29 01:13:20 +000050 SetCommonFieldVariables(descriptor, variables);
temporal40ee5512008-07-10 02:12:20 +000051 const EnumValueDescriptor* default_value = descriptor->default_value_enum();
temporal40ee5512008-07-10 02:12:20 +000052 (*variables)["type"] = ClassName(descriptor->enum_type(), true);
53 (*variables)["default"] = SimpleItoa(default_value->number());
temporal40ee5512008-07-10 02:12:20 +000054}
55
56} // namespace
57
58// ===================================================================
59
60EnumFieldGenerator::
61EnumFieldGenerator(const FieldDescriptor* descriptor)
62 : descriptor_(descriptor) {
63 SetEnumVariables(descriptor, &variables_);
64}
65
66EnumFieldGenerator::~EnumFieldGenerator() {}
67
68void EnumFieldGenerator::
69GeneratePrivateMembers(io::Printer* printer) const {
70 printer->Print(variables_, "int $name$_;\n");
71}
72
73void EnumFieldGenerator::
74GenerateAccessorDeclarations(io::Printer* printer) const {
75 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +000076 "inline $type$ $name$() const$deprecation$;\n"
77 "inline void set_$name$($type$ value)$deprecation$;\n");
temporal40ee5512008-07-10 02:12:20 +000078}
79
80void EnumFieldGenerator::
81GenerateInlineAccessorDefinitions(io::Printer* printer) const {
82 printer->Print(variables_,
83 "inline $type$ $classname$::$name$() const {\n"
84 " return static_cast< $type$ >($name$_);\n"
85 "}\n"
86 "inline void $classname$::set_$name$($type$ value) {\n"
87 " GOOGLE_DCHECK($type$_IsValid(value));\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +000088 " set_has_$name$();\n"
temporal40ee5512008-07-10 02:12:20 +000089 " $name$_ = value;\n"
90 "}\n");
91}
92
93void EnumFieldGenerator::
94GenerateClearingCode(io::Printer* printer) const {
95 printer->Print(variables_, "$name$_ = $default$;\n");
96}
97
98void EnumFieldGenerator::
99GenerateMergingCode(io::Printer* printer) const {
100 printer->Print(variables_, "set_$name$(from.$name$());\n");
101}
102
103void EnumFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000104GenerateSwappingCode(io::Printer* printer) const {
105 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
106}
107
108void EnumFieldGenerator::
kenton@google.comd37d46d2009-04-25 02:53:47 +0000109GenerateConstructorCode(io::Printer* printer) const {
110 printer->Print(variables_, "$name$_ = $default$;\n");
temporal40ee5512008-07-10 02:12:20 +0000111}
112
113void EnumFieldGenerator::
114GenerateMergeFromCodedStream(io::Printer* printer) const {
115 printer->Print(variables_,
116 "int value;\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000117 "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
118 " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
119 " input, &value)));\n"
temporal40ee5512008-07-10 02:12:20 +0000120 "if ($type$_IsValid(value)) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000121 " set_$name$(static_cast< $type$ >(value));\n");
122 if (HasUnknownFields(descriptor_->file())) {
123 printer->Print(variables_,
124 "} else {\n"
125 " mutable_unknown_fields()->AddVarint($number$, value);\n");
126 }
127 printer->Print(variables_,
temporal40ee5512008-07-10 02:12:20 +0000128 "}\n");
129}
130
131void EnumFieldGenerator::
132GenerateSerializeWithCachedSizes(io::Printer* printer) const {
133 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000134 "::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
135 " $number$, this->$name$(), output);\n");
kenton@google.comd37d46d2009-04-25 02:53:47 +0000136}
137
138void EnumFieldGenerator::
139GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
140 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000141 "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
142 " $number$, this->$name$(), target);\n");
temporal40ee5512008-07-10 02:12:20 +0000143}
144
145void EnumFieldGenerator::
146GenerateByteSize(io::Printer* printer) const {
147 printer->Print(variables_,
148 "total_size += $tag_size$ +\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000149 " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
temporal40ee5512008-07-10 02:12:20 +0000150}
151
152// ===================================================================
153
154RepeatedEnumFieldGenerator::
155RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
156 : descriptor_(descriptor) {
157 SetEnumVariables(descriptor, &variables_);
158}
159
160RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
161
162void RepeatedEnumFieldGenerator::
163GeneratePrivateMembers(io::Printer* printer) const {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000164 printer->Print(variables_,
165 "::google::protobuf::RepeatedField<int> $name$_;\n");
kenton@google.com80b1d622009-07-29 01:13:20 +0000166 if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000167 printer->Print(variables_,
168 "mutable int _$name$_cached_byte_size_;\n");
169 }
temporal40ee5512008-07-10 02:12:20 +0000170}
171
172void RepeatedEnumFieldGenerator::
173GenerateAccessorDeclarations(io::Printer* printer) const {
174 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000175 "inline $type$ $name$(int index) const$deprecation$;\n"
176 "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
177 "inline void add_$name$($type$ value)$deprecation$;\n");
kenton@google.comfccb1462009-12-18 02:11:36 +0000178 printer->Print(variables_,
179 "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
180 "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
temporal40ee5512008-07-10 02:12:20 +0000181}
182
183void RepeatedEnumFieldGenerator::
184GenerateInlineAccessorDefinitions(io::Printer* printer) const {
185 printer->Print(variables_,
temporal40ee5512008-07-10 02:12:20 +0000186 "inline $type$ $classname$::$name$(int index) const {\n"
187 " return static_cast< $type$ >($name$_.Get(index));\n"
188 "}\n"
189 "inline void $classname$::set_$name$(int index, $type$ value) {\n"
190 " GOOGLE_DCHECK($type$_IsValid(value));\n"
191 " $name$_.Set(index, value);\n"
192 "}\n"
193 "inline void $classname$::add_$name$($type$ value) {\n"
194 " GOOGLE_DCHECK($type$_IsValid(value));\n"
195 " $name$_.Add(value);\n"
196 "}\n");
kenton@google.comfccb1462009-12-18 02:11:36 +0000197 printer->Print(variables_,
198 "inline const ::google::protobuf::RepeatedField<int>&\n"
199 "$classname$::$name$() const {\n"
200 " return $name$_;\n"
201 "}\n"
202 "inline ::google::protobuf::RepeatedField<int>*\n"
203 "$classname$::mutable_$name$() {\n"
204 " return &$name$_;\n"
205 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000206}
207
208void RepeatedEnumFieldGenerator::
209GenerateClearingCode(io::Printer* printer) const {
210 printer->Print(variables_, "$name$_.Clear();\n");
211}
212
213void RepeatedEnumFieldGenerator::
214GenerateMergingCode(io::Printer* printer) const {
215 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
216}
217
218void RepeatedEnumFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000219GenerateSwappingCode(io::Printer* printer) const {
220 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
221}
222
223void RepeatedEnumFieldGenerator::
kenton@google.comd37d46d2009-04-25 02:53:47 +0000224GenerateConstructorCode(io::Printer* printer) const {
225 // Not needed for repeated fields.
temporal40ee5512008-07-10 02:12:20 +0000226}
227
228void RepeatedEnumFieldGenerator::
229GenerateMergeFromCodedStream(io::Printer* printer) const {
kenton@google.comfccb1462009-12-18 02:11:36 +0000230 // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
231 printer->Print(variables_,
232 "int value;\n"
233 "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
234 " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
235 " input, &value)));\n"
236 "if ($type$_IsValid(value)) {\n"
237 " add_$name$(static_cast< $type$ >(value));\n");
238 if (HasUnknownFields(descriptor_->file())) {
239 printer->Print(variables_,
240 "} else {\n"
241 " mutable_unknown_fields()->AddVarint($number$, value);\n");
242 }
243 printer->Print("}\n");
244}
245
246void RepeatedEnumFieldGenerator::
247GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
248 if (!descriptor_->options().packed()) {
249 // We use a non-inlined implementation in this case, since this path will
250 // rarely be executed.
251 printer->Print(variables_,
252 "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
253 " input,\n"
254 " &$type$_IsValid,\n"
255 " this->mutable_$name$())));\n");
256 } else {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000257 printer->Print(variables_,
258 "::google::protobuf::uint32 length;\n"
259 "DO_(input->ReadVarint32(&length));\n"
260 "::google::protobuf::io::CodedInputStream::Limit limit = "
261 "input->PushLimit(length);\n"
262 "while (input->BytesUntilLimit() > 0) {\n"
263 " int value;\n"
kenton@google.comfccb1462009-12-18 02:11:36 +0000264 " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
265 " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
266 " input, &value)));\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000267 " if ($type$_IsValid(value)) {\n"
268 " add_$name$(static_cast< $type$ >(value));\n"
269 " }\n"
270 "}\n"
271 "input->PopLimit(limit);\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000272 }
temporal40ee5512008-07-10 02:12:20 +0000273}
274
275void RepeatedEnumFieldGenerator::
276GenerateSerializeWithCachedSizes(io::Printer* printer) const {
kenton@google.com2d6daa72009-01-22 01:27:00 +0000277 if (descriptor_->options().packed()) {
278 // Write the tag and the size.
279 printer->Print(variables_,
280 "if (this->$name$_size() > 0) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000281 " ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
282 " $number$,\n"
283 " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
284 " output);\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000285 " output->WriteVarint32(_$name$_cached_byte_size_);\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000286 "}\n");
287 }
temporal40ee5512008-07-10 02:12:20 +0000288 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000289 "for (int i = 0; i < this->$name$_size(); i++) {\n");
290 if (descriptor_->options().packed()) {
291 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000292 " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
293 " this->$name$(i), output);\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000294 } else {
295 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000296 " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
297 " $number$, this->$name$(i), output);\n");
kenton@google.comd37d46d2009-04-25 02:53:47 +0000298 }
299 printer->Print("}\n");
300}
301
302void RepeatedEnumFieldGenerator::
303GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
304 if (descriptor_->options().packed()) {
305 // Write the tag and the size.
306 printer->Print(variables_,
307 "if (this->$name$_size() > 0) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000308 " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
309 " $number$,\n"
310 " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
311 " target);\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000312 " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
kenton@google.com80b1d622009-07-29 01:13:20 +0000313 " _$name$_cached_byte_size_, target);\n"
kenton@google.comd37d46d2009-04-25 02:53:47 +0000314 "}\n");
315 }
316 printer->Print(variables_,
317 "for (int i = 0; i < this->$name$_size(); i++) {\n");
318 if (descriptor_->options().packed()) {
319 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000320 " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
321 " this->$name$(i), target);\n");
kenton@google.comd37d46d2009-04-25 02:53:47 +0000322 } else {
323 printer->Print(variables_,
kenton@google.com80b1d622009-07-29 01:13:20 +0000324 " target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
325 " $number$, this->$name$(i), target);\n");
kenton@google.com2d6daa72009-01-22 01:27:00 +0000326 }
327 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000328}
329
330void RepeatedEnumFieldGenerator::
331GenerateByteSize(io::Printer* printer) const {
332 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000333 "{\n"
334 " int data_size = 0;\n");
335 printer->Indent();
336 printer->Print(variables_,
337 "for (int i = 0; i < this->$name$_size(); i++) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000338 " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000339 " this->$name$(i));\n"
340 "}\n");
341
342 if (descriptor_->options().packed()) {
343 printer->Print(variables_,
344 "if (data_size > 0) {\n"
kenton@google.com80b1d622009-07-29 01:13:20 +0000345 " total_size += $tag_size$ +\n"
346 " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
kenton@google.com2d6daa72009-01-22 01:27:00 +0000347 "}\n"
348 "_$name$_cached_byte_size_ = data_size;\n"
349 "total_size += data_size;\n");
350 } else {
351 printer->Print(variables_,
352 "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
353 }
354 printer->Outdent();
355 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000356}
357
358} // namespace cpp
359} // namespace compiler
360} // namespace protobuf
361} // namespace google