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