1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda)
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Based on original Protocol Buffers design by
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//  Sanjay Ghemawat, Jeff Dean, and others.
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <set>
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <map>
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/cpp/cpp_enum.h>
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/cpp/cpp_helpers.h>
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/printer.h>
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h>
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google {
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf {
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace compiler {
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace cpp {
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleEnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                             const string& dllexport_decl)
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  : descriptor_(descriptor),
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    classname_(ClassName(descriptor, false)),
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    dllexport_decl_(dllexport_decl) {
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleEnumGenerator::~EnumGenerator() {}
56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateDefinition(io::Printer* printer) {
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  map<string, string> vars;
59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["classname"] = classname_;
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["short_name"] = descriptor_->name();
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars, "enum $classname$ {\n");
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Indent();
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const EnumValueDescriptor* min_value = descriptor_->value(0);
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  const EnumValueDescriptor* max_value = descriptor_->value(0);
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int i = 0; i < descriptor_->value_count(); i++) {
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["name"] = descriptor_->value(i)->name();
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["prefix"] = (descriptor_->containing_type() == NULL) ?
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "" : classname_ + "_";
73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (i > 0) printer->Print(",\n");
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars, "$prefix$$name$ = $number$");
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (descriptor_->value(i)->number() < min_value->number()) {
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      min_value = descriptor_->value(i);
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (descriptor_->value(i)->number() > max_value->number()) {
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      max_value = descriptor_->value(i);
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Outdent();
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print("\n};\n");
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["min_name"] = min_value->name();
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["max_name"] = max_value->name();
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (dllexport_decl_.empty()) {
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["dllexport"] = "";
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["dllexport"] = dllexport_decl_ + " ";
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars,
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "$dllexport$bool $classname$_IsValid(int value);\n"
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "\n");
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasDescriptorMethods(descriptor_->file())) {
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // The _Name and _Parse methods
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "inline const ::std::string& $classname$_Name($classname$ value) {\n"
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return ::google::protobuf::internal::NameOfEnum(\n"
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "    $classname$_descriptor(), value);\n"
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "}\n");
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "inline bool $classname$_Parse(\n"
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "    const ::std::string& name, $classname$* value) {\n"
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "    $classname$_descriptor(), name, value);\n"
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "}\n");
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasDescriptorMethods(descriptor_->file())) {
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "template <>\n"
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return $classname$_descriptor();\n"
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "}\n",
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "classname", ClassName(descriptor_, true));
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  map<string, string> vars;
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["nested_name"] = descriptor_->name();
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["classname"] = classname_;
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars, "typedef $classname$ $nested_name$;\n");
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int j = 0; j < descriptor_->value_count(); j++) {
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["tag"] = descriptor_->value(j)->name();
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "static const $nested_name$ $tag$ = $classname$_$tag$;\n");
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars,
147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "static inline bool $nested_name$_IsValid(int value) {\n"
148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  return $classname$_IsValid(value);\n"
149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n"
150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "static const $nested_name$ $nested_name$_MIN =\n"
151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  $classname$_$nested_name$_MIN;\n"
152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "static const $nested_name$ $nested_name$_MAX =\n"
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "  $classname$_$nested_name$_MAX;\n"
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "static const int $nested_name$_ARRAYSIZE =\n"
155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    "  $classname$_$nested_name$_ARRAYSIZE;\n");
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasDescriptorMethods(descriptor_->file())) {
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "static inline const ::google::protobuf::EnumDescriptor*\n"
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "$nested_name$_descriptor() {\n"
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return $classname$_descriptor();\n"
162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "}\n");
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    printer->Print(vars,
164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return $classname$_Name(value);\n"
166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "}\n");
167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    printer->Print(vars,
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "    $nested_name$* value) {\n"
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return $classname$_Parse(name, value);\n"
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "}\n");
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateDescriptorInitializer(
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    io::Printer* printer, int index) {
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  map<string, string> vars;
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["classname"] = classname_;
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["index"] = SimpleItoa(index);
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (descriptor_->containing_type() == NULL) {
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "$classname$_descriptor_ = file->enum_type($index$);\n");
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  } else {
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["parent"] = ClassName(descriptor_->containing_type(), false);
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateMethods(io::Printer* printer) {
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  map<string, string> vars;
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  vars["classname"] = classname_;
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (HasDescriptorMethods(descriptor_->file())) {
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  protobuf_AssignDescriptorsOnce();\n"
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "  return $classname$_descriptor_;\n"
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "}\n");
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars,
204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "bool $classname$_IsValid(int value) {\n"
205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  switch(value) {\n");
206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Multiple values may have the same number.  Make sure we only cover
208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // each number once by first constructing a set containing all valid
209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // numbers, then printing a case statement for each element.
210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  set<int> numbers;
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (int j = 0; j < descriptor_->value_count(); j++) {
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    const EnumValueDescriptor* value = descriptor_->value(j);
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    numbers.insert(value->number());
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for (set<int>::iterator iter = numbers.begin();
218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville       iter != numbers.end(); ++iter) {
219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "    case $number$:\n",
221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "number", SimpleItoa(*iter));
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  printer->Print(vars,
225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "      return true;\n"
226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "    default:\n"
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "      return false;\n"
228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "  }\n"
229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "}\n"
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    "\n");
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if (descriptor_->containing_type() != NULL) {
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // We need to "define" the static constants which were declared in the
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // header, to give the linker a place to put them.  Or at least the C++
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // standard says we have to.  MSVC actually insists tha we do _not_ define
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    // them again in the .cc file.
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print("#ifndef _MSC_VER\n");
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["parent"] = ClassName(descriptor_->containing_type(), false);
240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    vars["nested_name"] = descriptor_->name();
241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for (int i = 0; i < descriptor_->value_count(); i++) {
242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      vars["value"] = descriptor_->value(i)->name();
243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      printer->Print(vars,
244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        "const $classname$ $parent$::$value$;\n");
245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print(vars,
247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      "const $classname$ $parent$::$nested_name$_MIN;\n"
248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "const $classname$ $parent$::$nested_name$_MAX;\n"
249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      "const int $parent$::$nested_name$_ARRAYSIZE;\n");
250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    printer->Print("#endif  // _MSC_VER\n");
252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace cpp
256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace compiler
257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace protobuf
258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}  // namespace google
259