php_generator.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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 
32 
40 
41 #include <sstream>
42 
43 const std::string kDescriptorFile = "google/protobuf/descriptor.proto";
44 const std::string kEmptyFile = "google/protobuf/empty.proto";
45 const std::string kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php";
47  "GPBMetadata/Google/Protobuf/Internal/Descriptor.php";
48 const std::string kDescriptorDirName = "Google/Protobuf/Internal";
49 const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
50 const char* const kReservedNames[] = {
51  "abstract", "and", "array", "as", "break",
52  "callable", "case", "catch", "class", "clone",
53  "const", "continue", "declare", "default", "die",
54  "do", "echo", "else", "elseif", "empty",
55  "enddeclare", "endfor", "endforeach", "endif", "endswitch",
56  "endwhile", "eval", "exit", "extends", "final",
57  "for", "foreach", "function", "global", "goto",
58  "if", "implements", "include", "include_once", "instanceof",
59  "insteadof", "interface", "isset", "list", "namespace",
60  "new", "or", "print", "private", "protected",
61  "public", "require", "require_once", "return", "static",
62  "switch", "throw", "trait", "try", "unset",
63  "use", "var", "while", "xor", "int",
64  "float", "bool", "string", "true", "false",
65  "null", "void", "iterable"};
66 const char* const kValidConstantNames[] = {
67  "int", "float", "bool", "string", "true",
68  "false", "null", "void", "iterable",
69 };
70 const int kReservedNamesSize = 73;
72 const int kFieldSetter = 1;
73 const int kFieldGetter = 2;
74 const int kFieldProperty = 3;
75 
76 namespace google {
77 namespace protobuf {
78 namespace compiler {
79 namespace php {
80 
81 // Forward decls.
82 std::string PhpName(const std::string& full_name, bool is_descriptor);
85 std::string FilenameToClassname(const string& filename);
87  bool is_descriptor);
90 std::string UnderscoresToCamelCase(const string& name, bool cap_first_letter);
91 std::string EscapeDollor(const string& to_escape);
92 std::string BinaryToHex(const string& binary);
93 void Indent(io::Printer* printer);
94 void Outdent(io::Printer* printer);
96  int is_descriptor);
98  const Descriptor* message,
99  int is_descriptor);
101  int is_descriptor, int function_type);
103  const FieldDescriptor* field);
105  const FieldDescriptor* field);
106 void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
107  int is_descriptor);
109  const EnumValueDescriptor* value);
111  const ServiceDescriptor* service);
113  const MethodDescriptor* method);
114 
115 
116 std::string ReservedNamePrefix(const string& classname,
117  const FileDescriptor* file) {
118  bool is_reserved = false;
119 
120  string lower = classname;
121  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
122 
123  for (int i = 0; i < kReservedNamesSize; i++) {
124  if (lower == kReservedNames[i]) {
125  is_reserved = true;
126  break;
127  }
128  }
129 
130  if (is_reserved) {
131  if (file->package() == "google.protobuf") {
132  return "GPB";
133  } else {
134  return "PB";
135  }
136  }
137 
138  return "";
139 }
140 
141 template <typename DescriptorType>
142 std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
143  if (is_descriptor) {
144  return StringReplace(desc->full_name(),
145  "google.protobuf",
146  "google.protobuf.internal", false);
147  } else {
148  return desc->full_name();
149  }
150 }
151 
152 template <typename DescriptorType>
153 std::string ClassNamePrefix(const string& classname,
154  const DescriptorType* desc) {
155  const string& prefix = (desc->file()->options()).php_class_prefix();
156  if (prefix != "") {
157  return prefix;
158  }
159 
160  return ReservedNamePrefix(classname, desc->file());
161 }
162 
163 template <typename DescriptorType>
164 std::string GeneratedClassNameImpl(const DescriptorType* desc) {
165  std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
166  const Descriptor* containing = desc->containing_type();
167  while (containing != NULL) {
168  classname = ClassNamePrefix(containing->name(), desc) + containing->name()
169  + '\\' + classname;
170  containing = containing->containing_type();
171  }
172  return classname;
173 }
174 
176  std::string classname = desc->name();
177  return ClassNamePrefix(classname, desc) + classname;
178 }
179 
182 }
183 
186 }
187 
190 }
191 
192 template <typename DescriptorType>
193 std::string LegacyGeneratedClassName(const DescriptorType* desc) {
194  std::string classname = desc->name();
195  const Descriptor* containing = desc->containing_type();
196  while (containing != NULL) {
197  classname = containing->name() + '_' + classname;
198  containing = containing->containing_type();
199  }
200  return ClassNamePrefix(classname, desc) + classname;
201 }
202 
203 std::string ClassNamePrefix(const string& classname) {
204  string lower = classname;
205  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
206 
207  for (int i = 0; i < kReservedNamesSize; i++) {
208  if (lower == kReservedNames[i]) {
209  return "PB";
210  }
211  }
212 
213  return "";
214 }
215 
216 std::string ConstantNamePrefix(const string& classname) {
217  bool is_reserved = false;
218 
219  string lower = classname;
220  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
221 
222  for (int i = 0; i < kReservedNamesSize; i++) {
223  if (lower == kReservedNames[i]) {
224  is_reserved = true;
225  break;
226  }
227  }
228 
229  for (int i = 0; i < kValidConstantNamesSize; i++) {
230  if (lower == kValidConstantNames[i]) {
231  is_reserved = false;
232  break;
233  }
234  }
235 
236  if (is_reserved) {
237  return "PB";
238  }
239 
240  return "";
241 }
242 
243 template <typename DescriptorType>
244 std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
245  if (desc->file()->options().has_php_namespace()) {
246  const string& php_namespace = desc->file()->options().php_namespace();
247  if (php_namespace != "") {
248  return php_namespace;
249  }
250  return "";
251  }
252 
253  if (desc->file()->package() != "") {
254  return PhpName(desc->file()->package(), is_descriptor);
255  }
256  return "";
257 }
258 
259 template <typename DescriptorType>
260 std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
261  string classname = GeneratedClassNameImpl(desc);
262  string php_namespace = RootPhpNamespace(desc, is_descriptor);
263  if (php_namespace != "") {
264  return php_namespace + "\\" + classname;
265  }
266  return classname;
267 }
268 
269 template <typename DescriptorType>
270 std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
271  string classname = LegacyGeneratedClassName(desc);
272  string php_namespace = RootPhpNamespace(desc, is_descriptor);
273  if (php_namespace != "") {
274  return php_namespace + "\\" + classname;
275  }
276  return classname;
277 }
278 
279 std::string PhpName(const std::string& full_name, bool is_descriptor) {
280  if (is_descriptor) {
281  return kDescriptorPackageName;
282  }
283 
284  std::string segment;
285  std::string result;
286  bool cap_next_letter = true;
287  for (int i = 0; i < full_name.size(); i++) {
288  if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
289  segment += full_name[i] + ('A' - 'a');
290  cap_next_letter = false;
291  } else if (full_name[i] == '.') {
292  result += ClassNamePrefix(segment) + segment + '\\';
293  segment = "";
294  cap_next_letter = true;
295  } else {
296  segment += full_name[i];
297  cap_next_letter = false;
298  }
299  }
300  result += ClassNamePrefix(segment) + segment;
301  return result;
302 }
303 
305  switch (field->type()) {
316  case FieldDescriptor::TYPE_ENUM: return "0";
318  case FieldDescriptor::TYPE_FLOAT: return "0.0";
319  case FieldDescriptor::TYPE_BOOL: return "false";
321  case FieldDescriptor::TYPE_BYTES: return "''";
323  case FieldDescriptor::TYPE_GROUP: return "null";
324  default: assert(false); return "";
325  }
326 }
327 
329  bool is_descriptor) {
330  const string& proto_file = file->name();
331  int start_index = 0;
332  int first_index = proto_file.find_first_of("/", start_index);
333  std::string result = "";
334  std::string segment = "";
335 
336  if (proto_file == kEmptyFile) {
337  return kEmptyMetadataFile;
338  }
339  if (is_descriptor) {
341  }
342 
343  // Append directory name.
344  std::string file_no_suffix;
345  int lastindex = proto_file.find_last_of(".");
346  if (proto_file == kEmptyFile) {
347  return kEmptyMetadataFile;
348  } else {
349  file_no_suffix = proto_file.substr(0, lastindex);
350  }
351 
352  if (file->options().has_php_metadata_namespace()) {
353  const string& php_metadata_namespace =
355  if (php_metadata_namespace != "" && php_metadata_namespace != "\\") {
356  result += php_metadata_namespace;
357  std::replace(result.begin(), result.end(), '\\', '/');
358  if (result.at(result.size() - 1) != '/') {
359  result += "/";
360  }
361  }
362  } else {
363  result += "GPBMetadata/";
364  while (first_index != string::npos) {
365  segment = UnderscoresToCamelCase(
366  file_no_suffix.substr(start_index, first_index - start_index), true);
367  result += ReservedNamePrefix(segment, file) + segment + "/";
368  start_index = first_index + 1;
369  first_index = file_no_suffix.find_first_of("/", start_index);
370  }
371  }
372 
373  // Append file name.
374  int file_name_start = file_no_suffix.find_last_of("/");
375  if (file_name_start == string::npos) {
376  file_name_start = 0;
377  } else {
378  file_name_start += 1;
379  }
380  segment = UnderscoresToCamelCase(
381  file_no_suffix.substr(file_name_start, first_index - file_name_start), true);
382 
383  return result + ReservedNamePrefix(segment, file) + segment + ".php";
384 }
385 
386 template <typename DescriptorType>
388  bool is_descriptor) {
389  std::string result = FullClassName(desc, is_descriptor);
390  for (int i = 0; i < result.size(); i++) {
391  if (result[i] == '\\') {
392  result[i] = '/';
393  }
394  }
395  return result + ".php";
396 }
397 
398 template <typename DescriptorType>
400  bool is_descriptor) {
401  std::string result = LegacyFullClassName(desc, is_descriptor);
402 
403  for (int i = 0; i < result.size(); i++) {
404  if (result[i] == '\\') {
405  result[i] = '/';
406  }
407  }
408  return result + ".php";
409 }
410 
412  bool is_descriptor) {
413  std::string result = FullClassName(service, is_descriptor) + "Interface";
414  for (int i = 0; i < result.size(); i++) {
415  if (result[i] == '\\') {
416  result[i] = '/';
417  }
418  }
419  return result + ".php";
420 }
421 
423  std::ostringstream os;
424  os << value;
425  return os.str();
426 }
427 
429  switch (field->label()) {
430  case FieldDescriptor::LABEL_OPTIONAL: return "optional";
431  case FieldDescriptor::LABEL_REQUIRED: return "required";
432  case FieldDescriptor::LABEL_REPEATED: return "repeated";
433  default: assert(false); return "";
434  }
435 }
436 
438  switch (field->type()) {
439  case FieldDescriptor::TYPE_INT32: return "int32";
440  case FieldDescriptor::TYPE_INT64: return "int64";
441  case FieldDescriptor::TYPE_UINT32: return "uint32";
442  case FieldDescriptor::TYPE_UINT64: return "uint64";
443  case FieldDescriptor::TYPE_SINT32: return "sint32";
444  case FieldDescriptor::TYPE_SINT64: return "sint64";
445  case FieldDescriptor::TYPE_FIXED32: return "fixed32";
446  case FieldDescriptor::TYPE_FIXED64: return "fixed64";
447  case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
448  case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
449  case FieldDescriptor::TYPE_DOUBLE: return "double";
450  case FieldDescriptor::TYPE_FLOAT: return "float";
451  case FieldDescriptor::TYPE_BOOL: return "bool";
452  case FieldDescriptor::TYPE_ENUM: return "enum";
453  case FieldDescriptor::TYPE_STRING: return "string";
454  case FieldDescriptor::TYPE_BYTES: return "bytes";
455  case FieldDescriptor::TYPE_MESSAGE: return "message";
456  case FieldDescriptor::TYPE_GROUP: return "group";
457  default: assert(false); return "";
458  }
459 }
460 
461 std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
462  if (field->is_map()) {
463  return "array|\\Google\\Protobuf\\Internal\\MapField";
464  }
465  string type;
466  switch (field->type()) {
473  type = "int";
474  break;
480  type = "int|string";
481  break;
484  type = "float";
485  break;
487  type = "bool";
488  break;
491  type = "string";
492  break;
494  type = "\\" + FullClassName(field->message_type(), is_descriptor);
495  break;
497  return "null";
498  default: assert(false); return "";
499  }
500  if (field->is_repeated()) {
501  // accommodate for edge case with multiple types.
502  size_t start_pos = type.find("|");
503  if (start_pos != std::string::npos) {
504  type.replace(start_pos, 1, "[]|");
505  }
506  type += "[]|\\Google\\Protobuf\\Internal\\RepeatedField";
507  }
508  return type;
509 }
510 
511 std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
512  if (field->is_map()) {
513  return "\\Google\\Protobuf\\Internal\\MapField";
514  }
515  if (field->is_repeated()) {
516  return "\\Google\\Protobuf\\Internal\\RepeatedField";
517  }
518  switch (field->type()) {
524  case FieldDescriptor::TYPE_ENUM: return "int";
529  case FieldDescriptor::TYPE_SFIXED64: return "int|string";
531  case FieldDescriptor::TYPE_FLOAT: return "float";
532  case FieldDescriptor::TYPE_BOOL: return "bool";
534  case FieldDescriptor::TYPE_BYTES: return "string";
536  return "\\" + FullClassName(field->message_type(), is_descriptor);
537  case FieldDescriptor::TYPE_GROUP: return "null";
538  default: assert(false); return "";
539  }
540 }
541 
543  const FieldDescriptor* field, bool is_descriptor) {
544  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
545  return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
546  }
547  if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
548  return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
549  }
550  return "";
551 }
552 
553 // Converts a name to camel-case. If cap_first_letter is true, capitalize the
554 // first letter.
555 std::string UnderscoresToCamelCase(const string& input, bool cap_first_letter) {
556  std::string result;
557  for (int i = 0; i < input.size(); i++) {
558  if ('a' <= input[i] && input[i] <= 'z') {
559  if (cap_first_letter) {
560  result += input[i] + ('A' - 'a');
561  } else {
562  result += input[i];
563  }
564  cap_first_letter = false;
565  } else if ('A' <= input[i] && input[i] <= 'Z') {
566  if (i == 0 && !cap_first_letter) {
567  // Force first letter to lower-case unless explicitly told to
568  // capitalize it.
569  result += input[i] + ('a' - 'A');
570  } else {
571  // Capital letters after the first are left as-is.
572  result += input[i];
573  }
574  cap_first_letter = false;
575  } else if ('0' <= input[i] && input[i] <= '9') {
576  result += input[i];
577  cap_first_letter = true;
578  } else {
579  cap_first_letter = true;
580  }
581  }
582  // Add a trailing "_" if the name should be altered.
583  if (input[input.size() - 1] == '#') {
584  result += '_';
585  }
586  return result;
587 }
588 
589 std::string EscapeDollor(const string& to_escape) {
590  return StringReplace(to_escape, "$", "\\$", true);
591 }
592 
593 std::string BinaryToHex(const string& src) {
594  string dest;
595  size_t i;
596  unsigned char symbol[16] = {
597  '0', '1', '2', '3',
598  '4', '5', '6', '7',
599  '8', '9', 'a', 'b',
600  'c', 'd', 'e', 'f',
601  };
602 
603  dest.resize(src.size() * 2);
604  char* append_ptr = &dest[0];
605 
606  for (i = 0; i < src.size(); i++) {
607  *append_ptr++ = symbol[(src[i] & 0xf0) >> 4];
608  *append_ptr++ = symbol[src[i] & 0x0f];
609  }
610 
611  return dest;
612 }
613 
614 void Indent(io::Printer* printer) {
615  printer->Indent();
616  printer->Indent();
617 }
618 void Outdent(io::Printer* printer) {
619  printer->Outdent();
620  printer->Outdent();
621 }
622 
624  bool is_descriptor) {
625  if (field->is_repeated()) {
626  GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
627  printer->Print(
628  "private $^name^;\n",
629  "name", field->name());
630  } else if (field->containing_oneof()) {
631  // Oneof fields are handled by GenerateOneofField.
632  return;
633  } else {
634  GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
635  printer->Print(
636  "private $^name^ = ^default^;\n",
637  "name", field->name(),
638  "default", DefaultForField(field));
639  }
640 
641  if (is_descriptor) {
642  printer->Print(
643  "private $has_^name^ = false;\n",
644  "name", field->name());
645  }
646 }
647 
648 void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) {
649  // Oneof property needs to be protected in order to be accessed by parent
650  // class in implementation.
651  printer->Print(
652  "protected $^name^;\n",
653  "name", oneof->name());
654 }
655 
656 void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
657  io::Printer* printer) {
658  const OneofDescriptor* oneof = field->containing_oneof();
659 
660  // Generate getter.
661  if (oneof != NULL) {
662  GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
663  printer->Print(
664  "public function get^camel_name^()\n"
665  "{\n"
666  " return $this->readOneof(^number^);\n"
667  "}\n\n",
668  "camel_name", UnderscoresToCamelCase(field->name(), true),
669  "number", IntToString(field->number()));
670  } else {
671  GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
672  printer->Print(
673  "public function get^camel_name^()\n"
674  "{\n"
675  " return $this->^name^;\n"
676  "}\n\n",
677  "camel_name", UnderscoresToCamelCase(field->name(), true), "name",
678  field->name());
679  }
680 
681  // For wrapper types, generate an additional getXXXUnwrapped getter
682  if (!field->is_map() &&
683  !field->is_repeated() &&
684  field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
685  IsWrapperType(field)) {
687  printer->Print(
688  "public function get^camel_name^Unwrapped()\n"
689  "{\n"
690  " $wrapper = $this->get^camel_name^();\n"
691  " return is_null($wrapper) ? null : $wrapper->getValue();\n"
692  "}\n\n",
693  "camel_name", UnderscoresToCamelCase(field->name(), true));
694  }
695 
696  // Generate setter.
697  GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter);
698  printer->Print(
699  "public function set^camel_name^($var)\n"
700  "{\n",
701  "camel_name", UnderscoresToCamelCase(field->name(), true));
702 
703  Indent(printer);
704 
705  // Type check.
706  if (field->is_map()) {
707  const Descriptor* map_entry = field->message_type();
708  const FieldDescriptor* key = map_entry->FindFieldByName("key");
709  const FieldDescriptor* value = map_entry->FindFieldByName("value");
710  printer->Print(
711  "$arr = GPBUtil::checkMapField($var, "
712  "\\Google\\Protobuf\\Internal\\GPBType::^key_type^, "
713  "\\Google\\Protobuf\\Internal\\GPBType::^value_type^",
714  "key_type", ToUpper(key->type_name()),
715  "value_type", ToUpper(value->type_name()));
716  if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
717  printer->Print(
718  ", \\^class_name^);\n",
719  "class_name",
720  FullClassName(value->message_type(), is_descriptor) + "::class");
721  } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
722  printer->Print(
723  ", \\^class_name^);\n",
724  "class_name",
725  FullClassName(value->enum_type(), is_descriptor) + "::class");
726  } else {
727  printer->Print(");\n");
728  }
729  } else if (field->is_repeated()) {
730  printer->Print(
731  "$arr = GPBUtil::checkRepeatedField($var, "
732  "\\Google\\Protobuf\\Internal\\GPBType::^type^",
733  "type", ToUpper(field->type_name()));
734  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
735  printer->Print(
736  ", \\^class_name^);\n",
737  "class_name",
738  FullClassName(field->message_type(), is_descriptor) + "::class");
739  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
740  printer->Print(
741  ", \\^class_name^);\n",
742  "class_name",
743  FullClassName(field->enum_type(), is_descriptor) + "::class");
744  } else {
745  printer->Print(");\n");
746  }
747  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
748  printer->Print(
749  "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
750  "class_name", LegacyFullClassName(field->message_type(), is_descriptor));
751  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
752  printer->Print(
753  "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
754  "class_name", LegacyFullClassName(field->enum_type(), is_descriptor));
755  } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
756  printer->Print(
757  "GPBUtil::checkString($var, ^utf8^);\n",
758  "utf8",
759  field->type() == FieldDescriptor::TYPE_STRING ? "True": "False");
760  } else {
761  printer->Print(
762  "GPBUtil::check^type^($var);\n",
763  "type", UnderscoresToCamelCase(field->cpp_type_name(), true));
764  }
765 
766  if (oneof != NULL) {
767  printer->Print(
768  "$this->writeOneof(^number^, $var);\n",
769  "number", IntToString(field->number()));
770  } else if (field->is_repeated()) {
771  printer->Print(
772  "$this->^name^ = $arr;\n",
773  "name", field->name());
774  } else {
775  printer->Print(
776  "$this->^name^ = $var;\n",
777  "name", field->name());
778  }
779 
780  // Set has bit for proto2 only.
781  if (is_descriptor) {
782  printer->Print(
783  "$this->has_^field_name^ = true;\n",
784  "field_name", field->name());
785  }
786 
787  printer->Print("\nreturn $this;\n");
788 
789  Outdent(printer);
790 
791  printer->Print(
792  "}\n\n");
793 
794  // For wrapper types, generate an additional setXXXValue getter
795  if (!field->is_map() &&
796  !field->is_repeated() &&
797  field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
798  IsWrapperType(field)) {
800  printer->Print(
801  "public function set^camel_name^Unwrapped($var)\n"
802  "{\n"
803  " $wrappedVar = is_null($var) ? null : new \\^wrapper_type^(['value' => $var]);\n"
804  " return $this->set^camel_name^($wrappedVar);\n"
805  "}\n\n",
806  "camel_name", UnderscoresToCamelCase(field->name(), true),
807  "wrapper_type", LegacyFullClassName(field->message_type(), is_descriptor));
808  }
809 
810  // Generate has method for proto2 only.
811  if (is_descriptor) {
812  printer->Print(
813  "public function has^camel_name^()\n"
814  "{\n"
815  " return $this->has_^field_name^;\n"
816  "}\n\n",
817  "camel_name", UnderscoresToCamelCase(field->name(), true),
818  "field_name", field->name());
819  }
820 }
821 
822 void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
823  printer->Print(
824  "$pool->addEnum('^name^', "
825  "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
826  "name", DescriptorFullName(en, true),
827  "class_name", en->name());
828  Indent(printer);
829 
830  for (int i = 0; i < en->value_count(); i++) {
831  const EnumValueDescriptor* value = en->value(i);
832  printer->Print(
833  "->value(\"^name^\", ^number^)\n",
834  "name", ConstantNamePrefix(value->name()) + value->name(),
835  "number", IntToString(value->number()));
836  }
837  printer->Print("->finalizeToPool();\n\n");
838  Outdent(printer);
839 }
840 
842  io::Printer* printer) {
843  printer->Print(
844  "public function ^camel_name^(\\^request_name^ $request);\n\n",
845  "camel_name", UnderscoresToCamelCase(method->name(), false),
846  "request_name", FullClassName(
847  method->input_type(), false)
848  );
849 }
850 
851 void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
852  io::Printer* printer) {
853  // Don't generate MapEntry messages -- we use the PHP extension's native
854  // support for map fields instead.
855  if (message->options().map_entry()) {
856  return;
857  }
858  string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") +
859  ReservedNamePrefix(message->name(), message->file()) + message->name();
860 
861  printer->Print(
862  "$pool->addMessage('^message^', "
863  "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
864  "message", DescriptorFullName(message, true),
865  "class_name", class_name);
866 
867  Indent(printer);
868 
869  for (int i = 0; i < message->field_count(); i++) {
870  const FieldDescriptor* field = message->field(i);
871  if (field->is_map()) {
872  const FieldDescriptor* key =
873  field->message_type()->FindFieldByName("key");
874  const FieldDescriptor* val =
875  field->message_type()->FindFieldByName("value");
876  printer->Print(
877  "->map('^field^', \\Google\\Protobuf\\Internal\\GPBType::^key^, "
878  "\\Google\\Protobuf\\Internal\\GPBType::^value^, ^number^^other^)\n",
879  "field", field->name(),
880  "key", ToUpper(key->type_name()),
881  "value", ToUpper(val->type_name()),
882  "number", StrCat(field->number()),
883  "other", EnumOrMessageSuffix(val, true));
884  } else if (!field->containing_oneof()) {
885  printer->Print(
886  "->^label^('^field^', "
887  "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
888  "field", field->name(),
889  "label", LabelForField(field),
890  "type", ToUpper(field->type_name()),
891  "number", StrCat(field->number()),
892  "other", EnumOrMessageSuffix(field, true));
893  }
894  }
895 
896  // oneofs.
897  for (int i = 0; i < message->oneof_decl_count(); i++) {
898  const OneofDescriptor* oneof = message->oneof_decl(i);
899  printer->Print("->oneof(^name^)\n",
900  "name", oneof->name());
901  Indent(printer);
902  for (int index = 0; index < oneof->field_count(); index++) {
903  const FieldDescriptor* field = oneof->field(index);
904  printer->Print(
905  "->value('^field^', "
906  "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
907  "field", field->name(),
908  "type", ToUpper(field->type_name()),
909  "number", StrCat(field->number()),
910  "other", EnumOrMessageSuffix(field, true));
911  }
912  printer->Print("->finish()\n");
913  Outdent(printer);
914  }
915 
916  printer->Print(
917  "->finalizeToPool();\n");
918 
919  Outdent(printer);
920 
921  printer->Print(
922  "\n");
923 
924  for (int i = 0; i < message->nested_type_count(); i++) {
925  GenerateMessageToPool(class_name, message->nested_type(i), printer);
926  }
927  for (int i = 0; i < message->enum_type_count(); i++) {
928  GenerateEnumToPool(message->enum_type(i), printer);
929  }
930 }
931 
932 void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
933  io::Printer* printer) {
934  printer->Print(
935  "public static $is_initialized = false;\n\n"
936  "public static function initOnce() {\n");
937  Indent(printer);
938 
939  printer->Print(
940  "$pool = \\Google\\Protobuf\\Internal\\"
941  "DescriptorPool::getGeneratedPool();\n\n"
942  "if (static::$is_initialized == true) {\n"
943  " return;\n"
944  "}\n");
945 
946  if (is_descriptor) {
947  for (int i = 0; i < file->message_type_count(); i++) {
948  GenerateMessageToPool("", file->message_type(i), printer);
949  }
950  for (int i = 0; i < file->enum_type_count(); i++) {
951  GenerateEnumToPool(file->enum_type(i), printer);
952  }
953 
954  printer->Print(
955  "$pool->finish();\n");
956  } else {
957  for (int i = 0; i < file->dependency_count(); i++) {
958  const std::string& name = file->dependency(i)->name();
959  // Currently, descriptor.proto is not ready for external usage. Skip to
960  // import it for now, so that its dependencies can still work as long as
961  // they don't use protos defined in descriptor.proto.
962  if (name == kDescriptorFile) {
963  continue;
964  }
965  std::string dependency_filename =
966  GeneratedMetadataFileName(file->dependency(i), is_descriptor);
967  printer->Print(
968  "\\^name^::initOnce();\n",
969  "name", FilenameToClassname(dependency_filename));
970  }
971 
972  // Add messages and enums to descriptor pool.
973  FileDescriptorSet files;
974  FileDescriptorProto* file_proto = files.add_file();
975  file->CopyTo(file_proto);
976 
977  // Filter out descriptor.proto as it cannot be depended on for now.
978  RepeatedPtrField<string>* dependency = file_proto->mutable_dependency();
979  for (RepeatedPtrField<string>::iterator it = dependency->begin();
980  it != dependency->end(); ++it) {
981  if (*it != kDescriptorFile) {
982  dependency->erase(it);
983  break;
984  }
985  }
986 
987  // Filter out all extensions, since we do not support extension yet.
988  file_proto->clear_extension();
990  file_proto->mutable_message_type();
992  it != message_type->end(); ++it) {
993  it->clear_extension();
994  }
995 
996  string files_data;
997  files.SerializeToString(&files_data);
998 
999  printer->Print("$pool->internalAddGeneratedFile(hex2bin(\n");
1000  Indent(printer);
1001 
1002  // Only write 30 bytes per line.
1003  static const int kBytesPerLine = 30;
1004  for (int i = 0; i < files_data.size(); i += kBytesPerLine) {
1005  printer->Print(
1006  "\"^data^\"^dot^\n",
1007  "data", BinaryToHex(files_data.substr(i, kBytesPerLine)),
1008  "dot", i + kBytesPerLine < files_data.size() ? " ." : "");
1009  }
1010 
1011  Outdent(printer);
1012  printer->Print(
1013  "), true);\n\n");
1014  }
1015  printer->Print(
1016  "static::$is_initialized = true;\n");
1017  Outdent(printer);
1018  printer->Print("}\n");
1019 }
1020 
1021 void GenerateUseDeclaration(bool is_descriptor, io::Printer* printer) {
1022  if (!is_descriptor) {
1023  printer->Print(
1024  "use Google\\Protobuf\\Internal\\GPBType;\n"
1025  "use Google\\Protobuf\\Internal\\RepeatedField;\n"
1026  "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
1027  } else {
1028  printer->Print(
1029  "use Google\\Protobuf\\Internal\\GPBType;\n"
1030  "use Google\\Protobuf\\Internal\\GPBWire;\n"
1031  "use Google\\Protobuf\\Internal\\RepeatedField;\n"
1032  "use Google\\Protobuf\\Internal\\InputStream;\n"
1033  "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
1034  }
1035 }
1036 
1037 void GenerateHead(const FileDescriptor* file, io::Printer* printer) {
1038  printer->Print(
1039  "<?php\n"
1040  "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
1041  "# source: ^filename^\n"
1042  "\n",
1043  "filename", file->name());
1044 }
1045 
1046 std::string FilenameToClassname(const string& filename) {
1047  int lastindex = filename.find_last_of(".");
1048  std::string result = filename.substr(0, lastindex);
1049  for (int i = 0; i < result.size(); i++) {
1050  if (result[i] == '/') {
1051  result[i] = '\\';
1052  }
1053  }
1054  return result;
1055 }
1056 
1058  bool is_descriptor,
1059  GeneratorContext* generator_context) {
1060  std::string filename = GeneratedMetadataFileName(file, is_descriptor);
1061  std::unique_ptr<io::ZeroCopyOutputStream> output(
1062  generator_context->Open(filename));
1063  io::Printer printer(output.get(), '^');
1064 
1065  GenerateHead(file, &printer);
1066 
1067  std::string fullname = FilenameToClassname(filename);
1068  int lastindex = fullname.find_last_of("\\");
1069 
1070  if (lastindex != string::npos) {
1071  printer.Print(
1072  "namespace ^name^;\n\n",
1073  "name", fullname.substr(0, lastindex));
1074 
1075  printer.Print(
1076  "class ^name^\n"
1077  "{\n",
1078  "name", fullname.substr(lastindex + 1));
1079  } else {
1080  printer.Print(
1081  "class ^name^\n"
1082  "{\n",
1083  "name", fullname);
1084  }
1085  Indent(&printer);
1086 
1087  GenerateAddFileToPool(file, is_descriptor, &printer);
1088 
1089  Outdent(&printer);
1090  printer.Print("}\n\n");
1091 }
1092 
1093 template <typename DescriptorType>
1094 void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
1095  bool is_descriptor,
1096  GeneratorContext* generator_context) {
1097 
1098  std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
1099  std::unique_ptr<io::ZeroCopyOutputStream> output(
1100  generator_context->Open(filename));
1101  io::Printer printer(output.get(), '^');
1102 
1103  GenerateHead(file, &printer);
1104 
1105  std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
1106  if (php_namespace != "") {
1107  printer.Print(
1108  "namespace ^name^;\n\n",
1109  "name", php_namespace);
1110  }
1111  std::string newname = FullClassName(desc, is_descriptor);
1112  printer.Print("if (false) {\n");
1113  Indent(&printer);
1114  printer.Print("/**\n");
1115  printer.Print(" * This class is deprecated. Use ^new^ instead.\n",
1116  "new", newname);
1117  printer.Print(" * @deprecated\n");
1118  printer.Print(" */\n");
1119  printer.Print("class ^old^ {}\n",
1120  "old", LegacyGeneratedClassName(desc));
1121  Outdent(&printer);
1122  printer.Print("}\n");
1123  printer.Print("class_exists(^new^::class);\n",
1124  "new", GeneratedClassNameImpl(desc));
1125  printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
1126  "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
1127  "old", LegacyFullClassName(desc, is_descriptor),
1128  "fullname", newname);
1129 }
1130 
1131 void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
1132  bool is_descriptor, GeneratorContext* generator_context) {
1133  std::string filename = GeneratedClassFileName(en, is_descriptor);
1134  std::unique_ptr<io::ZeroCopyOutputStream> output(
1135  generator_context->Open(filename));
1136  io::Printer printer(output.get(), '^');
1137 
1138  GenerateHead(file, &printer);
1139 
1140  std::string fullname = FilenameToClassname(filename);
1141  int lastindex = fullname.find_last_of("\\");
1142 
1143  if (lastindex != string::npos) {
1144  printer.Print(
1145  "namespace ^name^;\n\n",
1146  "name", fullname.substr(0, lastindex));
1147 
1148  // We only need this 'use' statement if the enum has a namespace.
1149  // Otherwise, we get a warning that the use statement has no effect.
1150  printer.Print("use UnexpectedValueException;\n\n");
1151  }
1152 
1153  GenerateEnumDocComment(&printer, en, is_descriptor);
1154 
1155  if (lastindex != string::npos) {
1156  fullname = fullname.substr(lastindex + 1);
1157  }
1158 
1159  printer.Print(
1160  "class ^name^\n"
1161  "{\n",
1162  "name", fullname);
1163  Indent(&printer);
1164 
1165  for (int i = 0; i < en->value_count(); i++) {
1166  const EnumValueDescriptor* value = en->value(i);
1168  printer.Print("const ^name^ = ^number^;\n",
1169  "name", ConstantNamePrefix(value->name()) + value->name(),
1170  "number", IntToString(value->number()));
1171  }
1172 
1173  printer.Print("\nprivate static $valueToName = [\n");
1174  Indent(&printer);
1175  for (int i = 0; i < en->value_count(); i++) {
1176  const EnumValueDescriptor* value = en->value(i);
1177  printer.Print("self::^name^ => '^name^',\n",
1178  "name", ConstantNamePrefix(value->name()) + value->name());
1179  }
1180  Outdent(&printer);
1181  printer.Print("];\n");
1182 
1183  printer.Print(
1184  "\npublic static function name($value)\n"
1185  "{\n");
1186  Indent(&printer);
1187  printer.Print("if (!isset(self::$valueToName[$value])) {\n");
1188  Indent(&printer);
1189  printer.Print("throw new UnexpectedValueException(sprintf(\n");
1190  Indent(&printer);
1191  Indent(&printer);
1192  printer.Print("'Enum %s has no name defined for value %s', __CLASS__, $value));\n");
1193  Outdent(&printer);
1194  Outdent(&printer);
1195  Outdent(&printer);
1196  printer.Print("}\n"
1197  "return self::$valueToName[$value];\n");
1198  Outdent(&printer);
1199  printer.Print("}\n\n");
1200 
1201  printer.Print(
1202  "\npublic static function value($name)\n"
1203  "{\n");
1204  Indent(&printer);
1205  printer.Print("$const = __CLASS__ . '::' . strtoupper($name);\n"
1206  "if (!defined($const)) {\n");
1207  Indent(&printer);
1208  printer.Print("throw new UnexpectedValueException(sprintf(\n");
1209  Indent(&printer);
1210  Indent(&printer);
1211  printer.Print("'Enum %s has no value defined for name %s', __CLASS__, $name));\n");
1212  Outdent(&printer);
1213  Outdent(&printer);
1214  Outdent(&printer);
1215  printer.Print("}\n"
1216  "return constant($const);\n");
1217  Outdent(&printer);
1218  printer.Print("}\n");
1219 
1220  Outdent(&printer);
1221  printer.Print("}\n\n");
1222 
1223  // write legacy file for backwards compatiblity with nested messages and enums
1224  if (en->containing_type() != NULL) {
1225  printer.Print(
1226  "// Adding a class alias for backwards compatibility with the previous class name.\n");
1227  printer.Print(
1228  "class_alias(^new^::class, \\^old^::class);\n\n",
1229  "new", fullname,
1230  "old", LegacyFullClassName(en, is_descriptor));
1231  LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
1232  }
1233 }
1234 
1236  bool is_descriptor,
1237  GeneratorContext* generator_context) {
1238  // Don't generate MapEntry messages -- we use the PHP extension's native
1239  // support for map fields instead.
1240  if (message->options().map_entry()) {
1241  return;
1242  }
1243 
1244  std::string filename = GeneratedClassFileName(message, is_descriptor);
1245  std::unique_ptr<io::ZeroCopyOutputStream> output(
1246  generator_context->Open(filename));
1247  io::Printer printer(output.get(), '^');
1248 
1249  GenerateHead(file, &printer);
1250 
1251  std::string fullname = FilenameToClassname(filename);
1252  int lastindex = fullname.find_last_of("\\");
1253 
1254  if (lastindex != string::npos) {
1255  printer.Print(
1256  "namespace ^name^;\n\n",
1257  "name", fullname.substr(0, lastindex));
1258  }
1259 
1260  GenerateUseDeclaration(is_descriptor, &printer);
1261 
1262  GenerateMessageDocComment(&printer, message, is_descriptor);
1263  if (lastindex != string::npos) {
1264  fullname = fullname.substr(lastindex + 1);
1265  }
1266 
1267  printer.Print(
1268  "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
1269  "{\n",
1270  "name", fullname);
1271  Indent(&printer);
1272 
1273  // Field and oneof definitions.
1274  for (int i = 0; i < message->field_count(); i++) {
1275  const FieldDescriptor* field = message->field(i);
1276  GenerateField(field, &printer, is_descriptor);
1277  }
1278  for (int i = 0; i < message->oneof_decl_count(); i++) {
1279  const OneofDescriptor* oneof = message->oneof_decl(i);
1280  GenerateOneofField(oneof, &printer);
1281  }
1282  printer.Print("\n");
1283 
1284  GenerateMessageConstructorDocComment(&printer, message, is_descriptor);
1285  printer.Print(
1286  "public function __construct($data = NULL) {\n");
1287  Indent(&printer);
1288 
1289  std::string metadata_filename =
1290  GeneratedMetadataFileName(file, is_descriptor);
1291  std::string metadata_fullname = FilenameToClassname(metadata_filename);
1292  printer.Print(
1293  "\\^fullname^::initOnce();\n"
1294  "parent::__construct($data);\n",
1295  "fullname", metadata_fullname);
1296 
1297  Outdent(&printer);
1298  printer.Print("}\n\n");
1299 
1300  // Field and oneof accessors.
1301  for (int i = 0; i < message->field_count(); i++) {
1302  const FieldDescriptor* field = message->field(i);
1303  GenerateFieldAccessor(field, is_descriptor, &printer);
1304  }
1305  for (int i = 0; i < message->oneof_decl_count(); i++) {
1306  const OneofDescriptor* oneof = message->oneof_decl(i);
1307  printer.Print(
1308  "/**\n"
1309  " * @return string\n"
1310  " */\n"
1311  "public function get^camel_name^()\n"
1312  "{\n"
1313  " return $this->whichOneof(\"^name^\");\n"
1314  "}\n\n",
1315  "camel_name", UnderscoresToCamelCase(oneof->name(), true), "name",
1316  oneof->name());
1317  }
1318 
1319  Outdent(&printer);
1320  printer.Print("}\n\n");
1321 
1322  // write legacy file for backwards compatiblity with nested messages and enums
1323  if (message->containing_type() != NULL) {
1324  printer.Print(
1325  "// Adding a class alias for backwards compatibility with the previous class name.\n");
1326  printer.Print(
1327  "class_alias(^new^::class, \\^old^::class);\n\n",
1328  "new", fullname,
1329  "old", LegacyFullClassName(message, is_descriptor));
1330  LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
1331  }
1332 
1333  // Nested messages and enums.
1334  for (int i = 0; i < message->nested_type_count(); i++) {
1335  GenerateMessageFile(file, message->nested_type(i), is_descriptor,
1336  generator_context);
1337  }
1338  for (int i = 0; i < message->enum_type_count(); i++) {
1339  GenerateEnumFile(file, message->enum_type(i), is_descriptor,
1340  generator_context);
1341  }
1342 }
1343 
1345  const ServiceDescriptor* service, bool is_descriptor,
1346  GeneratorContext* generator_context) {
1347  std::string filename = GeneratedServiceFileName(service, is_descriptor);
1348  std::unique_ptr<io::ZeroCopyOutputStream> output(
1349  generator_context->Open(filename));
1350  io::Printer printer(output.get(), '^');
1351 
1352  GenerateHead(file, &printer);
1353 
1354  std::string fullname = FilenameToClassname(filename);
1355  int lastindex = fullname.find_last_of("\\");
1356 
1357  if (!file->options().php_namespace().empty() ||
1358  (!file->options().has_php_namespace() && !file->package().empty()) ||
1359  lastindex != string::npos) {
1360  printer.Print(
1361  "namespace ^name^;\n\n",
1362  "name", fullname.substr(0, lastindex));
1363  }
1364 
1365  GenerateServiceDocComment(&printer, service);
1366 
1367  if (lastindex != string::npos) {
1368  printer.Print(
1369  "interface ^name^\n"
1370  "{\n",
1371  "name", fullname.substr(lastindex + 1));
1372  } else {
1373  printer.Print(
1374  "interface ^name^\n"
1375  "{\n",
1376  "name", fullname);
1377  }
1378 
1379  Indent(&printer);
1380 
1381  for (int i = 0; i < service->method_count(); i++) {
1382  const MethodDescriptor* method = service->method(i);
1384  GenerateServiceMethod(method, &printer);
1385  }
1386 
1387  Outdent(&printer);
1388  printer.Print("}\n\n");
1389 }
1390 
1391 void GenerateFile(const FileDescriptor* file, bool is_descriptor,
1392  GeneratorContext* generator_context) {
1393  GenerateMetadataFile(file, is_descriptor, generator_context);
1394  for (int i = 0; i < file->message_type_count(); i++) {
1395  GenerateMessageFile(file, file->message_type(i), is_descriptor,
1396  generator_context);
1397  }
1398  for (int i = 0; i < file->enum_type_count(); i++) {
1399  GenerateEnumFile(file, file->enum_type(i), is_descriptor,
1400  generator_context);
1401  }
1402  if (file->options().php_generic_services()) {
1403  for (int i = 0; i < file->service_count(); i++) {
1404  GenerateServiceFile(file, file->service(i), is_descriptor,
1405  generator_context);
1406  }
1407  }
1408 }
1409 
1410 static string EscapePhpdoc(const string& input) {
1411  string result;
1412  result.reserve(input.size() * 2);
1413 
1414  char prev = '*';
1415 
1416  for (string::size_type i = 0; i < input.size(); i++) {
1417  char c = input[i];
1418  switch (c) {
1419  case '*':
1420  // Avoid "/*".
1421  if (prev == '/') {
1422  result.append("&#42;");
1423  } else {
1424  result.push_back(c);
1425  }
1426  break;
1427  case '/':
1428  // Avoid "*/".
1429  if (prev == '*') {
1430  result.append("&#47;");
1431  } else {
1432  result.push_back(c);
1433  }
1434  break;
1435  case '@':
1436  // '@' starts phpdoc tags including the @deprecated tag, which will
1437  // cause a compile-time error if inserted before a declaration that
1438  // does not have a corresponding @Deprecated annotation.
1439  result.append("&#64;");
1440  break;
1441  default:
1442  result.push_back(c);
1443  break;
1444  }
1445 
1446  prev = c;
1447  }
1448 
1449  return result;
1450 }
1451 
1453  io::Printer* printer, const SourceLocation& location, bool trailingNewline,
1454  int indentCount) {
1455  string comments = location.leading_comments.empty() ?
1456  location.trailing_comments : location.leading_comments;
1457  if (!comments.empty()) {
1458  // TODO(teboring): Ideally we should parse the comment text as Markdown and
1459  // write it back as HTML, but this requires a Markdown parser. For now
1460  // we just use the proto comments unchanged.
1461 
1462  // If the comment itself contains block comment start or end markers,
1463  // HTML-escape them so that they don't accidentally close the doc comment.
1464  comments = EscapePhpdoc(comments);
1465 
1466  std::vector<string> lines = Split(comments, "\n");
1467  while (!lines.empty() && lines.back().empty()) {
1468  lines.pop_back();
1469  }
1470 
1471  for (int i = 0; i < lines.size(); i++) {
1472  // Most lines should start with a space. Watch out for lines that start
1473  // with a /, since putting that right after the leading asterisk will
1474  // close the comment.
1475  if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') {
1476  printer->Print(" * ^line^\n", "line", lines[i]);
1477  } else {
1478  std::string indent = std::string(indentCount, ' ');
1479  printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]);
1480  }
1481  }
1482  if (trailingNewline) {
1483  printer->Print(" *\n");
1484  }
1485  }
1486 }
1487 
1488 template <typename DescriptorType>
1490  io::Printer* printer, const DescriptorType* descriptor) {
1492  if (descriptor->GetSourceLocation(&location)) {
1493  GenerateDocCommentBodyForLocation(printer, location, true, 0);
1494  }
1495 }
1496 
1497 static string FirstLineOf(const string& value) {
1498  string result = value;
1499 
1500  string::size_type pos = result.find_first_of('\n');
1501  if (pos != string::npos) {
1502  result.erase(pos);
1503  }
1504 
1505  return result;
1506 }
1507 
1509  const Descriptor* message, int is_descriptor) {
1510  printer->Print("/**\n");
1511  GenerateDocCommentBody(printer, message);
1512  printer->Print(
1513  " * Generated from protobuf message <code>^messagename^</code>\n"
1514  " */\n",
1515  "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
1516  "messagename", EscapePhpdoc(message->full_name()));
1517 }
1518 
1520  const Descriptor* message,
1521  int is_descriptor) {
1522  // In theory we should have slightly different comments for setters, getters,
1523  // etc., but in practice everyone already knows the difference between these
1524  // so it's redundant information.
1525 
1526  // We start the comment with the main body based on the comments from the
1527  // .proto file (if present). We then end with the field declaration, e.g.:
1528  // optional string foo = 5;
1529  // If the field is a group, the debug string might end with {.
1530  printer->Print("/**\n");
1531  printer->Print(" * Constructor.\n");
1532  printer->Print(" *\n");
1533  printer->Print(" * @param array $data {\n");
1534  printer->Print(" * Optional. Data for populating the Message object.\n");
1535  printer->Print(" *\n");
1536  for (int i = 0; i < message->field_count(); i++) {
1537  const FieldDescriptor* field = message->field(i);
1538  printer->Print(" * @type ^php_type^ $^var^\n",
1539  "php_type", PhpSetterTypeName(field, is_descriptor),
1540  "var", field->name());
1542  if (field->GetSourceLocation(&location)) {
1543  GenerateDocCommentBodyForLocation(printer, location, false, 10);
1544  }
1545  }
1546  printer->Print(" * }\n");
1547  printer->Print(" */\n");
1548 }
1549 
1551  const ServiceDescriptor* service) {
1552  printer->Print("/**\n");
1553  GenerateDocCommentBody(printer, service);
1554  printer->Print(
1555  " * Protobuf type <code>^fullname^</code>\n"
1556  " */\n",
1557  "fullname", EscapePhpdoc(service->full_name()));
1558 }
1559 
1561  int is_descriptor, int function_type) {
1562  // In theory we should have slightly different comments for setters, getters,
1563  // etc., but in practice everyone already knows the difference between these
1564  // so it's redundant information.
1565 
1566  // We start the comment with the main body based on the comments from the
1567  // .proto file (if present). We then end with the field declaration, e.g.:
1568  // optional string foo = 5;
1569  // If the field is a group, the debug string might end with {.
1570  printer->Print("/**\n");
1571  GenerateDocCommentBody(printer, field);
1572  printer->Print(
1573  " * Generated from protobuf field <code>^def^</code>\n",
1574  "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
1575  if (function_type == kFieldSetter) {
1576  printer->Print(" * @param ^php_type^ $var\n",
1577  "php_type", PhpSetterTypeName(field, is_descriptor));
1578  printer->Print(" * @return $this\n");
1579  } else if (function_type == kFieldGetter) {
1580  printer->Print(" * @return ^php_type^\n",
1581  "php_type", PhpGetterTypeName(field, is_descriptor));
1582  }
1583  printer->Print(" */\n");
1584 }
1585 
1587  // Generate a doc comment for the special getXXXValue methods that are
1588  // generated for wrapper types.
1589  const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value");
1590  printer->Print("/**\n");
1591  printer->Print(
1592  " * Returns the unboxed value from <code>get^camel_name^()</code>\n\n",
1593  "camel_name", UnderscoresToCamelCase(field->name(), true));
1594  GenerateDocCommentBody(printer, field);
1595  printer->Print(
1596  " * Generated from protobuf field <code>^def^</code>\n",
1597  "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
1598  printer->Print(" * @return ^php_type^|null\n",
1599  "php_type", PhpGetterTypeName(primitiveField, false));
1600  printer->Print(" */\n");
1601 }
1602 
1604  // Generate a doc comment for the special setXXXValue methods that are
1605  // generated for wrapper types.
1606  const FieldDescriptor* primitiveField = field->message_type()->FindFieldByName("value");
1607  printer->Print("/**\n");
1608  printer->Print(
1609  " * Sets the field by wrapping a primitive type in a ^message_name^ object.\n\n",
1610  "message_name", LegacyFullClassName(field->message_type(), false));
1611  GenerateDocCommentBody(printer, field);
1612  printer->Print(
1613  " * Generated from protobuf field <code>^def^</code>\n",
1614  "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
1615  printer->Print(" * @param ^php_type^|null $var\n",
1616  "php_type", PhpSetterTypeName(primitiveField, false));
1617  printer->Print(" * @return $this\n");
1618  printer->Print(" */\n");
1619 }
1620 
1622  int is_descriptor) {
1623  printer->Print("/**\n");
1624  GenerateDocCommentBody(printer, enum_);
1625  printer->Print(
1626  " * Protobuf type <code>^fullname^</code>\n"
1627  " */\n",
1628  "fullname", EscapePhpdoc(enum_->full_name()));
1629 }
1630 
1632  const EnumValueDescriptor* value) {
1633  printer->Print("/**\n");
1634  GenerateDocCommentBody(printer, value);
1635  printer->Print(
1636  " * Generated from protobuf enum <code>^def^</code>\n"
1637  " */\n",
1638  "def", EscapePhpdoc(FirstLineOf(value->DebugString())));
1639 }
1640 
1642  const MethodDescriptor* method) {
1643  printer->Print("/**\n");
1644  GenerateDocCommentBody(printer, method);
1645  printer->Print(
1646  " * Method <code>^method_name^</code>\n"
1647  " *\n",
1648  "method_name", EscapePhpdoc(UnderscoresToCamelCase(method->name(), false)));
1649  printer->Print(
1650  " * @param \\^input_type^ $request\n",
1651  "input_type", EscapePhpdoc(FullClassName(method->input_type(), false)));
1652  printer->Print(
1653  " * @return \\^return_type^\n"
1654  " */\n",
1655  "return_type", EscapePhpdoc(FullClassName(method->output_type(), false)));
1656 }
1657 
1658 bool Generator::Generate(const FileDescriptor* file, const string& parameter,
1659  GeneratorContext* generator_context,
1660  string* error) const {
1661  bool is_descriptor = parameter == "internal";
1662 
1663  if (is_descriptor && file->name() != kDescriptorFile) {
1664  *error =
1665  "Can only generate PHP code for google/protobuf/descriptor.proto.\n";
1666  return false;
1667  }
1668 
1669  if (!is_descriptor && file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
1670  *error =
1671  "Can only generate PHP code for proto3 .proto files.\n"
1672  "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
1673  return false;
1674  }
1675 
1676  GenerateFile(file, is_descriptor, generator_context);
1677 
1678  return true;
1679 }
1680 
1681 } // namespace php
1682 } // namespace compiler
1683 } // namespace protobuf
1684 } // namespace google
kFieldGetter
const int kFieldGetter
Definition: php_generator.cc:73
google::protobuf::compiler::php::GeneratedClassNameImpl
std::string GeneratedClassNameImpl(const DescriptorType *desc)
Definition: php_generator.cc:164
google::protobuf::compiler::php::PhpGetterTypeName
std::string PhpGetterTypeName(const FieldDescriptor *field, bool is_descriptor)
Definition: php_generator.cc:511
zero_copy_stream.h
google::protobuf::io::Printer::Print
void Print(const std::map< std::string, std::string > &variables, const char *text)
Definition: printer.cc:112
FileOptions::php_generic_services
bool php_generic_services() const
Definition: descriptor.pb.h:9812
FileDescriptorSet::add_file
PROTOBUF_NAMESPACE_ID::FileDescriptorProto * add_file()
Definition: descriptor.pb.h:6554
google::protobuf::compiler::php::PhpName
std::string PhpName(const std::string &full_name, bool is_descriptor)
Definition: php_generator.cc:279
google::protobuf::compiler::php::FilenameToClassname
std::string FilenameToClassname(const string &filename)
Definition: php_generator.cc:1046
google::protobuf::FieldDescriptor::TYPE_SINT64
@ TYPE_SINT64
Definition: src/google/protobuf/descriptor.h:544
google::protobuf::FieldDescriptor::CPPTYPE_ENUM
@ CPPTYPE_ENUM
Definition: src/google/protobuf/descriptor.h:561
google::protobuf::RepeatedPtrField
Definition: command_line_interface.h:62
name
GLuint const GLchar * name
Definition: glcorearb.h:3055
google::protobuf::compiler::php::GenerateEnumFile
void GenerateEnumFile(const FileDescriptor *file, const EnumDescriptor *en, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1131
FileDescriptorProto::clear_extension
void clear_extension()
Definition: descriptor.pb.h:6947
google::protobuf::compiler::php::GeneratedClassName
std::string GeneratedClassName(const Descriptor *desc)
Definition: php_generator.cc:180
php_generator.h
google::protobuf::value
const Descriptor::ReservedRange value
Definition: src/google/protobuf/descriptor.h:1954
google::protobuf::FieldDescriptor::CPPTYPE_STRING
@ CPPTYPE_STRING
Definition: src/google/protobuf/descriptor.h:562
google::protobuf::FieldDescriptor
Definition: src/google/protobuf/descriptor.h:515
google::protobuf::FileDescriptor::enum_type
const EnumDescriptor * enum_type(int index) const
google::protobuf::compiler::php::ConstantNamePrefix
std::string ConstantNamePrefix(const string &classname)
Definition: php_generator.cc:216
google::protobuf::compiler::php::DescriptorFullName
std::string DescriptorFullName(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:142
google::protobuf::compiler::php::DefaultForField
std::string DefaultForField(FieldDescriptor *field)
google::protobuf::compiler::php::GenerateServiceMethodDocComment
void GenerateServiceMethodDocComment(io::Printer *printer, const MethodDescriptor *method)
Definition: php_generator.cc:1641
NULL
NULL
Definition: test_security_zap.cpp:405
google::protobuf::compiler::php::GenerateFile
void GenerateFile(const FileDescriptor *file, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1391
src
GLenum src
Definition: glcorearb.h:3364
google::protobuf::compiler::php::EscapeDollor
std::string EscapeDollor(const string &to_escape)
Definition: php_generator.cc:589
google::protobuf::StrCat
string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: strutil.cc:1480
google::protobuf::FieldDescriptor::TYPE_SINT32
@ TYPE_SINT32
Definition: src/google/protobuf/descriptor.h:543
indent
static int indent(upb_textprinter *p)
Definition: php/ext/google/protobuf/upb.c:8400
google::protobuf::compiler::php::PhpSetterTypeName
std::string PhpSetterTypeName(const FieldDescriptor *field, bool is_descriptor)
Definition: php_generator.cc:461
input
std::string input
Definition: tokenizer_unittest.cc:197
google::protobuf::compiler::php::GenerateFieldDocComment
void GenerateFieldDocComment(io::Printer *printer, const FieldDescriptor *field, int is_descriptor, int function_type)
Definition: php_generator.cc:1560
google::protobuf::EnumDescriptor::value_count
int value_count() const
google::protobuf::compiler::php::LegacyGenerateClassFile
void LegacyGenerateClassFile(const FileDescriptor *file, const DescriptorType *desc, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1094
google::protobuf::FieldDescriptor::TYPE_BYTES
@ TYPE_BYTES
Definition: src/google/protobuf/descriptor.h:538
google::protobuf::compiler::php::GenerateMessageConstructorDocComment
void GenerateMessageConstructorDocComment(io::Printer *printer, const Descriptor *message, int is_descriptor)
Definition: php_generator.cc:1519
google::protobuf::compiler::php::LegacyFullClassName
std::string LegacyFullClassName(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:270
google::protobuf::ServiceDescriptor::full_name
const std::string & full_name() const
google::protobuf::compiler::php::BinaryToHex
std::string BinaryToHex(const string &binary)
Definition: php_generator.cc:593
kDescriptorDirName
const std::string kDescriptorDirName
Definition: php_generator.cc:48
google::protobuf::compiler::GeneratorContext::Open
virtual io::ZeroCopyOutputStream * Open(const std::string &filename)=0
google::protobuf::compiler::php::GenerateMetadataFile
void GenerateMetadataFile(const FileDescriptor *file, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1057
google::protobuf::RepeatedPtrField::end
iterator end()
Definition: repeated_field.h:2459
google::protobuf::Descriptor::containing_type
const Descriptor * containing_type() const
kReservedNames
const char *const kReservedNames[]
Definition: php_generator.cc:50
FileDescriptorProto::mutable_dependency
std::string * mutable_dependency(int index)
Definition: descriptor.pb.h:6739
desc
#define desc
Definition: extension_set.h:342
google::protobuf::RepeatedPtrField::erase
iterator erase(const_iterator position)
Definition: repeated_field.h:2152
google::protobuf::OneofDescriptor
Definition: src/google/protobuf/descriptor.h:843
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
kValidConstantNamesSize
const int kValidConstantNamesSize
Definition: php_generator.cc:71
google::protobuf::SourceLocation
Definition: src/google/protobuf/descriptor.h:145
plugin.h
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
google::protobuf::OneofDescriptor::name
const std::string & name() const
google::protobuf::compiler::php::GenerateWrapperFieldSetterDocComment
void GenerateWrapperFieldSetterDocComment(io::Printer *printer, const FieldDescriptor *field)
Definition: php_generator.cc:1603
google::protobuf::compiler::php::GenerateMessageToPool
void GenerateMessageToPool(const string &name_prefix, const Descriptor *message, io::Printer *printer)
Definition: php_generator.cc:851
error
Definition: cJSON.c:88
google::protobuf::OneofDescriptor::field
const FieldDescriptor * field(int index) const
Definition: src/google/protobuf/descriptor.h:2179
google::protobuf::FileDescriptor::enum_type_count
int enum_type_count() const
google::protobuf::FileDescriptor::syntax
Syntax syntax() const
Definition: src/google/protobuf/descriptor.h:2175
google::protobuf::EnumValueDescriptor::name
const std::string & name() const
message_type
zend_class_entry * message_type
Definition: php/ext/google/protobuf/message.c:45
google::protobuf::FileDescriptor::package
const std::string & package() const
google::protobuf::ServiceDescriptor
Definition: src/google/protobuf/descriptor.h:1152
google::protobuf::io::Printer::Indent
void Indent()
Definition: printer.cc:185
google::protobuf::compiler::php::IntToString
std::string IntToString(int32 value)
Definition: php_generator.cc:422
google::protobuf::int32
int32_t int32
Definition: protobuf/src/google/protobuf/stubs/port.h:150
google::protobuf::compiler::php::LabelForField
std::string LabelForField(FieldDescriptor *field)
google::protobuf::compiler::php::GeneratedServiceFileName
std::string GeneratedServiceFileName(const ServiceDescriptor *service, bool is_descriptor)
Definition: php_generator.cc:411
kEmptyMetadataFile
const std::string kEmptyMetadataFile
Definition: php_generator.cc:45
google::protobuf::compiler::php::GenerateServiceDocComment
void GenerateServiceDocComment(io::Printer *printer, const ServiceDescriptor *service)
Definition: php_generator.cc:1550
google::protobuf::compiler::php::GenerateEnumDocComment
void GenerateEnumDocComment(io::Printer *printer, const EnumDescriptor *enum_, int is_descriptor)
Definition: php_generator.cc:1621
google::protobuf::compiler::php::GenerateHead
void GenerateHead(const FileDescriptor *file, io::Printer *printer)
Definition: php_generator.cc:1037
google::protobuf::FieldDescriptor::LABEL_REQUIRED
@ LABEL_REQUIRED
Definition: src/google/protobuf/descriptor.h:573
google::protobuf::EnumDescriptor::name
const std::string & name() const
strutil.h
google::protobuf::FieldDescriptor::TYPE_UINT32
@ TYPE_UINT32
Definition: src/google/protobuf/descriptor.h:539
google::protobuf::FileDescriptor::service
const ServiceDescriptor * service(int index) const
prefix
static const char prefix[]
Definition: test_pair_ipc.cpp:26
google::protobuf::EnumDescriptor::value
const EnumValueDescriptor * value(int index) const
google::protobuf::compiler::php::Outdent
void Outdent(io::Printer *printer)
Definition: php_generator.cc:618
printer.h
google::protobuf::FieldDescriptor::TYPE_BOOL
@ TYPE_BOOL
Definition: src/google/protobuf/descriptor.h:533
google::protobuf.internal::RepeatedPtrIterator
Definition: repeated_field.h:369
kEmptyFile
const std::string kEmptyFile
Definition: php_generator.cc:44
google::protobuf::FieldDescriptor::TYPE_STRING
@ TYPE_STRING
Definition: src/google/protobuf/descriptor.h:534
google::protobuf::compiler::php::RootPhpNamespace
std::string RootPhpNamespace(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:244
code_generator.h
google::protobuf::FileDescriptor::options
const FileOptions & options() const
FileDescriptorProto
Definition: descriptor.pb.h:501
kDescriptorFile
const std::string kDescriptorFile
Definition: php_generator.cc:43
google::protobuf::FileDescriptor::SYNTAX_PROTO3
@ SYNTAX_PROTO3
Definition: src/google/protobuf/descriptor.h:1394
google::protobuf::MethodDescriptor
Definition: src/google/protobuf/descriptor.h:1234
google::protobuf::compiler::php::Indent
void Indent(io::Printer *printer)
Definition: php_generator.cc:614
field
const FieldDescriptor * field
Definition: parser_unittest.cc:2694
google::protobuf::compiler::php::GenerateMessageDocComment
void GenerateMessageDocComment(io::Printer *printer, const Descriptor *message, int is_descriptor)
Definition: php_generator.cc:1508
FileDescriptorSet
Definition: descriptor.pb.h:333
google::protobuf::compiler::php::GenerateUseDeclaration
void GenerateUseDeclaration(bool is_descriptor, io::Printer *printer)
Definition: php_generator.cc:1021
key
const SETUP_TEARDOWN_TESTCONTEXT char * key
Definition: test_wss_transport.cpp:10
google::protobuf::FileDescriptor::CopyTo
void CopyTo(FileDescriptorProto *proto) const
Definition: src/google/protobuf/descriptor.cc:2010
location
GLint location
Definition: glcorearb.h:3074
google::protobuf::io::Printer
Definition: printer.h:181
google::protobuf::compiler::php::EscapePhpdoc
static string EscapePhpdoc(const string &input)
Definition: php_generator.cc:1410
google::protobuf::compiler::php::EnumOrMessageSuffix
std::string EnumOrMessageSuffix(const FieldDescriptor *field, bool is_descriptor)
Definition: php_generator.cc:542
google::protobuf::compiler::php::ClassNamePrefix
std::string ClassNamePrefix(const string &classname, const DescriptorType *desc)
Definition: php_generator.cc:153
FileDescriptorProto::mutable_message_type
PROTOBUF_NAMESPACE_ID::DescriptorProto * mutable_message_type(int index)
Definition: descriptor.pb.h:6860
i
int i
Definition: gmock-matchers_test.cc:764
google::protobuf::FieldDescriptor::TYPE_MESSAGE
@ TYPE_MESSAGE
Definition: src/google/protobuf/descriptor.h:536
google::protobuf::FieldDescriptor::TYPE_DOUBLE
@ TYPE_DOUBLE
Definition: src/google/protobuf/descriptor.h:522
google::protobuf::compiler::php::GenerateServiceMethod
void GenerateServiceMethod(const MethodDescriptor *method, io::Printer *printer)
Definition: php_generator.cc:841
google::protobuf::FileDescriptor::name
const std::string & name() const
type
GLenum type
Definition: glcorearb.h:2695
google::protobuf::FieldDescriptor::TYPE_INT32
@ TYPE_INT32
Definition: src/google/protobuf/descriptor.h:528
google::protobuf::FieldDescriptor::TYPE_FLOAT
@ TYPE_FLOAT
Definition: src/google/protobuf/descriptor.h:523
google::protobuf::compiler::php::GenerateMessageFile
void GenerateMessageFile(const FileDescriptor *file, const Descriptor *message, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1235
kDescriptorMetadataFile
const std::string kDescriptorMetadataFile
Definition: php_generator.cc:46
google::protobuf::StringReplace
void StringReplace(const string &s, const string &oldsub, const string &newsub, bool replace_all, string *res)
Definition: strutil.cc:148
kValidConstantNames
const char *const kValidConstantNames[]
Definition: php_generator.cc:66
google::protobuf::EnumDescriptor::containing_type
const Descriptor * containing_type() const
google::protobuf::FileDescriptor::message_type
const Descriptor * message_type(int index) const
google::protobuf::compiler::php::Generator::Generate
virtual bool Generate(const FileDescriptor *file, const string &parameter, GeneratorContext *generator_context, string *error) const
Definition: php_generator.cc:1658
google::protobuf::EnumDescriptor::full_name
const std::string & full_name() const
google::protobuf::Descriptor::FindFieldByName
const FieldDescriptor * FindFieldByName(const std::string &name) const
Definition: src/google/protobuf/descriptor.cc:1615
google::protobuf::FileDescriptor::dependency
const FileDescriptor * dependency(int index) const
Definition: src/google/protobuf/descriptor.cc:7271
benchmarks.python.py_benchmark.dest
dest
Definition: py_benchmark.py:13
google::protobuf::FieldDescriptor::TYPE_FIXED64
@ TYPE_FIXED64
Definition: src/google/protobuf/descriptor.h:531
google::protobuf::FileDescriptor::service_count
int service_count() const
kFieldProperty
const int kFieldProperty
Definition: php_generator.cc:74
google::protobuf::compiler::php::GeneratedClassFileName
std::string GeneratedClassFileName(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:387
google::protobuf::Descriptor::name
const std::string & name() const
google::protobuf::ServiceDescriptor::method_count
int method_count() const
google::protobuf::EnumValueDescriptor
Definition: src/google/protobuf/descriptor.h:1075
google::protobuf::Split
std::vector< string > Split(const string &full, const char *delim, bool skip_empty=true)
Definition: strutil.h:235
google::protobuf::Descriptor
Definition: src/google/protobuf/descriptor.h:231
descriptor.h
google::protobuf::FieldDescriptor::TYPE_GROUP
@ TYPE_GROUP
Definition: src/google/protobuf/descriptor.h:535
kFieldSetter
const int kFieldSetter
Definition: php_generator.cc:72
google::protobuf::FieldDescriptor::TYPE_SFIXED32
@ TYPE_SFIXED32
Definition: src/google/protobuf/descriptor.h:541
google::protobuf::compiler::php::FirstLineOf
static string FirstLineOf(const string &value)
Definition: php_generator.cc:1497
google::protobuf::compiler::php::GenerateDocCommentBodyForLocation
static void GenerateDocCommentBodyForLocation(io::Printer *printer, const SourceLocation &location, bool trailingNewline, int indentCount)
Definition: php_generator.cc:1452
google::protobuf::ToUpper
string ToUpper(const string &s)
Definition: strutil.h:193
google::protobuf::compiler::php::GenerateEnumToPool
void GenerateEnumToPool(const EnumDescriptor *en, io::Printer *printer)
Definition: php_generator.cc:822
google::protobuf::FieldDescriptor::TYPE_UINT64
@ TYPE_UINT64
Definition: src/google/protobuf/descriptor.h:527
google::protobuf::FileDescriptor
Definition: src/google/protobuf/descriptor.h:1320
kDescriptorPackageName
const std::string kDescriptorPackageName
Definition: php_generator.cc:49
google::protobuf::compiler::php::GenerateEnumValueDocComment
void GenerateEnumValueDocComment(io::Printer *printer, const EnumValueDescriptor *value)
Definition: php_generator.cc:1631
google::protobuf::compiler::php::TypeName
std::string TypeName(FieldDescriptor *field)
google::protobuf::compiler::php::FullClassName
std::string FullClassName(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:260
FileOptions::php_metadata_namespace
const std::string & php_metadata_namespace() const
Definition: descriptor.pb.h:10266
google::protobuf::compiler::php::IsWrapperType
bool IsWrapperType(const FieldDescriptor *descriptor)
Definition: php_generator.h:61
google::protobuf::FieldDescriptor::LABEL_REPEATED
@ LABEL_REPEATED
Definition: src/google/protobuf/descriptor.h:574
google::protobuf::FieldDescriptor::TYPE_INT64
@ TYPE_INT64
Definition: src/google/protobuf/descriptor.h:524
google::protobuf::FieldDescriptor::LABEL_OPTIONAL
@ LABEL_OPTIONAL
Definition: src/google/protobuf/descriptor.h:572
FileOptions::php_namespace
const std::string & php_namespace() const
Definition: descriptor.pb.h:10186
val
GLuint GLfloat * val
Definition: glcorearb.h:3604
google::protobuf::ServiceDescriptor::method
const MethodDescriptor * method(int index) const
google::protobuf::compiler::php::GenerateFieldAccessor
void GenerateFieldAccessor(const FieldDescriptor *field, bool is_descriptor, io::Printer *printer)
Definition: php_generator.cc:656
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
google::protobuf::compiler::php::GenerateDocCommentBody
static void GenerateDocCommentBody(io::Printer *printer, const DescriptorType *descriptor)
Definition: php_generator.cc:1489
google::protobuf::OneofDescriptor::field_count
int field_count() const
descriptor.pb.h
binary
const GLuint GLenum const GLvoid * binary
Definition: glcorearb.h:3962
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: src/google/protobuf/descriptor.h:563
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
google::protobuf::FieldDescriptor::TYPE_ENUM
@ TYPE_ENUM
Definition: src/google/protobuf/descriptor.h:540
google::protobuf::EnumDescriptor
Definition: src/google/protobuf/descriptor.h:918
google::protobuf::FieldDescriptor::TYPE_SFIXED64
@ TYPE_SFIXED64
Definition: src/google/protobuf/descriptor.h:542
google::protobuf::compiler::php::GenerateOneofField
void GenerateOneofField(const OneofDescriptor *oneof, io::Printer *printer)
Definition: php_generator.cc:648
google::protobuf::compiler::GeneratorContext
Definition: code_generator.h:119
index
GLuint index
Definition: glcorearb.h:3055
kReservedNamesSize
const int kReservedNamesSize
Definition: php_generator.cc:70
google::protobuf::compiler::php::GeneratedMetadataFileName
std::string GeneratedMetadataFileName(const FileDescriptor *file, bool is_descriptor)
Definition: php_generator.cc:328
google::protobuf::FileDescriptor::message_type_count
int message_type_count() const
google::protobuf::RepeatedPtrField::begin
iterator begin()
Definition: repeated_field.h:2444
google::protobuf::io::Printer::Outdent
void Outdent()
Definition: printer.cc:187
google::protobuf::compiler::php::GenerateField
void GenerateField(const FieldDescriptor *field, io::Printer *printer, bool is_descriptor)
Definition: php_generator.cc:623
it
MapIter it
Definition: php/ext/google/protobuf/map.c:205
compiler
Definition: plugin.pb.cc:22
google
Definition: data_proto2_to_proto3_util.h:11
message
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glcorearb.h:2695
google::protobuf::compiler::php::LegacyGeneratedClassFileName
std::string LegacyGeneratedClassFileName(const DescriptorType *desc, bool is_descriptor)
Definition: php_generator.cc:399
google::protobuf::compiler::php::LegacyGeneratedClassName
std::string LegacyGeneratedClassName(const DescriptorType *desc)
Definition: php_generator.cc:193
google::protobuf::method
const Descriptor::ReservedRange const EnumValueDescriptor method
Definition: src/google/protobuf/descriptor.h:1973
google::protobuf::FileDescriptor::dependency_count
int dependency_count() const
google::protobuf::compiler::php::ReservedNamePrefix
std::string ReservedNamePrefix(const string &classname, const FileDescriptor *file)
Definition: php_generator.cc:116
google::protobuf::FieldDescriptor::TYPE_FIXED32
@ TYPE_FIXED32
Definition: src/google/protobuf/descriptor.h:532
google::protobuf::compiler::php::GenerateWrapperFieldGetterDocComment
void GenerateWrapperFieldGetterDocComment(io::Printer *printer, const FieldDescriptor *field)
Definition: php_generator.cc:1586
google::protobuf::compiler::php::GenerateAddFileToPool
void GenerateAddFileToPool(const FileDescriptor *file, bool is_descriptor, io::Printer *printer)
Definition: php_generator.cc:932
google::protobuf::compiler::php::UnderscoresToCamelCase
std::string UnderscoresToCamelCase(const string &name, bool cap_first_letter)
Definition: php_generator.cc:555
is_reserved
static bool is_reserved(const char *segment, int length)
Definition: def.c:732
google::protobuf::compiler::php::GenerateServiceFile
void GenerateServiceFile(const FileDescriptor *file, const ServiceDescriptor *service, bool is_descriptor, GeneratorContext *generator_context)
Definition: php_generator.cc:1344


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:57