Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
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 : #include <map>
32 : #include <string>
33 :
34 : #include <google/protobuf/compiler/objectivec/objectivec_enum.h>
35 : #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
36 : #include <google/protobuf/io/printer.h>
37 : #include <google/protobuf/stubs/strutil.h>
38 :
39 : namespace google {
40 : namespace protobuf {
41 : namespace compiler {
42 : namespace objectivec {
43 :
44 0 : EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
45 : : descriptor_(descriptor),
46 0 : name_(EnumName(descriptor_)) {
47 0 : for (int i = 0; i < descriptor_->value_count(); i++) {
48 0 : const EnumValueDescriptor* value = descriptor_->value(i);
49 : const EnumValueDescriptor* canonical_value =
50 0 : descriptor_->FindValueByNumber(value->number());
51 :
52 0 : if (value == canonical_value) {
53 0 : base_values_.push_back(value);
54 : }
55 0 : all_values_.push_back(value);
56 : }
57 0 : }
58 :
59 0 : EnumGenerator::~EnumGenerator() {}
60 :
61 0 : void EnumGenerator::GenerateHeader(io::Printer* printer) {
62 : string enum_comments;
63 0 : SourceLocation location;
64 0 : if (descriptor_->GetSourceLocation(&location)) {
65 0 : enum_comments = BuildCommentsString(location);
66 : } else {
67 : enum_comments = "";
68 : }
69 :
70 : printer->Print(
71 : "#pragma mark - Enum $name$\n"
72 : "\n",
73 0 : "name", name_);
74 :
75 : printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
76 : "comments", enum_comments,
77 0 : "name", name_);
78 0 : printer->Indent();
79 :
80 0 : if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
81 : // Include the unknown value.
82 : printer->Print(
83 : "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
84 0 : "name", name_);
85 : }
86 :
87 0 : for (int i = 0; i < all_values_.size(); i++) {
88 : SourceLocation location;
89 0 : if (all_values_[i]->GetSourceLocation(&location)) {
90 0 : string comments = BuildCommentsString(location).c_str();
91 0 : if (comments.length() > 0) {
92 0 : if (i > 0) {
93 0 : printer->Print("\n");
94 : }
95 0 : printer->Print(comments.c_str());
96 : }
97 : }
98 :
99 : printer->Print(
100 : "$name$ = $value$,\n",
101 0 : "name", EnumValueName(all_values_[i]),
102 0 : "value", SimpleItoa(all_values_[i]->number()));
103 0 : }
104 0 : printer->Outdent();
105 : printer->Print(
106 : "};\n"
107 : "\n"
108 : "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
109 : "\n"
110 : "BOOL $name$_IsValidValue(int32_t value);\n"
111 : "\n",
112 0 : "name", name_);
113 0 : }
114 :
115 0 : void EnumGenerator::GenerateSource(io::Printer* printer) {
116 : printer->Print(
117 : "#pragma mark - Enum $name$\n"
118 : "\n",
119 0 : "name", name_);
120 :
121 : printer->Print(
122 : "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
123 : " static GPBEnumDescriptor *descriptor = NULL;\n"
124 : " if (!descriptor) {\n"
125 : " static GPBMessageEnumValueDescription values[] = {\n",
126 0 : "name", name_);
127 0 : printer->Indent();
128 0 : printer->Indent();
129 0 : printer->Indent();
130 :
131 : // Note: For the TextFormat decode info, we can't use the enum value as
132 : // the key because protocol buffer enums have 'allow_alias', which lets
133 : // a value be used more than once. Instead, the index into the list of
134 : // enum value descriptions is used. Note: start with -1 so the first one
135 : // will be zero.
136 : TextFormatDecodeData text_format_decode_data;
137 0 : int enum_value_description_key = -1;
138 :
139 0 : for (int i = 0; i < all_values_.size(); i++) {
140 0 : ++enum_value_description_key;
141 0 : string short_name(EnumValueShortName(all_values_[i]));
142 : printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
143 : "short_name", short_name,
144 0 : "name", EnumValueName(all_values_[i]));
145 0 : if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
146 : text_format_decode_data.AddString(enum_value_description_key, short_name,
147 0 : all_values_[i]->name());
148 : }
149 : }
150 0 : printer->Outdent();
151 0 : printer->Outdent();
152 0 : printer->Outdent();
153 0 : printer->Print(" };\n");
154 0 : if (text_format_decode_data.num_entries() == 0) {
155 : printer->Print(
156 : " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
157 : " values:values\n"
158 : " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
159 : " enumVerifier:$name$_IsValidValue];\n",
160 0 : "name", name_);
161 : } else {
162 : printer->Print(
163 : " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
164 : " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
165 : " values:values\n"
166 : " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
167 : " enumVerifier:$name$_IsValidValue\n"
168 : " extraTextFormatInfo:extraTextFormatInfo];\n",
169 : "name", name_,
170 0 : "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
171 : }
172 : printer->Print(
173 : " }\n"
174 : " return descriptor;\n"
175 0 : "}\n\n");
176 :
177 : printer->Print(
178 : "BOOL $name$_IsValidValue(int32_t value__) {\n"
179 : " switch (value__) {\n",
180 0 : "name", name_);
181 :
182 0 : for (int i = 0; i < base_values_.size(); i++) {
183 : printer->Print(
184 : " case $name$:\n",
185 0 : "name", EnumValueName(base_values_[i]));
186 : }
187 :
188 : printer->Print(
189 : " return YES;\n"
190 : " default:\n"
191 : " return NO;\n"
192 : " }\n"
193 0 : "}\n\n");
194 0 : }
195 : } // namespace objectivec
196 : } // namespace compiler
197 : } // namespace protobuf
198 : } // namespace google
|