Initial import of v2.0.0beta
[protobuf.git] / src / google / protobuf / compiler / cpp / cpp_enum.cc
blobf78d60d8a839006aaca87c8c1b1bfa567c1d20ef
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
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.
17 // Author: kenton@google.com (Kenton Varda)
18 // Based on original Protocol Buffers design by
19 // Sanjay Ghemawat, Jeff Dean, and others.
21 #include <set>
22 #include <map>
24 #include <google/protobuf/compiler/cpp/cpp_enum.h>
25 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
26 #include <google/protobuf/io/printer.h>
27 #include <google/protobuf/stubs/strutil.h>
29 namespace google {
30 namespace protobuf {
31 namespace compiler {
32 namespace cpp {
34 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
35 const string& dllexport_decl)
36 : descriptor_(descriptor),
37 classname_(ClassName(descriptor, false)),
38 dllexport_decl_(dllexport_decl) {
41 EnumGenerator::~EnumGenerator() {}
43 void EnumGenerator::GenerateDefinition(io::Printer* printer) {
44 map<string, string> vars;
45 vars["classname"] = classname_;
46 vars["short_name"] = descriptor_->name();
48 printer->Print(vars, "enum $classname$ {\n");
49 printer->Indent();
51 const EnumValueDescriptor* min_value = descriptor_->value(0);
52 const EnumValueDescriptor* max_value = descriptor_->value(0);
54 for (int i = 0; i < descriptor_->value_count(); i++) {
55 vars["name"] = descriptor_->value(i)->name();
56 vars["number"] = SimpleItoa(descriptor_->value(i)->number());
57 vars["prefix"] = (descriptor_->containing_type() == NULL) ?
58 "" : classname_ + "_";
60 printer->Print(vars, "$prefix$$name$ = $number$,\n");
62 if (descriptor_->value(i)->number() < min_value->number()) {
63 min_value = descriptor_->value(i);
65 if (descriptor_->value(i)->number() > max_value->number()) {
66 max_value = descriptor_->value(i);
70 printer->Outdent();
71 printer->Print("};\n");
73 vars["min_name"] = min_value->name();
74 vars["max_name"] = max_value->name();
76 if (dllexport_decl_.empty()) {
77 vars["dllexport"] = "";
78 } else {
79 vars["dllexport"] = dllexport_decl_ + " ";
82 printer->Print(vars,
83 "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"
84 "$dllexport$bool $classname$_IsValid(int value);\n"
85 "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
86 "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
87 "\n");
90 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
91 map<string, string> vars;
92 vars["nested_name"] = descriptor_->name();
93 vars["classname"] = classname_;
94 printer->Print(vars, "typedef $classname$ $nested_name$;\n");
96 for (int j = 0; j < descriptor_->value_count(); j++) {
97 vars["tag"] = descriptor_->value(j)->name();
98 printer->Print(vars,
99 "static const $nested_name$ $tag$ = $classname$_$tag$;\n");
102 printer->Print(vars,
103 "static inline const ::google::protobuf::EnumDescriptor*\n"
104 "$nested_name$_descriptor() {\n"
105 " return $classname$_descriptor();\n"
106 "}\n"
107 "static inline bool $nested_name$_IsValid(int value) {\n"
108 " return $classname$_IsValid(value);\n"
109 "}\n"
110 "static const $nested_name$ $nested_name$_MIN =\n"
111 " $classname$_$nested_name$_MIN;\n"
112 "static const $nested_name$ $nested_name$_MAX =\n"
113 " $classname$_$nested_name$_MAX;\n");
116 void EnumGenerator::GenerateDescriptorInitializer(
117 io::Printer* printer, int index) {
118 map<string, string> vars;
119 vars["classname"] = classname_;
120 vars["index"] = SimpleItoa(index);
122 if (descriptor_->containing_type() == NULL) {
123 printer->Print(vars,
124 "$classname$_descriptor_ = file->enum_type($index$);\n");
125 } else {
126 vars["parent"] = ClassName(descriptor_->containing_type(), false);
127 printer->Print(vars,
128 "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
132 void EnumGenerator::GenerateMethods(io::Printer* printer) {
133 map<string, string> vars;
134 vars["classname"] = classname_;
135 vars["builddescriptorsname"] =
136 GlobalBuildDescriptorsName(descriptor_->file()->name());
138 printer->Print(vars,
139 "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
140 " if ($classname$_descriptor_ == NULL) $builddescriptorsname$();\n"
141 " return $classname$_descriptor_;\n"
142 "}\n"
143 "bool $classname$_IsValid(int value) {\n"
144 " switch(value) {\n");
146 // Multiple values may have the same number. Make sure we only cover
147 // each number once by first constructing a set containing all valid
148 // numbers, then printing a case statement for each element.
150 set<int> numbers;
151 for (int j = 0; j < descriptor_->value_count(); j++) {
152 const EnumValueDescriptor* value = descriptor_->value(j);
153 numbers.insert(value->number());
156 for (set<int>::iterator iter = numbers.begin();
157 iter != numbers.end(); ++iter) {
158 printer->Print(
159 " case $number$:\n",
160 "number", SimpleItoa(*iter));
163 printer->Print(vars,
164 " return true;\n"
165 " default:\n"
166 " return false;\n"
167 " }\n"
168 "}\n"
169 "\n");
171 if (descriptor_->containing_type() != NULL) {
172 // We need to "define" the static constants which were declared in the
173 // header, to give the linker a place to put them. Or at least the C++
174 // standard says we have to. MSVC actually insists tha we do _not_ define
175 // them again in the .cc file.
176 printer->Print("#ifndef _MSC_VER\n");
178 vars["parent"] = ClassName(descriptor_->containing_type(), false);
179 vars["nested_name"] = descriptor_->name();
180 for (int i = 0; i < descriptor_->value_count(); i++) {
181 vars["value"] = descriptor_->value(i)->name();
182 printer->Print(vars,
183 "const $classname$ $parent$::$value$;\n");
185 printer->Print(vars,
186 "const $classname$ $parent$::$nested_name$_MIN;\n"
187 "const $classname$ $parent$::$nested_name$_MAX;\n");
189 printer->Print("#endif // _MSC_VER\n");
193 } // namespace cpp
194 } // namespace compiler
195 } // namespace protobuf
196 } // namespace google