15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_enum.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/cpp/cpp_helpers.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/printer.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cpp {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                             const Options& options)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : descriptor_(descriptor),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classname_(ClassName(descriptor, false)),
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    options_(options) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumGenerator::~EnumGenerator() {}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumGenerator::GenerateDefinition(io::Printer* printer) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["short_name"] = descriptor_->name();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars, "enum $classname$ {\n");
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const EnumValueDescriptor* min_value = descriptor_->value(0);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const EnumValueDescriptor* max_value = descriptor_->value(0);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < descriptor_->value_count(); i++) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["name"] = descriptor_->value(i)->name();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["number"] = SimpleItoa(descriptor_->value(i)->number());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["prefix"] = (descriptor_->containing_type() == NULL) ?
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "" : classname_ + "_";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0) printer->Print(",\n");
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars, "$prefix$$name$ = $number$");
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (descriptor_->value(i)->number() < min_value->number()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      min_value = descriptor_->value(i);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (descriptor_->value(i)->number() > max_value->number()) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_value = descriptor_->value(i);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n};\n");
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["min_name"] = min_value->name();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["max_name"] = max_value->name();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (options_.dllexport_decl.empty()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["dllexport"] = "";
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    vars["dllexport"] = options_.dllexport_decl + " ";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "$dllexport$bool $classname$_IsValid(int value);\n"
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The _Name and _Parse methods
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline const ::std::string& $classname$_Name($classname$ value) {\n"
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return ::google::protobuf::internal::NameOfEnum(\n"
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    $classname$_descriptor(), value);\n"
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline bool $classname$_Parse(\n"
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    const ::std::string& name, $classname$* value) {\n"
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    $classname$_descriptor(), name, value);\n"
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumGenerator::
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "template <>\n"
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_descriptor();\n"
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n",
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "classname", ClassName(descriptor_, true));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["nested_name"] = descriptor_->name();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars, "typedef $classname$ $nested_name$;\n");
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 0; j < descriptor_->value_count(); j++) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["tag"] = descriptor_->value(j)->name();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static const $nested_name$ $tag$ = $classname$_$tag$;\n");
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static inline bool $nested_name$_IsValid(int value) {\n"
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return $classname$_IsValid(value);\n"
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static const $nested_name$ $nested_name$_MIN =\n"
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $classname$_$nested_name$_MIN;\n"
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static const $nested_name$ $nested_name$_MAX =\n"
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $classname$_$nested_name$_MAX;\n"
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static const int $nested_name$_ARRAYSIZE =\n"
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  $classname$_$nested_name$_ARRAYSIZE;\n");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static inline const ::google::protobuf::EnumDescriptor*\n"
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$nested_name$_descriptor() {\n"
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_descriptor();\n"
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_Name(value);\n"
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    $nested_name$* value) {\n"
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_Parse(name, value);\n"
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumGenerator::GenerateDescriptorInitializer(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io::Printer* printer, int index) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["index"] = SimpleItoa(index);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->containing_type() == NULL) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$classname$_descriptor_ = file->enum_type($index$);\n");
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["parent"] = ClassName(descriptor_->containing_type(), false);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumGenerator::GenerateMethods(io::Printer* printer) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  map<string, string> vars;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vars["classname"] = classname_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(descriptor_->file())) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  protobuf_AssignDescriptorsOnce();\n"
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  return $classname$_descriptor_;\n"
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "bool $classname$_IsValid(int value) {\n"
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  switch(value) {\n");
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Multiple values may have the same number.  Make sure we only cover
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // each number once by first constructing a set containing all valid
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // numbers, then printing a case statement for each element.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set<int> numbers;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 0; j < descriptor_->value_count(); j++) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EnumValueDescriptor* value = descriptor_->value(j);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    numbers.insert(value->number());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (set<int>::iterator iter = numbers.begin();
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != numbers.end(); ++iter) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    case $number$:\n",
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "number", SimpleItoa(*iter));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(vars,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "      return true;\n"
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    default:\n"
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "      return false;\n"
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  }\n"
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n");
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor_->containing_type() != NULL) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to "define" the static constants which were declared in the
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // header, to give the linker a place to put them.  Or at least the C++
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // standard says we have to.  MSVC actually insists tha we do _not_ define
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // them again in the .cc file.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("#ifndef _MSC_VER\n");
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["parent"] = ClassName(descriptor_->containing_type(), false);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vars["nested_name"] = descriptor_->name();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < descriptor_->value_count(); i++) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vars["value"] = descriptor_->value(i)->name();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(vars,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "const $classname$ $parent$::$value$;\n");
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(vars,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const $classname$ $parent$::$nested_name$_MIN;\n"
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const $classname$ $parent$::$nested_name$_MAX;\n"
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "const int $parent$::$nested_name$_ARRAYSIZE;\n");
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("#endif  // _MSC_VER\n");
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace cpp
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace compiler
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
259