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