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)48 void 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
61 StringFieldGenerator::
StringFieldGenerator(const FieldDescriptor * descriptor)62 StringFieldGenerator(const FieldDescriptor* descriptor)
63 : descriptor_(descriptor) {
64 SetStringVariables(descriptor, &variables_);
65 }
66
~StringFieldGenerator()67 StringFieldGenerator::~StringFieldGenerator() {}
68
69 void StringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const70 GeneratePrivateMembers(io::Printer* printer) const {
71 printer->Print(variables_,
72 "::std::string* $name$_;\n"
73 "static const ::std::string _default_$name$_;\n");
74 }
75
76 void StringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const77 GenerateAccessorDeclarations(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
117 void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const118 GenerateInlineAccessorDefinitions(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
161 void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const162 GenerateNonInlineAccessorDefinitions(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
172 void StringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const173 GenerateClearingCode(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
187 void StringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const188 GenerateMergingCode(io::Printer* printer) const {
189 printer->Print(variables_, "set_$name$(from.$name$());\n");
190 }
191
192 void StringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const193 GenerateSwappingCode(io::Printer* printer) const {
194 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
195 }
196
197 void StringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const198 GenerateConstructorCode(io::Printer* printer) const {
199 printer->Print(variables_,
200 "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n");
201 }
202
203 void StringFieldGenerator::
GenerateDestructorCode(io::Printer * printer) const204 GenerateDestructorCode(io::Printer* printer) const {
205 printer->Print(variables_,
206 "if ($name$_ != &_default_$name$_) {\n"
207 " delete $name$_;\n"
208 "}\n");
209 }
210
211 void StringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const212 GenerateMergeFromCodedStream(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
225 void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const226 GenerateSerializeWithCachedSizes(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
239 void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const240 GenerateSerializeWithCachedSizesToArray(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
254 void StringFieldGenerator::
GenerateByteSize(io::Printer * printer) const255 GenerateByteSize(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
264 RepeatedStringFieldGenerator::
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor)265 RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
266 : descriptor_(descriptor) {
267 SetStringVariables(descriptor, &variables_);
268 }
269
~RepeatedStringFieldGenerator()270 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
271
272 void RepeatedStringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const273 GeneratePrivateMembers(io::Printer* printer) const {
274 printer->Print(variables_,
275 "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
276 }
277
278 void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const279 GenerateAccessorDeclarations(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
316 void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const317 GenerateInlineAccessorDefinitions(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
361 void RepeatedStringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const362 GenerateClearingCode(io::Printer* printer) const {
363 printer->Print(variables_, "$name$_.Clear();\n");
364 }
365
366 void RepeatedStringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const367 GenerateMergingCode(io::Printer* printer) const {
368 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
369 }
370
371 void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const372 GenerateSwappingCode(io::Printer* printer) const {
373 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
374 }
375
376 void RepeatedStringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const377 GenerateConstructorCode(io::Printer* printer) const {
378 // Not needed for repeated fields.
379 }
380
381 void RepeatedStringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const382 GenerateMergeFromCodedStream(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
395 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const396 GenerateSerializeWithCachedSizes(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
412 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const413 GenerateSerializeWithCachedSizesToArray(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
429 void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer * printer) const430 GenerateByteSize(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