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_string_field.h>
36 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/descriptor.pb.h>
39 #include <google/protobuf/stubs/strutil.h>
40
41 namespace google {
42 namespace protobuf {
43 namespace compiler {
44 namespace cpp {
45
46 namespace {
47
SetStringVariables(const FieldDescriptor * descriptor,map<string,string> * variables,const Options & options)48 void SetStringVariables(const FieldDescriptor* descriptor,
49 map<string, string>* variables,
50 const Options& options) {
51 SetCommonFieldVariables(descriptor, variables, options);
52 (*variables)["default"] = DefaultValue(descriptor);
53 (*variables)["default_length"] =
54 SimpleItoa(descriptor->default_value_string().length());
55 (*variables)["default_variable"] = descriptor->default_value_string().empty()
56 ? "&::google::protobuf::internal::kEmptyString"
57 : "_default_" + FieldName(descriptor) + "_";
58 (*variables)["pointer_type"] =
59 descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
60 }
61
62 } // namespace
63
64 // ===================================================================
65
66 StringFieldGenerator::
StringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)67 StringFieldGenerator(const FieldDescriptor* descriptor,
68 const Options& options)
69 : descriptor_(descriptor) {
70 SetStringVariables(descriptor, &variables_, options);
71 }
72
~StringFieldGenerator()73 StringFieldGenerator::~StringFieldGenerator() {}
74
75 void StringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const76 GeneratePrivateMembers(io::Printer* printer) const {
77 printer->Print(variables_, "::std::string* $name$_;\n");
78 if (!descriptor_->default_value_string().empty()) {
79 printer->Print(variables_, "static ::std::string* $default_variable$;\n");
80 }
81 }
82
83 void StringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const84 GenerateAccessorDeclarations(io::Printer* printer) const {
85 // If we're using StringFieldGenerator for a field with a ctype, it's
86 // because that ctype isn't actually implemented. In particular, this is
87 // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
88 // We aren't releasing Cord because it has too many Google-specific
89 // dependencies and we aren't releasing StringPiece because it's hardly
90 // useful outside of Google and because it would get confusing to have
91 // multiple instances of the StringPiece class in different libraries (PCRE
92 // already includes it for their C++ bindings, which came from Google).
93 //
94 // In any case, we make all the accessors private while still actually
95 // using a string to represent the field internally. This way, we can
96 // guarantee that if we do ever implement the ctype, it won't break any
97 // existing users who might be -- for whatever reason -- already using .proto
98 // files that applied the ctype. The field can still be accessed via the
99 // reflection interface since the reflection interface is independent of
100 // the string's underlying representation.
101 if (descriptor_->options().ctype() != FieldOptions::STRING) {
102 printer->Outdent();
103 printer->Print(
104 " private:\n"
105 " // Hidden due to unknown ctype option.\n");
106 printer->Indent();
107 }
108
109 printer->Print(variables_,
110 "inline const ::std::string& $name$() const$deprecation$;\n"
111 "inline void set_$name$(const ::std::string& value)$deprecation$;\n"
112 "inline void set_$name$(const char* value)$deprecation$;\n"
113 "inline void set_$name$(const $pointer_type$* value, size_t size)"
114 "$deprecation$;\n"
115 "inline ::std::string* mutable_$name$()$deprecation$;\n"
116 "inline ::std::string* release_$name$()$deprecation$;\n"
117 "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
118
119
120 if (descriptor_->options().ctype() != FieldOptions::STRING) {
121 printer->Outdent();
122 printer->Print(" public:\n");
123 printer->Indent();
124 }
125 }
126
127 void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const128 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
129 printer->Print(variables_,
130 "inline const ::std::string& $classname$::$name$() const {\n"
131 " return *$name$_;\n"
132 "}\n"
133 "inline void $classname$::set_$name$(const ::std::string& value) {\n"
134 " set_has_$name$();\n"
135 " if ($name$_ == $default_variable$) {\n"
136 " $name$_ = new ::std::string;\n"
137 " }\n"
138 " $name$_->assign(value);\n"
139 "}\n"
140 "inline void $classname$::set_$name$(const char* value) {\n"
141 " set_has_$name$();\n"
142 " if ($name$_ == $default_variable$) {\n"
143 " $name$_ = new ::std::string;\n"
144 " }\n"
145 " $name$_->assign(value);\n"
146 "}\n"
147 "inline "
148 "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
149 " set_has_$name$();\n"
150 " if ($name$_ == $default_variable$) {\n"
151 " $name$_ = new ::std::string;\n"
152 " }\n"
153 " $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
154 "}\n"
155 "inline ::std::string* $classname$::mutable_$name$() {\n"
156 " set_has_$name$();\n"
157 " if ($name$_ == $default_variable$) {\n");
158 if (descriptor_->default_value_string().empty()) {
159 printer->Print(variables_,
160 " $name$_ = new ::std::string;\n");
161 } else {
162 printer->Print(variables_,
163 " $name$_ = new ::std::string(*$default_variable$);\n");
164 }
165 printer->Print(variables_,
166 " }\n"
167 " return $name$_;\n"
168 "}\n"
169 "inline ::std::string* $classname$::release_$name$() {\n"
170 " clear_has_$name$();\n"
171 " if ($name$_ == $default_variable$) {\n"
172 " return NULL;\n"
173 " } else {\n"
174 " ::std::string* temp = $name$_;\n"
175 " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
176 " return temp;\n"
177 " }\n"
178 "}\n"
179 "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
180 " if ($name$_ != $default_variable$) {\n"
181 " delete $name$_;\n"
182 " }\n"
183 " if ($name$) {\n"
184 " set_has_$name$();\n"
185 " $name$_ = $name$;\n"
186 " } else {\n"
187 " clear_has_$name$();\n"
188 " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
189 " }\n"
190 "}\n");
191 }
192
193 void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const194 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
195 if (!descriptor_->default_value_string().empty()) {
196 // Initialized in GenerateDefaultInstanceAllocator.
197 printer->Print(variables_,
198 "::std::string* $classname$::$default_variable$ = NULL;\n");
199 }
200 }
201
202 void StringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const203 GenerateClearingCode(io::Printer* printer) const {
204 if (descriptor_->default_value_string().empty()) {
205 printer->Print(variables_,
206 "if ($name$_ != $default_variable$) {\n"
207 " $name$_->clear();\n"
208 "}\n");
209 } else {
210 printer->Print(variables_,
211 "if ($name$_ != $default_variable$) {\n"
212 " $name$_->assign(*$default_variable$);\n"
213 "}\n");
214 }
215 }
216
217 void StringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const218 GenerateMergingCode(io::Printer* printer) const {
219 printer->Print(variables_, "set_$name$(from.$name$());\n");
220 }
221
222 void StringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const223 GenerateSwappingCode(io::Printer* printer) const {
224 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
225 }
226
227 void StringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const228 GenerateConstructorCode(io::Printer* printer) const {
229 printer->Print(variables_,
230 "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
231 }
232
233 void StringFieldGenerator::
GenerateDestructorCode(io::Printer * printer) const234 GenerateDestructorCode(io::Printer* printer) const {
235 printer->Print(variables_,
236 "if ($name$_ != $default_variable$) {\n"
237 " delete $name$_;\n"
238 "}\n");
239 }
240
241 void StringFieldGenerator::
GenerateDefaultInstanceAllocator(io::Printer * printer) const242 GenerateDefaultInstanceAllocator(io::Printer* printer) const {
243 if (!descriptor_->default_value_string().empty()) {
244 printer->Print(variables_,
245 "$classname$::$default_variable$ =\n"
246 " new ::std::string($default$, $default_length$);\n");
247 }
248 }
249
250 void StringFieldGenerator::
GenerateShutdownCode(io::Printer * printer) const251 GenerateShutdownCode(io::Printer* printer) const {
252 if (!descriptor_->default_value_string().empty()) {
253 printer->Print(variables_,
254 "delete $classname$::$default_variable$;\n");
255 }
256 }
257
258 void StringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const259 GenerateMergeFromCodedStream(io::Printer* printer) const {
260 printer->Print(variables_,
261 "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
262 " input, this->mutable_$name$()));\n");
263 if (HasUtf8Verification(descriptor_->file()) &&
264 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
265 printer->Print(variables_,
266 "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
267 " this->$name$().data(), this->$name$().length(),\n"
268 " ::google::protobuf::internal::WireFormat::PARSE);\n");
269 }
270 }
271
272 void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const273 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
274 if (HasUtf8Verification(descriptor_->file()) &&
275 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
276 printer->Print(variables_,
277 "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
278 " this->$name$().data(), this->$name$().length(),\n"
279 " ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
280 }
281 printer->Print(variables_,
282 "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
283 " $number$, this->$name$(), output);\n");
284 }
285
286 void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const287 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
288 if (HasUtf8Verification(descriptor_->file()) &&
289 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
290 printer->Print(variables_,
291 "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
292 " this->$name$().data(), this->$name$().length(),\n"
293 " ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
294 }
295 printer->Print(variables_,
296 "target =\n"
297 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
298 " $number$, this->$name$(), target);\n");
299 }
300
301 void StringFieldGenerator::
GenerateByteSize(io::Printer * printer) const302 GenerateByteSize(io::Printer* printer) const {
303 printer->Print(variables_,
304 "total_size += $tag_size$ +\n"
305 " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
306 " this->$name$());\n");
307 }
308
309 // ===================================================================
310
311 RepeatedStringFieldGenerator::
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)312 RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
313 const Options& options)
314 : descriptor_(descriptor) {
315 SetStringVariables(descriptor, &variables_, options);
316 }
317
~RepeatedStringFieldGenerator()318 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
319
320 void RepeatedStringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const321 GeneratePrivateMembers(io::Printer* printer) const {
322 printer->Print(variables_,
323 "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
324 }
325
326 void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const327 GenerateAccessorDeclarations(io::Printer* printer) const {
328 // See comment above about unknown ctypes.
329 if (descriptor_->options().ctype() != FieldOptions::STRING) {
330 printer->Outdent();
331 printer->Print(
332 " private:\n"
333 " // Hidden due to unknown ctype option.\n");
334 printer->Indent();
335 }
336
337 printer->Print(variables_,
338 "inline const ::std::string& $name$(int index) const$deprecation$;\n"
339 "inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
340 "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
341 "inline void set_$name$(int index, const char* value)$deprecation$;\n"
342 "inline "
343 "void set_$name$(int index, const $pointer_type$* value, size_t size)"
344 "$deprecation$;\n"
345 "inline ::std::string* add_$name$()$deprecation$;\n"
346 "inline void add_$name$(const ::std::string& value)$deprecation$;\n"
347 "inline void add_$name$(const char* value)$deprecation$;\n"
348 "inline void add_$name$(const $pointer_type$* value, size_t size)"
349 "$deprecation$;\n");
350
351 printer->Print(variables_,
352 "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
353 "$deprecation$;\n"
354 "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
355 "$deprecation$;\n");
356
357 if (descriptor_->options().ctype() != FieldOptions::STRING) {
358 printer->Outdent();
359 printer->Print(" public:\n");
360 printer->Indent();
361 }
362 }
363
364 void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const365 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
366 printer->Print(variables_,
367 "inline const ::std::string& $classname$::$name$(int index) const {\n"
368 " return $name$_.$cppget$(index);\n"
369 "}\n"
370 "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
371 " return $name$_.Mutable(index);\n"
372 "}\n"
373 "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
374 " $name$_.Mutable(index)->assign(value);\n"
375 "}\n"
376 "inline void $classname$::set_$name$(int index, const char* value) {\n"
377 " $name$_.Mutable(index)->assign(value);\n"
378 "}\n"
379 "inline void "
380 "$classname$::set_$name$"
381 "(int index, const $pointer_type$* value, size_t size) {\n"
382 " $name$_.Mutable(index)->assign(\n"
383 " reinterpret_cast<const char*>(value), size);\n"
384 "}\n"
385 "inline ::std::string* $classname$::add_$name$() {\n"
386 " return $name$_.Add();\n"
387 "}\n"
388 "inline void $classname$::add_$name$(const ::std::string& value) {\n"
389 " $name$_.Add()->assign(value);\n"
390 "}\n"
391 "inline void $classname$::add_$name$(const char* value) {\n"
392 " $name$_.Add()->assign(value);\n"
393 "}\n"
394 "inline void "
395 "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
396 " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
397 "}\n");
398 printer->Print(variables_,
399 "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
400 "$classname$::$name$() const {\n"
401 " return $name$_;\n"
402 "}\n"
403 "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
404 "$classname$::mutable_$name$() {\n"
405 " return &$name$_;\n"
406 "}\n");
407 }
408
409 void RepeatedStringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const410 GenerateClearingCode(io::Printer* printer) const {
411 printer->Print(variables_, "$name$_.Clear();\n");
412 }
413
414 void RepeatedStringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const415 GenerateMergingCode(io::Printer* printer) const {
416 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
417 }
418
419 void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const420 GenerateSwappingCode(io::Printer* printer) const {
421 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
422 }
423
424 void RepeatedStringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const425 GenerateConstructorCode(io::Printer* printer) const {
426 // Not needed for repeated fields.
427 }
428
429 void RepeatedStringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const430 GenerateMergeFromCodedStream(io::Printer* printer) const {
431 printer->Print(variables_,
432 "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
433 " input, this->add_$name$()));\n");
434 if (HasUtf8Verification(descriptor_->file()) &&
435 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
436 printer->Print(variables_,
437 "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
438 " this->$name$(this->$name$_size() - 1).data(),\n"
439 " this->$name$(this->$name$_size() - 1).length(),\n"
440 " ::google::protobuf::internal::WireFormat::PARSE);\n");
441 }
442 }
443
444 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const445 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
446 printer->Print(variables_,
447 "for (int i = 0; i < this->$name$_size(); i++) {\n");
448 if (HasUtf8Verification(descriptor_->file()) &&
449 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
450 printer->Print(variables_,
451 "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
452 " this->$name$(i).data(), this->$name$(i).length(),\n"
453 " ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
454 }
455 printer->Print(variables_,
456 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
457 " $number$, this->$name$(i), output);\n"
458 "}\n");
459 }
460
461 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const462 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
463 printer->Print(variables_,
464 "for (int i = 0; i < this->$name$_size(); i++) {\n");
465 if (HasUtf8Verification(descriptor_->file()) &&
466 descriptor_->type() == FieldDescriptor::TYPE_STRING) {
467 printer->Print(variables_,
468 " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
469 " this->$name$(i).data(), this->$name$(i).length(),\n"
470 " ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
471 }
472 printer->Print(variables_,
473 " target = ::google::protobuf::internal::WireFormatLite::\n"
474 " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
475 "}\n");
476 }
477
478 void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer * printer) const479 GenerateByteSize(io::Printer* printer) const {
480 printer->Print(variables_,
481 "total_size += $tag_size$ * this->$name$_size();\n"
482 "for (int i = 0; i < this->$name$_size(); i++) {\n"
483 " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
484 " this->$name$(i));\n"
485 "}\n");
486 }
487
488 } // namespace cpp
489 } // namespace compiler
490 } // namespace protobuf
491 } // namespace google
492