csharp_helpers.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. // Author: jonskeet@google.com (Jon Skeet)
  17. // Following the Java generator by kenton@google.com (Kenton Varda)
  18. // Based on original Protocol Buffers design by
  19. // Sanjay Ghemawat, Jeff Dean, and others.
  20. #include <vector>
  21. #include <google/protobuf/compiler/csharp/csharp_helpers.h>
  22. #include <google/protobuf/descriptor.pb.h>
  23. #include <google/protobuf/stubs/strutil.h>
  24. namespace google {
  25. namespace protobuf {
  26. namespace compiler {
  27. namespace csharp {
  28. const char kThickSeparator[] =
  29. "// ===================================================================\r\n";
  30. const char kThinSeparator[] =
  31. "// -------------------------------------------------------------------\r\n";
  32. namespace {
  33. const char* kDefaultPackage = "";
  34. const string& FieldName(const FieldDescriptor* field) {
  35. // Groups are hacky: The name of the field is just the lower-cased name
  36. // of the group type. In Java, though, we would like to retain the original
  37. // capitalization of the type name.
  38. if (field->type() == FieldDescriptor::TYPE_GROUP) {
  39. return field->message_type()->name();
  40. } else {
  41. return field->name();
  42. }
  43. }
  44. string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) {
  45. string result;
  46. // Note: I distrust ctype.h due to locales.
  47. for (int i = 0; i < input.size(); i++) {
  48. if ('a' <= input[i] && input[i] <= 'z') {
  49. if (cap_next_letter) {
  50. result += input[i] + ('A' - 'a');
  51. } else {
  52. result += input[i];
  53. }
  54. cap_next_letter = false;
  55. } else if ('A' <= input[i] && input[i] <= 'Z') {
  56. if (i == 0 && !cap_next_letter) {
  57. // Force first letter to lower-case unless explicitly told to
  58. // capitalize it.
  59. result += input[i] + ('a' - 'A');
  60. } else {
  61. // Capital letters after the first are left as-is.
  62. result += input[i];
  63. }
  64. cap_next_letter = false;
  65. } else if ('0' <= input[i] && input[i] <= '9') {
  66. result += input[i];
  67. cap_next_letter = true;
  68. } else {
  69. cap_next_letter = true;
  70. }
  71. }
  72. return result;
  73. }
  74. } // namespace
  75. string UnderscoresToCamelCase(const FieldDescriptor* field) {
  76. return UnderscoresToCamelCaseImpl(FieldName(field), false);
  77. }
  78. string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
  79. return UnderscoresToCamelCaseImpl(FieldName(field), true);
  80. }
  81. string UnderscoresToCamelCase(const MethodDescriptor* method) {
  82. return UnderscoresToCamelCaseImpl(method->name(), false);
  83. }
  84. string StripProto(const string& filename) {
  85. if (HasSuffixString(filename, ".protodevel")) {
  86. return StripSuffixString(filename, ".protodevel");
  87. } else {
  88. return StripSuffixString(filename, ".proto");
  89. }
  90. }
  91. string FileClassName(const FileDescriptor* file) {
  92. if (file->options().has_csharp_outer_classname()) {
  93. return file->options().csharp_outer_classname();
  94. } else {
  95. string basename;
  96. string::size_type last_slash = file->name().find_last_of('/');
  97. if (last_slash == string::npos) {
  98. basename = file->name();
  99. } else {
  100. basename = file->name().substr(last_slash + 1);
  101. }
  102. return UnderscoresToCamelCaseImpl(StripProto(basename), true);
  103. }
  104. }
  105. string FileJavaPackage(const FileDescriptor* file) {
  106. if (file->options().has_csharp_namespace()) {
  107. return file->options().csharp_namespace();
  108. } else {
  109. string result = kDefaultPackage;
  110. if (!file->package().empty()) {
  111. if (!result.empty()) result += '.';
  112. result += file->package();
  113. }
  114. return result;
  115. }
  116. }
  117. string ToJavaName(const string& full_name, const FileDescriptor* file) {
  118. string result;
  119. if (file->options().csharp_multiple_files()) {
  120. result = FileJavaPackage(file);
  121. } else {
  122. result = ClassName(file);
  123. }
  124. if (!result.empty()) {
  125. result += '.';
  126. }
  127. if (file->package().empty()) {
  128. result += full_name;
  129. } else {
  130. // Strip the proto package from full_name since we've replaced it with
  131. // the Java package.
  132. result += full_name.substr(file->package().size() + 1);
  133. }
  134. return result;
  135. }
  136. string ClassName(const FileDescriptor* descriptor) {
  137. string result = FileJavaPackage(descriptor);
  138. if (!result.empty()) result += '.';
  139. result += FileClassName(descriptor);
  140. return result;
  141. }
  142. JavaType GetJavaType(FieldDescriptor::Type field_type) {
  143. switch (field_type) {
  144. case FieldDescriptor::TYPE_INT32:
  145. case FieldDescriptor::TYPE_UINT32:
  146. case FieldDescriptor::TYPE_SINT32:
  147. case FieldDescriptor::TYPE_FIXED32:
  148. case FieldDescriptor::TYPE_SFIXED32:
  149. return JAVATYPE_INT;
  150. case FieldDescriptor::TYPE_INT64:
  151. case FieldDescriptor::TYPE_UINT64:
  152. case FieldDescriptor::TYPE_SINT64:
  153. case FieldDescriptor::TYPE_FIXED64:
  154. case FieldDescriptor::TYPE_SFIXED64:
  155. return JAVATYPE_LONG;
  156. case FieldDescriptor::TYPE_FLOAT:
  157. return JAVATYPE_FLOAT;
  158. case FieldDescriptor::TYPE_DOUBLE:
  159. return JAVATYPE_DOUBLE;
  160. case FieldDescriptor::TYPE_BOOL:
  161. return JAVATYPE_BOOLEAN;
  162. case FieldDescriptor::TYPE_STRING:
  163. return JAVATYPE_STRING;
  164. case FieldDescriptor::TYPE_BYTES:
  165. return JAVATYPE_BYTES;
  166. case FieldDescriptor::TYPE_ENUM:
  167. return JAVATYPE_ENUM;
  168. case FieldDescriptor::TYPE_GROUP:
  169. case FieldDescriptor::TYPE_MESSAGE:
  170. return JAVATYPE_MESSAGE;
  171. // No default because we want the compiler to complain if any new
  172. // types are added.
  173. }
  174. GOOGLE_LOG(FATAL) << "Can't get here.";
  175. return JAVATYPE_INT;
  176. }
  177. const char* BoxedPrimitiveTypeName(JavaType type) {
  178. switch (type) {
  179. case JAVATYPE_INT : return "int";
  180. case JAVATYPE_LONG : return "long";
  181. case JAVATYPE_FLOAT : return "float";
  182. case JAVATYPE_DOUBLE : return "double";
  183. case JAVATYPE_BOOLEAN: return "bool";
  184. case JAVATYPE_STRING : return "string";
  185. case JAVATYPE_BYTES : return "pb::ByteString";
  186. case JAVATYPE_ENUM : return NULL;
  187. case JAVATYPE_MESSAGE: return NULL;
  188. // No default because we want the compiler to complain if any new
  189. // JavaTypes are added.
  190. }
  191. GOOGLE_LOG(FATAL) << "Can't get here.";
  192. return NULL;
  193. }
  194. } // namespace csharp
  195. } // namespace compiler
  196. } // namespace protobuf
  197. } // namespace google