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 |