- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / src / google / protobuf / compiler / cpp / cpp_enum.cc
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <set>
36 #include <map>
37
38 #include <google/protobuf/compiler/cpp/cpp_enum.h>
39 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
40 #include <google/protobuf/io/printer.h>
41 #include <google/protobuf/stubs/strutil.h>
42
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace cpp {
47
48 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
49                              const Options& options)
50   : descriptor_(descriptor),
51     classname_(ClassName(descriptor, false)),
52     options_(options) {
53 }
54
55 EnumGenerator::~EnumGenerator() {}
56
57 void EnumGenerator::GenerateDefinition(io::Printer* printer) {
58   map<string, string> vars;
59   vars["classname"] = classname_;
60   vars["short_name"] = descriptor_->name();
61
62   printer->Print(vars, "enum $classname$ {\n");
63   printer->Indent();
64
65   const EnumValueDescriptor* min_value = descriptor_->value(0);
66   const EnumValueDescriptor* max_value = descriptor_->value(0);
67
68   for (int i = 0; i < descriptor_->value_count(); i++) {
69     vars["name"] = descriptor_->value(i)->name();
70     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
71     vars["prefix"] = (descriptor_->containing_type() == NULL) ?
72       "" : classname_ + "_";
73
74     if (i > 0) printer->Print(",\n");
75     printer->Print(vars, "$prefix$$name$ = $number$");
76
77     if (descriptor_->value(i)->number() < min_value->number()) {
78       min_value = descriptor_->value(i);
79     }
80     if (descriptor_->value(i)->number() > max_value->number()) {
81       max_value = descriptor_->value(i);
82     }
83   }
84
85   printer->Outdent();
86   printer->Print("\n};\n");
87
88   vars["min_name"] = min_value->name();
89   vars["max_name"] = max_value->name();
90
91   if (options_.dllexport_decl.empty()) {
92     vars["dllexport"] = "";
93   } else {
94     vars["dllexport"] = options_.dllexport_decl + " ";
95   }
96
97   printer->Print(vars,
98     "$dllexport$bool $classname$_IsValid(int value);\n"
99     "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
100     "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
101     "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
102     "\n");
103
104   if (HasDescriptorMethods(descriptor_->file())) {
105     printer->Print(vars,
106       "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
107     // The _Name and _Parse methods
108     printer->Print(vars,
109       "inline const ::std::string& $classname$_Name($classname$ value) {\n"
110       "  return ::google::protobuf::internal::NameOfEnum(\n"
111       "    $classname$_descriptor(), value);\n"
112       "}\n");
113     printer->Print(vars,
114       "inline bool $classname$_Parse(\n"
115       "    const ::std::string& name, $classname$* value) {\n"
116       "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
117       "    $classname$_descriptor(), name, value);\n"
118       "}\n");
119   }
120 }
121
122 void EnumGenerator::
123 GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
124   if (HasDescriptorMethods(descriptor_->file())) {
125     printer->Print(
126       "template <>\n"
127       "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
128       "  return $classname$_descriptor();\n"
129       "}\n",
130       "classname", ClassName(descriptor_, true));
131   }
132 }
133
134 void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
135   map<string, string> vars;
136   vars["nested_name"] = descriptor_->name();
137   vars["classname"] = classname_;
138   printer->Print(vars, "typedef $classname$ $nested_name$;\n");
139
140   for (int j = 0; j < descriptor_->value_count(); j++) {
141     vars["tag"] = descriptor_->value(j)->name();
142     printer->Print(vars,
143       "static const $nested_name$ $tag$ = $classname$_$tag$;\n");
144   }
145
146   printer->Print(vars,
147     "static inline bool $nested_name$_IsValid(int value) {\n"
148     "  return $classname$_IsValid(value);\n"
149     "}\n"
150     "static const $nested_name$ $nested_name$_MIN =\n"
151     "  $classname$_$nested_name$_MIN;\n"
152     "static const $nested_name$ $nested_name$_MAX =\n"
153     "  $classname$_$nested_name$_MAX;\n"
154     "static const int $nested_name$_ARRAYSIZE =\n"
155     "  $classname$_$nested_name$_ARRAYSIZE;\n");
156
157   if (HasDescriptorMethods(descriptor_->file())) {
158     printer->Print(vars,
159       "static inline const ::google::protobuf::EnumDescriptor*\n"
160       "$nested_name$_descriptor() {\n"
161       "  return $classname$_descriptor();\n"
162       "}\n");
163     printer->Print(vars,
164       "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
165       "  return $classname$_Name(value);\n"
166       "}\n");
167     printer->Print(vars,
168       "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
169       "    $nested_name$* value) {\n"
170       "  return $classname$_Parse(name, value);\n"
171       "}\n");
172   }
173 }
174
175 void EnumGenerator::GenerateDescriptorInitializer(
176     io::Printer* printer, int index) {
177   map<string, string> vars;
178   vars["classname"] = classname_;
179   vars["index"] = SimpleItoa(index);
180
181   if (descriptor_->containing_type() == NULL) {
182     printer->Print(vars,
183       "$classname$_descriptor_ = file->enum_type($index$);\n");
184   } else {
185     vars["parent"] = ClassName(descriptor_->containing_type(), false);
186     printer->Print(vars,
187       "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
188   }
189 }
190
191 void EnumGenerator::GenerateMethods(io::Printer* printer) {
192   map<string, string> vars;
193   vars["classname"] = classname_;
194
195   if (HasDescriptorMethods(descriptor_->file())) {
196     printer->Print(vars,
197       "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
198       "  protobuf_AssignDescriptorsOnce();\n"
199       "  return $classname$_descriptor_;\n"
200       "}\n");
201   }
202
203   printer->Print(vars,
204     "bool $classname$_IsValid(int value) {\n"
205     "  switch(value) {\n");
206
207   // Multiple values may have the same number.  Make sure we only cover
208   // each number once by first constructing a set containing all valid
209   // numbers, then printing a case statement for each element.
210
211   set<int> numbers;
212   for (int j = 0; j < descriptor_->value_count(); j++) {
213     const EnumValueDescriptor* value = descriptor_->value(j);
214     numbers.insert(value->number());
215   }
216
217   for (set<int>::iterator iter = numbers.begin();
218        iter != numbers.end(); ++iter) {
219     printer->Print(
220       "    case $number$:\n",
221       "number", SimpleItoa(*iter));
222   }
223
224   printer->Print(vars,
225     "      return true;\n"
226     "    default:\n"
227     "      return false;\n"
228     "  }\n"
229     "}\n"
230     "\n");
231
232   if (descriptor_->containing_type() != NULL) {
233     // We need to "define" the static constants which were declared in the
234     // header, to give the linker a place to put them.  Or at least the C++
235     // standard says we have to.  MSVC actually insists tha we do _not_ define
236     // them again in the .cc file.
237     printer->Print("#ifndef _MSC_VER\n");
238
239     vars["parent"] = ClassName(descriptor_->containing_type(), false);
240     vars["nested_name"] = descriptor_->name();
241     for (int i = 0; i < descriptor_->value_count(); i++) {
242       vars["value"] = descriptor_->value(i)->name();
243       printer->Print(vars,
244         "const $classname$ $parent$::$value$;\n");
245     }
246     printer->Print(vars,
247       "const $classname$ $parent$::$nested_name$_MIN;\n"
248       "const $classname$ $parent$::$nested_name$_MAX;\n"
249       "const int $parent$::$nested_name$_ARRAYSIZE;\n");
250
251     printer->Print("#endif  // _MSC_VER\n");
252   }
253 }
254
255 }  // namespace cpp
256 }  // namespace compiler
257 }  // namespace protobuf
258 }  // namespace google