PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/google/protobuf/compiler/cpp/cpp_extension.cc

https://gitlab.com/github-cloud-corporation/protobuf
C++ | 210 lines | 142 code | 22 blank | 46 comment | 12 complexity | caae6ddc69b3749ec5a4e0ea62a7538c MD5 | raw 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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/compiler/cpp/cpp_extension.h>
  34. #include <map>
  35. #include <google/protobuf/compiler/cpp/cpp_helpers.h>
  36. #include <google/protobuf/stubs/strutil.h>
  37. #include <google/protobuf/io/printer.h>
  38. #include <google/protobuf/descriptor.pb.h>
  39. namespace google {
  40. namespace protobuf {
  41. namespace compiler {
  42. namespace cpp {
  43. namespace {
  44. // Returns the fully-qualified class name of the message that this field
  45. // extends. This function is used in the Google-internal code to handle some
  46. // legacy cases.
  47. string ExtendeeClassName(const FieldDescriptor* descriptor) {
  48. const Descriptor* extendee = descriptor->containing_type();
  49. return ClassName(extendee, true);
  50. }
  51. } // anonymous namespace
  52. ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
  53. const Options& options)
  54. : descriptor_(descriptor),
  55. options_(options) {
  56. // Construct type_traits_.
  57. if (descriptor_->is_repeated()) {
  58. type_traits_ = "Repeated";
  59. }
  60. switch (descriptor_->cpp_type()) {
  61. case FieldDescriptor::CPPTYPE_ENUM:
  62. type_traits_.append("EnumTypeTraits< ");
  63. type_traits_.append(ClassName(descriptor_->enum_type(), true));
  64. type_traits_.append(", ");
  65. type_traits_.append(ClassName(descriptor_->enum_type(), true));
  66. type_traits_.append("_IsValid>");
  67. break;
  68. case FieldDescriptor::CPPTYPE_STRING:
  69. type_traits_.append("StringTypeTraits");
  70. break;
  71. case FieldDescriptor::CPPTYPE_MESSAGE:
  72. type_traits_.append("MessageTypeTraits< ");
  73. type_traits_.append(ClassName(descriptor_->message_type(), true));
  74. type_traits_.append(" >");
  75. break;
  76. default:
  77. type_traits_.append("PrimitiveTypeTraits< ");
  78. type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type()));
  79. type_traits_.append(" >");
  80. break;
  81. }
  82. }
  83. ExtensionGenerator::~ExtensionGenerator() {}
  84. void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
  85. map<string, string> vars;
  86. vars["extendee" ] = ExtendeeClassName(descriptor_);
  87. vars["number" ] = SimpleItoa(descriptor_->number());
  88. vars["type_traits" ] = type_traits_;
  89. vars["name" ] = descriptor_->name();
  90. vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  91. vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
  92. vars["constant_name"] = FieldConstantName(descriptor_);
  93. // If this is a class member, it needs to be declared "static". Otherwise,
  94. // it needs to be "extern". In the latter case, it also needs the DLL
  95. // export/import specifier.
  96. if (descriptor_->extension_scope() == NULL) {
  97. vars["qualifier"] = "extern";
  98. if (!options_.dllexport_decl.empty()) {
  99. vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
  100. }
  101. } else {
  102. vars["qualifier"] = "static";
  103. }
  104. printer->Print(vars,
  105. "static const int $constant_name$ = $number$;\n"
  106. "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
  107. " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
  108. " $name$;\n"
  109. );
  110. }
  111. void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
  112. // If this is a class member, it needs to be declared in its class scope.
  113. string scope = (descriptor_->extension_scope() == NULL) ? "" :
  114. ClassName(descriptor_->extension_scope(), false) + "::";
  115. string name = scope + descriptor_->name();
  116. map<string, string> vars;
  117. vars["extendee" ] = ExtendeeClassName(descriptor_);
  118. vars["type_traits" ] = type_traits_;
  119. vars["name" ] = name;
  120. vars["constant_name"] = FieldConstantName(descriptor_);
  121. vars["default" ] = DefaultValue(descriptor_);
  122. vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  123. vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
  124. vars["scope" ] = scope;
  125. if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
  126. // We need to declare a global string which will contain the default value.
  127. // We cannot declare it at class scope because that would require exposing
  128. // it in the header which would be annoying for other reasons. So we
  129. // replace :: with _ in the name and declare it as a global.
  130. string global_name = StringReplace(name, "::", "_", true);
  131. vars["global_name"] = global_name;
  132. printer->Print(vars,
  133. "const ::std::string $global_name$_default($default$);\n");
  134. // Update the default to refer to the string global.
  135. vars["default"] = global_name + "_default";
  136. }
  137. // Likewise, class members need to declare the field constant variable.
  138. if (descriptor_->extension_scope() != NULL) {
  139. printer->Print(vars,
  140. "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"
  141. "const int $scope$$constant_name$;\n"
  142. "#endif\n");
  143. }
  144. printer->Print(vars,
  145. "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
  146. " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
  147. " $name$($constant_name$, $default$);\n");
  148. }
  149. void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
  150. map<string, string> vars;
  151. vars["extendee" ] = ExtendeeClassName(descriptor_);
  152. vars["number" ] = SimpleItoa(descriptor_->number());
  153. vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
  154. vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
  155. vars["is_packed" ] = (descriptor_->is_repeated() &&
  156. descriptor_->options().packed())
  157. ? "true" : "false";
  158. switch (descriptor_->cpp_type()) {
  159. case FieldDescriptor::CPPTYPE_ENUM:
  160. printer->Print(vars,
  161. "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
  162. " &$extendee$::default_instance(),\n"
  163. " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
  164. printer->Print(
  165. " &$type$_IsValid);\n",
  166. "type", ClassName(descriptor_->enum_type(), true));
  167. break;
  168. case FieldDescriptor::CPPTYPE_MESSAGE:
  169. printer->Print(vars,
  170. "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
  171. " &$extendee$::default_instance(),\n"
  172. " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
  173. printer->Print(
  174. " &$type$::default_instance());\n",
  175. "type", ClassName(descriptor_->message_type(), true));
  176. break;
  177. default:
  178. printer->Print(vars,
  179. "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
  180. " &$extendee$::default_instance(),\n"
  181. " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
  182. break;
  183. }
  184. }
  185. } // namespace cpp
  186. } // namespace compiler
  187. } // namespace protobuf
  188. } // namespace google