1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/ 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 <map> 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/cpp/cpp_enum.h> 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/cpp/cpp_helpers.h> 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/printer.h> 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h> 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google { 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf { 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace compiler { 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace cpp { 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 47a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonnamespace { 48a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the 50a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson// generation of the GOOGLE_ARRAYSIZE constant. 51a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonbool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { 52a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson int32 max_value = descriptor->value(0)->number(); 53a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson for (int i = 0; i < descriptor->value_count(); i++) { 54a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (descriptor->value(i)->number() > max_value) { 55a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson max_value = descriptor->value(i)->number(); 56a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson } 57a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson } 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return max_value != ::google::protobuf::kint32max; 59a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson} 60a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson} // namespace 61a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleEnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, 63a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson const Options& options) 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : descriptor_(descriptor), 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville classname_(ClassName(descriptor, false)), 66a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson options_(options), 67a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson generate_array_size_(ShouldGenerateArraySize(descriptor)) { 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleEnumGenerator::~EnumGenerator() {} 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid EnumGenerator::FillForwardDeclaration( 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map<string, const EnumDescriptor*>* enum_names) { 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!options_.proto_h) { 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return; 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (*enum_names)[classname_] = descriptor_; 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateDefinition(io::Printer* printer) { 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville map<string, string> vars; 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["classname"] = classname_; 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["short_name"] = descriptor_->name(); 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : ""); 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print(vars, "enum $enumbase$ {\n"); 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Annotate("enumbase", descriptor_); 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Indent(); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const EnumValueDescriptor* min_value = descriptor_->value(0); 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const EnumValueDescriptor* max_value = descriptor_->value(0); 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < descriptor_->value_count(); i++) { 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["name"] = EnumValueName(descriptor_->value(i)); 95a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson // In C++, an value of -2147483648 gets interpreted as the negative of 96a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson // 2147483648, and since 2147483648 can't fit in an integer, this produces a 97a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson // compiler warning. This works around that issue. 98a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson vars["number"] = Int32ToString(descriptor_->value(i)->number()); 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["prefix"] = (descriptor_->containing_type() == NULL) ? 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "" : classname_ + "_"; 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["deprecation"] = descriptor_->value(i)->options().deprecated() ? 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " PROTOBUF_DEPRECATED" : ""; 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (i > 0) printer->Print(",\n"); 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print(vars, "$prefix$$name$$deprecation$ = $number$"); 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (descriptor_->value(i)->number() < min_value->number()) { 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville min_value = descriptor_->value(i); 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (descriptor_->value(i)->number() > max_value->number()) { 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville max_value = descriptor_->value(i); 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // For new enum semantics: generate min and max sentinel values equal to 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // INT32_MIN and INT32_MAX 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (descriptor_->value_count() > 0) printer->Print(",\n"); 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print(vars, 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n" 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max"); 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Outdent(); 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print("\n};\n"); 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["min_name"] = EnumValueName(min_value); 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["max_name"] = EnumValueName(max_value); 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 130a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (options_.dllexport_decl.empty()) { 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["dllexport"] = ""; 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 133a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson vars["dllexport"] = options_.dllexport_decl + " "; 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "$dllexport$bool $classname$_IsValid(int value);\n" 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" 139a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"); 140a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 141a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (generate_array_size_) { 142a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson printer->Print(vars, 143a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "const int $prefix$$short_name$_ARRAYSIZE = " 144a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "$prefix$$short_name$_MAX + 1;\n\n"); 145a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson } 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HasDescriptorMethods(descriptor_->file(), options_)) { 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // The _Name and _Parse methods 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars, 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "inline const ::std::string& $classname$_Name($classname$ value) {\n" 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " return ::google::protobuf::internal::NameOfEnum(\n" 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " $classname$_descriptor(), value);\n" 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "}\n"); 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "inline bool $classname$_Parse(\n" 159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " const ::std::string& name, $classname$* value) {\n" 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " $classname$_descriptor(), name, value);\n" 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n"); 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator:: 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleGenerateGetEnumDescriptorSpecializations(io::Printer* printer) { 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print( 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type " 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "{};\n", 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "classname", ClassName(descriptor_, true)); 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HasDescriptorMethods(descriptor_->file(), options_)) { 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print( 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "template <>\n" 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return $classname$_descriptor();\n" 177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n", 178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "classname", ClassName(descriptor_, true)); 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateSymbolImports(io::Printer* printer) { 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville map<string, string> vars; 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["nested_name"] = descriptor_->name(); 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["classname"] = classname_; 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["constexpr"] = options_.proto_h ? "constexpr " : ""; 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, "typedef $classname$ $nested_name$;\n"); 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int j = 0; j < descriptor_->value_count(); j++) { 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["tag"] = EnumValueName(descriptor_->value(j)); 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ? 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "PROTOBUF_DEPRECATED_ATTR " : ""; 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$deprecated_attr$static $constexpr$const $nested_name$ $tag$ =\n" 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " $classname$_$tag$;\n"); 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "static inline bool $nested_name$_IsValid(int value) {\n" 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return $classname$_IsValid(value);\n" 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n" 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "static const $nested_name$ $nested_name$_MIN =\n" 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " $classname$_$nested_name$_MIN;\n" 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "static const $nested_name$ $nested_name$_MAX =\n" 205a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson " $classname$_$nested_name$_MAX;\n"); 206a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (generate_array_size_) { 207a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson printer->Print(vars, 208a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "static const int $nested_name$_ARRAYSIZE =\n" 209a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson " $classname$_$nested_name$_ARRAYSIZE;\n"); 210a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson } 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HasDescriptorMethods(descriptor_->file(), options_)) { 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "static inline const ::google::protobuf::EnumDescriptor*\n" 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "$nested_name$_descriptor() {\n" 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return $classname$_descriptor();\n" 217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "}\n"); 218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville printer->Print(vars, 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "static inline const ::std::string& " 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$nested_name$_Name($nested_name$ value) {" 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "\n" 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer " return $classname$_Name(value);\n" 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "}\n"); 224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville printer->Print(vars, 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "static inline bool $nested_name$_Parse(const ::std::string& name,\n" 226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " $nested_name$* value) {\n" 227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return $classname$_Parse(name, value);\n" 228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n"); 229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateDescriptorInitializer( 233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::Printer* printer, int index) { 234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville map<string, string> vars; 235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["classname"] = classname_; 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["index"] = SimpleItoa(index); 237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (descriptor_->containing_type() == NULL) { 239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "$classname$_descriptor_ = file->enum_type($index$);\n"); 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["parent"] = ClassName(descriptor_->containing_type(), false); 243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n"); 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid EnumGenerator::GenerateMethods(io::Printer* printer) { 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville map<string, string> vars; 250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["classname"] = classname_; 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["constexpr"] = options_.proto_h ? "constexpr " : ""; 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (HasDescriptorMethods(descriptor_->file(), options_)) { 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " protobuf_AssignDescriptorsOnce();\n" 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return $classname$_descriptor_;\n" 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n"); 259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "bool $classname$_IsValid(int value) {\n" 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " switch(value) {\n"); 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Multiple values may have the same number. Make sure we only cover 266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // each number once by first constructing a set containing all valid 267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // numbers, then printing a case statement for each element. 268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville set<int> numbers; 270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int j = 0; j < descriptor_->value_count(); j++) { 271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const EnumValueDescriptor* value = descriptor_->value(j); 272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville numbers.insert(value->number()); 273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (set<int>::iterator iter = numbers.begin(); 276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville iter != numbers.end(); ++iter) { 277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print( 278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " case $number$:\n", 279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "number", Int32ToString(*iter)); 280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 283fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return true;\n" 284fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " default:\n" 285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " return false;\n" 286fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville " }\n" 287fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "}\n" 288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "\n"); 289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (descriptor_->containing_type() != NULL) { 291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We need to "define" the static constants which were declared in the 292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // header, to give the linker a place to put them. Or at least the C++ 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // standard says we have to. MSVC actually insists that we do _not_ define 294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // them again in the .cc file, prior to VC++ 2015. 295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); 296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["parent"] = ClassName(descriptor_->containing_type(), false); 298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vars["nested_name"] = descriptor_->name(); 299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < descriptor_->value_count(); i++) { 300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer vars["value"] = EnumValueName(descriptor_->value(i)); 301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "$constexpr$const $classname$ $parent$::$value$;\n"); 303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville printer->Print(vars, 305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "const $classname$ $parent$::$nested_name$_MIN;\n" 306a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "const $classname$ $parent$::$nested_name$_MAX;\n"); 307a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if (generate_array_size_) { 308a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson printer->Print(vars, 309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson "const int $parent$::$nested_name$_ARRAYSIZE;\n"); 310a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson } 311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer printer->Print("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n"); 313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace cpp 317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace compiler 318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace protobuf 319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace google 320