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