blob: 51c5c6f5ec48ece3c3fd49d64df44ff719a9e49e [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_string_field.h>
36#include <google/protobuf/compiler/cpp/cpp_helpers.h>
37#include <google/protobuf/io/printer.h>
38#include <google/protobuf/wire_format_inl.h>
39#include <google/protobuf/descriptor.pb.h>
40#include <google/protobuf/stubs/strutil.h>
41
42namespace google {
43namespace protobuf {
44namespace compiler {
45namespace cpp {
46
47using internal::WireFormat;
48
49namespace {
50
51// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
52// repeat code between this and the other field types.
53void SetStringVariables(const FieldDescriptor* descriptor,
54 map<string, string>* variables) {
55 (*variables)["name"] = FieldName(descriptor);
56 (*variables)["default"] =
57 "\"" + CEscape(descriptor->default_value_string()) + "\"";
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 (*variables)["tag_size"] = SimpleItoa(
63 WireFormat::TagSize(descriptor->number(), descriptor->type()));
64}
65
66} // namespace
67
68// ===================================================================
69
70StringFieldGenerator::
71StringFieldGenerator(const FieldDescriptor* descriptor)
72 : descriptor_(descriptor) {
73 SetStringVariables(descriptor, &variables_);
74}
75
76StringFieldGenerator::~StringFieldGenerator() {}
77
78void StringFieldGenerator::
79GeneratePrivateMembers(io::Printer* printer) const {
80 printer->Print(variables_,
81 "::std::string* $name$_;\n"
82 "static const ::std::string _default_$name$_;\n");
83}
84
85void StringFieldGenerator::
86GenerateAccessorDeclarations(io::Printer* printer) const {
87 // If we're using StringFieldGenerator for a field with a ctype, it's
88 // because that ctype isn't actually implemented. In particular, this is
89 // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
90 // We aren't releasing Cord because it has too many Google-specific
91 // dependencies and we aren't releasing StringPiece because it's hardly
92 // useful outside of Google and because it would get confusing to have
93 // multiple instances of the StringPiece class in different libraries (PCRE
94 // already includes it for their C++ bindings, which came from Google).
95 //
96 // In any case, we make all the accessors private while still actually
97 // using a string to represent the field internally. This way, we can
98 // guarantee that if we do ever implement the ctype, it won't break any
99 // existing users who might be -- for whatever reason -- already using .proto
100 // files that applied the ctype. The field can still be accessed via the
101 // reflection interface since the reflection interface is independent of
102 // the string's underlying representation.
103 if (descriptor_->options().has_ctype()) {
104 printer->Outdent();
105 printer->Print(
106 " private:\n"
107 " // Hidden due to unknown ctype option.\n");
108 printer->Indent();
109 }
110
111 printer->Print(variables_,
112 "inline const ::std::string& $name$() const;\n"
temporalf2063512008-07-23 01:19:07 +0000113 "inline void set_$name$(const ::std::string& value);\n"
114 "inline void set_$name$(const char* value);\n");
temporal928ebb62008-07-16 02:00:27 +0000115 if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
116 printer->Print(variables_,
temporalf2063512008-07-23 01:19:07 +0000117 "inline void set_$name$(const void* value, size_t size);\n");
temporal928ebb62008-07-16 02:00:27 +0000118 }
temporal40ee5512008-07-10 02:12:20 +0000119
120 printer->Print(variables_,
121 "inline ::std::string* mutable_$name$();\n");
122
123 if (descriptor_->options().has_ctype()) {
124 printer->Outdent();
125 printer->Print(" public:\n");
126 printer->Indent();
127 }
128}
129
130void StringFieldGenerator::
131GenerateInlineAccessorDefinitions(io::Printer* printer) const {
132 printer->Print(variables_,
133 "inline const ::std::string& $classname$::$name$() const {\n"
134 " return *$name$_;\n"
135 "}\n"
136 "inline void $classname$::set_$name$(const ::std::string& value) {\n"
137 " _set_bit($index$);\n"
138 " if ($name$_ == &_default_$name$_) {\n"
139 " $name$_ = new ::std::string;\n"
140 " }\n"
141 " $name$_->assign(value);\n"
temporalf2063512008-07-23 01:19:07 +0000142 "}\n"
143 "inline void $classname$::set_$name$(const char* value) {\n"
144 " _set_bit($index$);\n"
145 " if ($name$_ == &_default_$name$_) {\n"
146 " $name$_ = new ::std::string;\n"
147 " }\n"
148 " $name$_->assign(value);\n"
temporal40ee5512008-07-10 02:12:20 +0000149 "}\n");
temporal928ebb62008-07-16 02:00:27 +0000150
151 if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
152 printer->Print(variables_,
temporalf2063512008-07-23 01:19:07 +0000153 "inline void $classname$::set_$name$(const void* value, size_t size) {\n"
temporal928ebb62008-07-16 02:00:27 +0000154 " _set_bit($index$);\n"
155 " if ($name$_ == &_default_$name$_) {\n"
156 " $name$_ = new ::std::string;\n"
157 " }\n"
temporalf2063512008-07-23 01:19:07 +0000158 " $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
temporal928ebb62008-07-16 02:00:27 +0000159 "}\n");
160 }
161
temporal40ee5512008-07-10 02:12:20 +0000162 printer->Print(variables_,
163 "inline ::std::string* $classname$::mutable_$name$() {\n"
164 " _set_bit($index$);\n"
165 " if ($name$_ == &_default_$name$_) {\n");
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000166 if (descriptor_->default_value_string().empty()) {
temporal40ee5512008-07-10 02:12:20 +0000167 printer->Print(variables_,
168 " $name$_ = new ::std::string;\n");
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000169 } else {
170 printer->Print(variables_,
171 " $name$_ = new ::std::string(_default_$name$_);\n");
temporal40ee5512008-07-10 02:12:20 +0000172 }
173 printer->Print(variables_,
174 " }\n"
175 " return $name$_;\n"
176 "}\n");
177}
178
179void StringFieldGenerator::
180GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000181 if (descriptor_->default_value_string().empty()) {
temporal40ee5512008-07-10 02:12:20 +0000182 printer->Print(variables_,
183 "const ::std::string $classname$::_default_$name$_;");
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000184 } else {
185 printer->Print(variables_,
186 "const ::std::string $classname$::_default_$name$_($default$);");
temporal40ee5512008-07-10 02:12:20 +0000187 }
188}
189
190void StringFieldGenerator::
191GenerateClearingCode(io::Printer* printer) const {
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000192 if (descriptor_->default_value_string().empty()) {
temporal40ee5512008-07-10 02:12:20 +0000193 printer->Print(variables_,
194 "if ($name$_ != &_default_$name$_) {\n"
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000195 " $name$_->clear();\n"
temporal40ee5512008-07-10 02:12:20 +0000196 "}\n");
197 } else {
198 printer->Print(variables_,
199 "if ($name$_ != &_default_$name$_) {\n"
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000200 " $name$_->assign(_default_$name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000201 "}\n");
202 }
203}
204
205void StringFieldGenerator::
206GenerateMergingCode(io::Printer* printer) const {
207 printer->Print(variables_, "set_$name$(from.$name$());\n");
208}
209
210void StringFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000211GenerateSwappingCode(io::Printer* printer) const {
212 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
213}
214
215void StringFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000216GenerateInitializer(io::Printer* printer) const {
217 printer->Print(variables_,
218 ",\n$name$_(const_cast< ::std::string*>(&_default_$name$_))");
219}
220
221void StringFieldGenerator::
222GenerateDestructorCode(io::Printer* printer) const {
223 printer->Print(variables_,
224 "if ($name$_ != &_default_$name$_) {\n"
225 " delete $name$_;\n"
226 "}\n");
227}
228
229void StringFieldGenerator::
230GenerateMergeFromCodedStream(io::Printer* printer) const {
231 printer->Print(variables_,
232 "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
233 "input, mutable_$name$()));\n");
234}
235
236void StringFieldGenerator::
237GenerateSerializeWithCachedSizes(io::Printer* printer) const {
238 printer->Print(variables_,
239 "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
240 "$number$, this->$name$(), output));\n");
241}
242
243void StringFieldGenerator::
244GenerateByteSize(io::Printer* printer) const {
245 printer->Print(variables_,
246 "total_size += $tag_size$ +\n"
247 " ::google::protobuf::internal::WireFormat::$declared_type$Size(this->$name$());\n");
248}
249
250// ===================================================================
251
252RepeatedStringFieldGenerator::
253RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
254 : descriptor_(descriptor) {
255 SetStringVariables(descriptor, &variables_);
256}
257
258RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
259
260void RepeatedStringFieldGenerator::
261GeneratePrivateMembers(io::Printer* printer) const {
262 printer->Print(variables_,
263 "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
264}
265
266void RepeatedStringFieldGenerator::
267GenerateAccessorDeclarations(io::Printer* printer) const {
268 // See comment above about unknown ctypes.
269 if (descriptor_->options().has_ctype()) {
270 printer->Outdent();
271 printer->Print(
272 " private:\n"
273 " // Hidden due to unknown ctype option.\n");
274 printer->Indent();
275 }
276
277 printer->Print(variables_,
278 "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const;\n"
279 "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$();\n"
280 "inline const ::std::string& $name$(int index) const;\n"
281 "inline ::std::string* mutable_$name$(int index);\n"
282 "inline void set_$name$(int index, const ::std::string& value);\n"
temporalf2063512008-07-23 01:19:07 +0000283 "inline void set_$name$(int index, const char* value);\n"
temporal40ee5512008-07-10 02:12:20 +0000284 "inline ::std::string* add_$name$();\n"
temporalf2063512008-07-23 01:19:07 +0000285 "inline void add_$name$(const ::std::string& value);\n"
286 "inline void add_$name$(const char* value);\n");
temporal928ebb62008-07-16 02:00:27 +0000287
288 if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
289 printer->Print(variables_,
temporalf2063512008-07-23 01:19:07 +0000290 "inline void set_$name$(int index, const void* value, size_t size);\n"
291 "inline void add_$name$(const void* value, size_t size);\n");
temporal928ebb62008-07-16 02:00:27 +0000292 }
temporal40ee5512008-07-10 02:12:20 +0000293
294 if (descriptor_->options().has_ctype()) {
295 printer->Outdent();
296 printer->Print(" public:\n");
297 printer->Indent();
298 }
299}
300
301void RepeatedStringFieldGenerator::
302GenerateInlineAccessorDefinitions(io::Printer* printer) const {
303 printer->Print(variables_,
304 "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
305 "$classname$::$name$() const {\n"
306 " return $name$_;\n"
307 "}\n"
308 "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
309 "$classname$::mutable_$name$() {\n"
310 " return &$name$_;\n"
311 "}\n"
312 "inline const ::std::string& $classname$::$name$(int index) const {\n"
313 " return $name$_.Get(index);\n"
314 "}\n"
315 "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
316 " return $name$_.Mutable(index);\n"
317 "}\n"
318 "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
319 " $name$_.Mutable(index)->assign(value);\n"
320 "}\n"
temporalf2063512008-07-23 01:19:07 +0000321 "inline void $classname$::set_$name$(int index, const char* value) {\n"
322 " $name$_.Mutable(index)->assign(value);\n"
323 "}\n"
temporal40ee5512008-07-10 02:12:20 +0000324 "inline ::std::string* $classname$::add_$name$() {\n"
325 " return $name$_.Add();\n"
326 "}\n"
327 "inline void $classname$::add_$name$(const ::std::string& value) {\n"
328 " $name$_.Add()->assign(value);\n"
temporalf2063512008-07-23 01:19:07 +0000329 "}\n"
330 "inline void $classname$::add_$name$(const char* value) {\n"
331 " $name$_.Add()->assign(value);\n"
temporal40ee5512008-07-10 02:12:20 +0000332 "}\n");
temporal928ebb62008-07-16 02:00:27 +0000333
334 if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
335 printer->Print(variables_,
336 "inline void "
temporalf2063512008-07-23 01:19:07 +0000337 "$classname$::set_$name$(int index, const void* value, size_t size) {\n"
338 " $name$_.Mutable(index)->assign(\n"
339 " reinterpret_cast<const char*>(value), size);\n"
temporal928ebb62008-07-16 02:00:27 +0000340 "}\n"
temporalf2063512008-07-23 01:19:07 +0000341 "inline void $classname$::add_$name$(const void* value, size_t size) {\n"
342 " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
temporal928ebb62008-07-16 02:00:27 +0000343 "}\n");
344 }
temporal40ee5512008-07-10 02:12:20 +0000345}
346
347void RepeatedStringFieldGenerator::
348GenerateClearingCode(io::Printer* printer) const {
349 printer->Print(variables_, "$name$_.Clear();\n");
350}
351
352void RepeatedStringFieldGenerator::
353GenerateMergingCode(io::Printer* printer) const {
354 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
355}
356
357void RepeatedStringFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000358GenerateSwappingCode(io::Printer* printer) const {
359 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
360}
361
362void RepeatedStringFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000363GenerateInitializer(io::Printer* printer) const {
kenton@google.comeb26a1e2009-04-16 22:43:40 +0000364 printer->Print(variables_, ",\n$name$_()");
temporal40ee5512008-07-10 02:12:20 +0000365}
366
367void RepeatedStringFieldGenerator::
368GenerateMergeFromCodedStream(io::Printer* printer) const {
369 printer->Print(variables_,
370 "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
371 " input, add_$name$()));\n");
372}
373
374void RepeatedStringFieldGenerator::
375GenerateSerializeWithCachedSizes(io::Printer* printer) const {
376 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000377 "for (int i = 0; i < this->$name$_size(); i++) {\n"
378 " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
379 "$number$, this->$name$(i), output));\n"
380 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000381}
382
383void RepeatedStringFieldGenerator::
384GenerateByteSize(io::Printer* printer) const {
385 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000386 "total_size += $tag_size$ * this->$name$_size();\n"
387 "for (int i = 0; i < this->$name$_size(); i++) {\n"
temporal40ee5512008-07-10 02:12:20 +0000388 " total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
389 " this->$name$(i));\n"
390 "}\n");
391}
392
393} // namespace cpp
394} // namespace compiler
395} // namespace protobuf
396} // namespace google