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
41namespace google {
42namespace protobuf {
43namespace compiler {
44namespace cpp {
45
46namespace {
47
48void 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::GetEmptyString()"
57      : "_default_" + FieldName(descriptor) + "_";
58  (*variables)["pointer_type"] =
59      descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
60}
61
62}  // namespace
63
64// ===================================================================
65
66StringFieldGenerator::
67StringFieldGenerator(const FieldDescriptor* descriptor,
68                     const Options& options)
69  : descriptor_(descriptor) {
70  SetStringVariables(descriptor, &variables_, options);
71}
72
73StringFieldGenerator::~StringFieldGenerator() {}
74
75void StringFieldGenerator::
76GeneratePrivateMembers(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
83void StringFieldGenerator::
84GenerateAccessorDeclarations(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
127void StringFieldGenerator::
128GenerateInlineAccessorDefinitions(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
193void StringFieldGenerator::
194GenerateNonInlineAccessorDefinitions(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
202void StringFieldGenerator::
203GenerateClearingCode(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
217void StringFieldGenerator::
218GenerateMergingCode(io::Printer* printer) const {
219  printer->Print(variables_, "set_$name$(from.$name$());\n");
220}
221
222void StringFieldGenerator::
223GenerateSwappingCode(io::Printer* printer) const {
224  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
225}
226
227void StringFieldGenerator::
228GenerateConstructorCode(io::Printer* printer) const {
229  printer->Print(variables_,
230    "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
231}
232
233void StringFieldGenerator::
234GenerateDestructorCode(io::Printer* printer) const {
235  printer->Print(variables_,
236    "if ($name$_ != $default_variable$) {\n"
237    "  delete $name$_;\n"
238    "}\n");
239}
240
241void StringFieldGenerator::
242GenerateDefaultInstanceAllocator(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
250void StringFieldGenerator::
251GenerateShutdownCode(io::Printer* printer) const {
252  if (!descriptor_->default_value_string().empty()) {
253    printer->Print(variables_,
254      "delete $classname$::$default_variable$;\n");
255  }
256}
257
258void StringFieldGenerator::
259GenerateMergeFromCodedStream(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
272void StringFieldGenerator::
273GenerateSerializeWithCachedSizes(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
286void StringFieldGenerator::
287GenerateSerializeWithCachedSizesToArray(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
301void StringFieldGenerator::
302GenerateByteSize(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
311RepeatedStringFieldGenerator::
312RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
313                             const Options& options)
314  : descriptor_(descriptor) {
315  SetStringVariables(descriptor, &variables_, options);
316}
317
318RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
319
320void RepeatedStringFieldGenerator::
321GeneratePrivateMembers(io::Printer* printer) const {
322  printer->Print(variables_,
323    "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
324}
325
326void RepeatedStringFieldGenerator::
327GenerateAccessorDeclarations(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
364void RepeatedStringFieldGenerator::
365GenerateInlineAccessorDefinitions(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
409void RepeatedStringFieldGenerator::
410GenerateClearingCode(io::Printer* printer) const {
411  printer->Print(variables_, "$name$_.Clear();\n");
412}
413
414void RepeatedStringFieldGenerator::
415GenerateMergingCode(io::Printer* printer) const {
416  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
417}
418
419void RepeatedStringFieldGenerator::
420GenerateSwappingCode(io::Printer* printer) const {
421  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
422}
423
424void RepeatedStringFieldGenerator::
425GenerateConstructorCode(io::Printer* printer) const {
426  // Not needed for repeated fields.
427}
428
429void RepeatedStringFieldGenerator::
430GenerateMergeFromCodedStream(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
444void RepeatedStringFieldGenerator::
445GenerateSerializeWithCachedSizes(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
461void RepeatedStringFieldGenerator::
462GenerateSerializeWithCachedSizesToArray(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
478void RepeatedStringFieldGenerator::
479GenerateByteSize(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