| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // http://code.google.com/p/protobuf/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| 11 // * Redistributions in binary form must reproduce the above | 11 // * Redistributions in binary form must reproduce the above |
| 12 // copyright notice, this list of conditions and the following disclaimer | 12 // copyright notice, this list of conditions and the following disclaimer |
| 13 // in the documentation and/or other materials provided with the | 13 // in the documentation and/or other materials provided with the |
| (...skipping 24 matching lines...) Expand all Loading... |
| 38 #include <google/protobuf/compiler/cpp/cpp_enum.h> | 38 #include <google/protobuf/compiler/cpp/cpp_enum.h> |
| 39 #include <google/protobuf/compiler/cpp/cpp_helpers.h> | 39 #include <google/protobuf/compiler/cpp/cpp_helpers.h> |
| 40 #include <google/protobuf/io/printer.h> | 40 #include <google/protobuf/io/printer.h> |
| 41 #include <google/protobuf/stubs/strutil.h> | 41 #include <google/protobuf/stubs/strutil.h> |
| 42 | 42 |
| 43 namespace google { | 43 namespace google { |
| 44 namespace protobuf { | 44 namespace protobuf { |
| 45 namespace compiler { | 45 namespace compiler { |
| 46 namespace cpp { | 46 namespace cpp { |
| 47 | 47 |
| 48 namespace { | |
| 49 // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum v
alue | |
| 50 // is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cas
es we should omit the | |
| 51 // generation of the GOOGLE_ARRAYSIZE constant. | |
| 52 bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { | |
| 53 int32 max_value = descriptor->value(0)->number(); | |
| 54 for (int i = 0; i < descriptor->value_count(); i++) { | |
| 55 if (descriptor->value(i)->number() > max_value) { | |
| 56 max_value = descriptor->value(i)->number(); | |
| 57 } | |
| 58 } | |
| 59 return max_value != ::google::protobuf::kint32max; | |
| 60 } | |
| 61 } // namespace | |
| 62 | |
| 63 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, | 48 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, |
| 64 const Options& options) | 49 const Options& options) |
| 65 : descriptor_(descriptor), | 50 : descriptor_(descriptor), |
| 66 classname_(ClassName(descriptor, false)), | 51 classname_(ClassName(descriptor, false)), |
| 67 options_(options), | 52 options_(options) { |
| 68 generate_array_size_(ShouldGenerateArraySize(descriptor)) { | |
| 69 } | 53 } |
| 70 | 54 |
| 71 EnumGenerator::~EnumGenerator() {} | 55 EnumGenerator::~EnumGenerator() {} |
| 72 | 56 |
| 73 void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) { | |
| 74 if (!options_.proto_h) { | |
| 75 return; | |
| 76 } | |
| 77 map<string, string> vars; | |
| 78 vars["classname"] = classname_; | |
| 79 printer->Print(vars, "enum $classname$ : int;\n"); | |
| 80 printer->Print(vars, "bool $classname$_IsValid(int value);\n"); | |
| 81 } | |
| 82 | |
| 83 void EnumGenerator::GenerateDefinition(io::Printer* printer) { | 57 void EnumGenerator::GenerateDefinition(io::Printer* printer) { |
| 84 map<string, string> vars; | 58 map<string, string> vars; |
| 85 vars["classname"] = classname_; | 59 vars["classname"] = classname_; |
| 86 vars["short_name"] = descriptor_->name(); | 60 vars["short_name"] = descriptor_->name(); |
| 87 vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : ""); | |
| 88 | 61 |
| 89 printer->Print(vars, "enum $enumbase$ {\n"); | 62 printer->Print(vars, "enum $classname$ {\n"); |
| 90 printer->Indent(); | 63 printer->Indent(); |
| 91 | 64 |
| 92 const EnumValueDescriptor* min_value = descriptor_->value(0); | 65 const EnumValueDescriptor* min_value = descriptor_->value(0); |
| 93 const EnumValueDescriptor* max_value = descriptor_->value(0); | 66 const EnumValueDescriptor* max_value = descriptor_->value(0); |
| 94 | 67 |
| 95 for (int i = 0; i < descriptor_->value_count(); i++) { | 68 for (int i = 0; i < descriptor_->value_count(); i++) { |
| 96 vars["name"] = EnumValueName(descriptor_->value(i)); | 69 vars["name"] = descriptor_->value(i)->name(); |
| 97 // In C++, an value of -2147483648 gets interpreted as the negative of | 70 vars["number"] = SimpleItoa(descriptor_->value(i)->number()); |
| 98 // 2147483648, and since 2147483648 can't fit in an integer, this produces a | |
| 99 // compiler warning. This works around that issue. | |
| 100 vars["number"] = Int32ToString(descriptor_->value(i)->number()); | |
| 101 vars["prefix"] = (descriptor_->containing_type() == NULL) ? | 71 vars["prefix"] = (descriptor_->containing_type() == NULL) ? |
| 102 "" : classname_ + "_"; | 72 "" : classname_ + "_"; |
| 103 | 73 |
| 104 if (i > 0) printer->Print(",\n"); | 74 if (i > 0) printer->Print(",\n"); |
| 105 printer->Print(vars, "$prefix$$name$ = $number$"); | 75 printer->Print(vars, "$prefix$$name$ = $number$"); |
| 106 | 76 |
| 107 if (descriptor_->value(i)->number() < min_value->number()) { | 77 if (descriptor_->value(i)->number() < min_value->number()) { |
| 108 min_value = descriptor_->value(i); | 78 min_value = descriptor_->value(i); |
| 109 } | 79 } |
| 110 if (descriptor_->value(i)->number() > max_value->number()) { | 80 if (descriptor_->value(i)->number() > max_value->number()) { |
| 111 max_value = descriptor_->value(i); | 81 max_value = descriptor_->value(i); |
| 112 } | 82 } |
| 113 } | 83 } |
| 114 | 84 |
| 115 if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { | |
| 116 // For new enum semantics: generate min and max sentinel values equal to | |
| 117 // INT32_MIN and INT32_MAX | |
| 118 if (descriptor_->value_count() > 0) printer->Print(",\n"); | |
| 119 printer->Print(vars, | |
| 120 "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::
kint32min,\n" | |
| 121 "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::
kint32max"); | |
| 122 } | |
| 123 | |
| 124 printer->Outdent(); | 85 printer->Outdent(); |
| 125 printer->Print("\n};\n"); | 86 printer->Print("\n};\n"); |
| 126 | 87 |
| 127 vars["min_name"] = EnumValueName(min_value); | 88 vars["min_name"] = min_value->name(); |
| 128 vars["max_name"] = EnumValueName(max_value); | 89 vars["max_name"] = max_value->name(); |
| 129 | 90 |
| 130 if (options_.dllexport_decl.empty()) { | 91 if (options_.dllexport_decl.empty()) { |
| 131 vars["dllexport"] = ""; | 92 vars["dllexport"] = ""; |
| 132 } else { | 93 } else { |
| 133 vars["dllexport"] = options_.dllexport_decl + " "; | 94 vars["dllexport"] = options_.dllexport_decl + " "; |
| 134 } | 95 } |
| 135 | 96 |
| 136 printer->Print(vars, | 97 printer->Print(vars, |
| 137 "$dllexport$bool $classname$_IsValid(int value);\n" | 98 "$dllexport$bool $classname$_IsValid(int value);\n" |
| 138 "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" | 99 "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" |
| 139 "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"); | 100 "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" |
| 140 | 101 "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n" |
| 141 if (generate_array_size_) { | 102 "\n"); |
| 142 printer->Print(vars, | |
| 143 "const int $prefix$$short_name$_ARRAYSIZE = " | |
| 144 "$prefix$$short_name$_MAX + 1;\n\n"); | |
| 145 } | |
| 146 | 103 |
| 147 if (HasDescriptorMethods(descriptor_->file())) { | 104 if (HasDescriptorMethods(descriptor_->file())) { |
| 148 printer->Print(vars, | 105 printer->Print(vars, |
| 149 "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descript
or();\n"); | 106 "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descript
or();\n"); |
| 150 // The _Name and _Parse methods | 107 // The _Name and _Parse methods |
| 151 printer->Print(vars, | 108 printer->Print(vars, |
| 152 "inline const ::std::string& $classname$_Name($classname$ value) {\n" | 109 "inline const ::std::string& $classname$_Name($classname$ value) {\n" |
| 153 " return ::google::protobuf::internal::NameOfEnum(\n" | 110 " return ::google::protobuf::internal::NameOfEnum(\n" |
| 154 " $classname$_descriptor(), value);\n" | 111 " $classname$_descriptor(), value);\n" |
| 155 "}\n"); | 112 "}\n"); |
| 156 printer->Print(vars, | 113 printer->Print(vars, |
| 157 "inline bool $classname$_Parse(\n" | 114 "inline bool $classname$_Parse(\n" |
| 158 " const ::std::string& name, $classname$* value) {\n" | 115 " const ::std::string& name, $classname$* value) {\n" |
| 159 " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" | 116 " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" |
| 160 " $classname$_descriptor(), name, value);\n" | 117 " $classname$_descriptor(), name, value);\n" |
| 161 "}\n"); | 118 "}\n"); |
| 162 } | 119 } |
| 163 } | 120 } |
| 164 | 121 |
| 165 void EnumGenerator:: | 122 void EnumGenerator:: |
| 166 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { | 123 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { |
| 167 printer->Print( | |
| 168 "template <> struct is_proto_enum< $classname$> : ::google::protobuf::inte
rnal::true_type " | |
| 169 "{};\n", | |
| 170 "classname", ClassName(descriptor_, true)); | |
| 171 if (HasDescriptorMethods(descriptor_->file())) { | 124 if (HasDescriptorMethods(descriptor_->file())) { |
| 172 printer->Print( | 125 printer->Print( |
| 173 "template <>\n" | 126 "template <>\n" |
| 174 "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" | 127 "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" |
| 175 " return $classname$_descriptor();\n" | 128 " return $classname$_descriptor();\n" |
| 176 "}\n", | 129 "}\n", |
| 177 "classname", ClassName(descriptor_, true)); | 130 "classname", ClassName(descriptor_, true)); |
| 178 } | 131 } |
| 179 } | 132 } |
| 180 | 133 |
| 181 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { | 134 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { |
| 182 map<string, string> vars; | 135 map<string, string> vars; |
| 183 vars["nested_name"] = descriptor_->name(); | 136 vars["nested_name"] = descriptor_->name(); |
| 184 vars["classname"] = classname_; | 137 vars["classname"] = classname_; |
| 185 printer->Print(vars, "typedef $classname$ $nested_name$;\n"); | 138 printer->Print(vars, "typedef $classname$ $nested_name$;\n"); |
| 186 | 139 |
| 187 for (int j = 0; j < descriptor_->value_count(); j++) { | 140 for (int j = 0; j < descriptor_->value_count(); j++) { |
| 188 vars["tag"] = EnumValueName(descriptor_->value(j)); | 141 vars["tag"] = descriptor_->value(j)->name(); |
| 189 printer->Print(vars, | 142 printer->Print(vars, |
| 190 "static const $nested_name$ $tag$ = $classname$_$tag$;\n"); | 143 "static const $nested_name$ $tag$ = $classname$_$tag$;\n"); |
| 191 } | 144 } |
| 192 | 145 |
| 193 printer->Print(vars, | 146 printer->Print(vars, |
| 194 "static inline bool $nested_name$_IsValid(int value) {\n" | 147 "static inline bool $nested_name$_IsValid(int value) {\n" |
| 195 " return $classname$_IsValid(value);\n" | 148 " return $classname$_IsValid(value);\n" |
| 196 "}\n" | 149 "}\n" |
| 197 "static const $nested_name$ $nested_name$_MIN =\n" | 150 "static const $nested_name$ $nested_name$_MIN =\n" |
| 198 " $classname$_$nested_name$_MIN;\n" | 151 " $classname$_$nested_name$_MIN;\n" |
| 199 "static const $nested_name$ $nested_name$_MAX =\n" | 152 "static const $nested_name$ $nested_name$_MAX =\n" |
| 200 " $classname$_$nested_name$_MAX;\n"); | 153 " $classname$_$nested_name$_MAX;\n" |
| 201 if (generate_array_size_) { | 154 "static const int $nested_name$_ARRAYSIZE =\n" |
| 202 printer->Print(vars, | 155 " $classname$_$nested_name$_ARRAYSIZE;\n"); |
| 203 "static const int $nested_name$_ARRAYSIZE =\n" | |
| 204 " $classname$_$nested_name$_ARRAYSIZE;\n"); | |
| 205 } | |
| 206 | 156 |
| 207 if (HasDescriptorMethods(descriptor_->file())) { | 157 if (HasDescriptorMethods(descriptor_->file())) { |
| 208 printer->Print(vars, | 158 printer->Print(vars, |
| 209 "static inline const ::google::protobuf::EnumDescriptor*\n" | 159 "static inline const ::google::protobuf::EnumDescriptor*\n" |
| 210 "$nested_name$_descriptor() {\n" | 160 "$nested_name$_descriptor() {\n" |
| 211 " return $classname$_descriptor();\n" | 161 " return $classname$_descriptor();\n" |
| 212 "}\n"); | 162 "}\n"); |
| 213 printer->Print(vars, | 163 printer->Print(vars, |
| 214 "static inline const ::std::string& $nested_name$_Name($nested_name$ value
) {\n" | 164 "static inline const ::std::string& $nested_name$_Name($nested_name$ value
) {\n" |
| 215 " return $classname$_Name(value);\n" | 165 " return $classname$_Name(value);\n" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 set<int> numbers; | 211 set<int> numbers; |
| 262 for (int j = 0; j < descriptor_->value_count(); j++) { | 212 for (int j = 0; j < descriptor_->value_count(); j++) { |
| 263 const EnumValueDescriptor* value = descriptor_->value(j); | 213 const EnumValueDescriptor* value = descriptor_->value(j); |
| 264 numbers.insert(value->number()); | 214 numbers.insert(value->number()); |
| 265 } | 215 } |
| 266 | 216 |
| 267 for (set<int>::iterator iter = numbers.begin(); | 217 for (set<int>::iterator iter = numbers.begin(); |
| 268 iter != numbers.end(); ++iter) { | 218 iter != numbers.end(); ++iter) { |
| 269 printer->Print( | 219 printer->Print( |
| 270 " case $number$:\n", | 220 " case $number$:\n", |
| 271 "number", Int32ToString(*iter)); | 221 "number", SimpleItoa(*iter)); |
| 272 } | 222 } |
| 273 | 223 |
| 274 printer->Print(vars, | 224 printer->Print(vars, |
| 275 " return true;\n" | 225 " return true;\n" |
| 276 " default:\n" | 226 " default:\n" |
| 277 " return false;\n" | 227 " return false;\n" |
| 278 " }\n" | 228 " }\n" |
| 279 "}\n" | 229 "}\n" |
| 280 "\n"); | 230 "\n"); |
| 281 | 231 |
| 282 if (descriptor_->containing_type() != NULL) { | 232 if (descriptor_->containing_type() != NULL) { |
| 283 // We need to "define" the static constants which were declared in the | 233 // We need to "define" the static constants which were declared in the |
| 284 // header, to give the linker a place to put them. Or at least the C++ | 234 // header, to give the linker a place to put them. Or at least the C++ |
| 285 // standard says we have to. MSVC actually insists tha we do _not_ define | 235 // standard says we have to. MSVC actually insists tha we do _not_ define |
| 286 // them again in the .cc file. | 236 // them again in the .cc file. |
| 287 printer->Print("#ifndef _MSC_VER\n"); | 237 printer->Print("#ifndef _MSC_VER\n"); |
| 288 | 238 |
| 289 vars["parent"] = ClassName(descriptor_->containing_type(), false); | 239 vars["parent"] = ClassName(descriptor_->containing_type(), false); |
| 290 vars["nested_name"] = descriptor_->name(); | 240 vars["nested_name"] = descriptor_->name(); |
| 291 for (int i = 0; i < descriptor_->value_count(); i++) { | 241 for (int i = 0; i < descriptor_->value_count(); i++) { |
| 292 vars["value"] = EnumValueName(descriptor_->value(i)); | 242 vars["value"] = descriptor_->value(i)->name(); |
| 293 printer->Print(vars, | 243 printer->Print(vars, |
| 294 "const $classname$ $parent$::$value$;\n"); | 244 "const $classname$ $parent$::$value$;\n"); |
| 295 } | 245 } |
| 296 printer->Print(vars, | 246 printer->Print(vars, |
| 297 "const $classname$ $parent$::$nested_name$_MIN;\n" | 247 "const $classname$ $parent$::$nested_name$_MIN;\n" |
| 298 "const $classname$ $parent$::$nested_name$_MAX;\n"); | 248 "const $classname$ $parent$::$nested_name$_MAX;\n" |
| 299 if (generate_array_size_) { | 249 "const int $parent$::$nested_name$_ARRAYSIZE;\n"); |
| 300 printer->Print(vars, | |
| 301 "const int $parent$::$nested_name$_ARRAYSIZE;\n"); | |
| 302 } | |
| 303 | 250 |
| 304 printer->Print("#endif // _MSC_VER\n"); | 251 printer->Print("#endif // _MSC_VER\n"); |
| 305 } | 252 } |
| 306 } | 253 } |
| 307 | 254 |
| 308 } // namespace cpp | 255 } // namespace cpp |
| 309 } // namespace compiler | 256 } // namespace compiler |
| 310 } // namespace protobuf | 257 } // namespace protobuf |
| 311 } // namespace google | 258 } // namespace google |
| OLD | NEW |