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 <limits>
32 #include <sstream>
33
34 #include <google/protobuf/compiler/code_generator.h>
35 #include <google/protobuf/compiler/plugin.h>
36 #include <google/protobuf/descriptor.h>
37 #include <google/protobuf/descriptor.pb.h>
38 #include <google/protobuf/io/coded_stream.h>
39 #include <google/protobuf/io/printer.h>
40 #include <google/protobuf/io/zero_copy_stream.h>
41 #include <google/protobuf/stubs/mathlimits.h>
42 #include <google/protobuf/stubs/strutil.h>
43 #include <google/protobuf/wire_format.h>
44
45 #include <google/protobuf/compiler/csharp/csharp_field_base.h>
46 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
47 #include <google/protobuf/compiler/csharp/csharp_names.h>
48
49 using google::protobuf::internal::scoped_ptr;
50
51 namespace google {
52 namespace protobuf {
53 namespace compiler {
54 namespace csharp {
55
SetCommonFieldVariables(map<string,string> * variables)56 void FieldGeneratorBase::SetCommonFieldVariables(
57 map<string, string>* variables) {
58 // Note: this will be valid even though the tag emitted for packed and unpacked versions of
59 // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
60 // never effects the tag size.
61 int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
62 uint tag = internal::WireFormat::MakeTag(descriptor_);
63 uint8 tag_array[5];
64 io::CodedOutputStream::WriteTagToArray(tag, tag_array);
65 string tag_bytes = SimpleItoa(tag_array[0]);
66 for (int i = 1; i < tag_size; i++) {
67 tag_bytes += ", " + SimpleItoa(tag_array[i]);
68 }
69
70 (*variables)["access_level"] = "public";
71 (*variables)["tag"] = SimpleItoa(tag);
72 (*variables)["tag_size"] = SimpleItoa(tag_size);
73 (*variables)["tag_bytes"] = tag_bytes;
74
75 (*variables)["property_name"] = property_name();
76 (*variables)["type_name"] = type_name();
77 (*variables)["name"] = name();
78 (*variables)["descriptor_name"] = descriptor_->name();
79 (*variables)["default_value"] = default_value();
80 if (has_default_value()) {
81 (*variables)["name_def_message"] =
82 (*variables)["name"] + "_ = " + (*variables)["default_value"];
83 } else {
84 (*variables)["name_def_message"] = (*variables)["name"] + "_";
85 }
86 (*variables)["capitalized_type_name"] = capitalized_type_name();
87 (*variables)["number"] = number();
88 (*variables)["has_property_check"] =
89 (*variables)["property_name"] + " != " + (*variables)["default_value"];
90 (*variables)["other_has_property_check"] = "other." +
91 (*variables)["property_name"] + " != " + (*variables)["default_value"];
92 }
93
SetCommonOneofFieldVariables(map<string,string> * variables)94 void FieldGeneratorBase::SetCommonOneofFieldVariables(
95 map<string, string>* variables) {
96 (*variables)["oneof_name"] = oneof_name();
97 (*variables)["has_property_check"] =
98 oneof_name() + "Case_ == " + oneof_property_name() +
99 "OneofCase." + property_name();
100 (*variables)["oneof_property_name"] = oneof_property_name();
101 }
102
FieldGeneratorBase(const FieldDescriptor * descriptor,int fieldOrdinal,const Options * options)103 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
104 int fieldOrdinal, const Options* options)
105 : SourceGeneratorBase(descriptor->file(), options),
106 descriptor_(descriptor),
107 fieldOrdinal_(fieldOrdinal) {
108 SetCommonFieldVariables(&variables_);
109 }
110
~FieldGeneratorBase()111 FieldGeneratorBase::~FieldGeneratorBase() {
112 }
113
GenerateFreezingCode(io::Printer * printer)114 void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
115 // No-op: only message fields and repeated fields need
116 // special handling for freezing, so default to not generating any code.
117 }
118
GenerateCodecCode(io::Printer * printer)119 void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
120 // No-op: expect this to be overridden by appropriate types.
121 // Could fail if we get called here though...
122 }
123
AddDeprecatedFlag(io::Printer * printer)124 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
125 if (descriptor_->options().deprecated())
126 {
127 printer->Print("[global::System.ObsoleteAttribute]\n");
128 }
129 }
130
AddPublicMemberAttributes(io::Printer * printer)131 void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
132 AddDeprecatedFlag(printer);
133 WriteGeneratedCodeAttributes(printer);
134 }
135
oneof_property_name()136 std::string FieldGeneratorBase::oneof_property_name() {
137 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
138 }
139
oneof_name()140 std::string FieldGeneratorBase::oneof_name() {
141 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
142 }
143
property_name()144 std::string FieldGeneratorBase::property_name() {
145 return GetPropertyName(descriptor_);
146 }
147
name()148 std::string FieldGeneratorBase::name() {
149 return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
150 }
151
type_name()152 std::string FieldGeneratorBase::type_name() {
153 return type_name(descriptor_);
154 }
155
type_name(const FieldDescriptor * descriptor)156 std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
157 switch (descriptor->type()) {
158 case FieldDescriptor::TYPE_ENUM:
159 return GetClassName(descriptor->enum_type());
160 case FieldDescriptor::TYPE_MESSAGE:
161 case FieldDescriptor::TYPE_GROUP:
162 if (IsWrapperType(descriptor)) {
163 const FieldDescriptor* wrapped_field =
164 descriptor->message_type()->field(0);
165 string wrapped_field_type_name = type_name(wrapped_field);
166 // String and ByteString go to the same type; other wrapped types
167 // go to the nullable equivalent.
168 if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
169 wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
170 return wrapped_field_type_name;
171 } else {
172 return wrapped_field_type_name + "?";
173 }
174 }
175 return GetClassName(descriptor->message_type());
176 case FieldDescriptor::TYPE_DOUBLE:
177 return "double";
178 case FieldDescriptor::TYPE_FLOAT:
179 return "float";
180 case FieldDescriptor::TYPE_INT64:
181 return "long";
182 case FieldDescriptor::TYPE_UINT64:
183 return "ulong";
184 case FieldDescriptor::TYPE_INT32:
185 return "int";
186 case FieldDescriptor::TYPE_FIXED64:
187 return "ulong";
188 case FieldDescriptor::TYPE_FIXED32:
189 return "uint";
190 case FieldDescriptor::TYPE_BOOL:
191 return "bool";
192 case FieldDescriptor::TYPE_STRING:
193 return "string";
194 case FieldDescriptor::TYPE_BYTES:
195 return "pb::ByteString";
196 case FieldDescriptor::TYPE_UINT32:
197 return "uint";
198 case FieldDescriptor::TYPE_SFIXED32:
199 return "int";
200 case FieldDescriptor::TYPE_SFIXED64:
201 return "long";
202 case FieldDescriptor::TYPE_SINT32:
203 return "int";
204 case FieldDescriptor::TYPE_SINT64:
205 return "long";
206 default:
207 GOOGLE_LOG(FATAL)<< "Unknown field type.";
208 return "";
209 }
210 }
211
has_default_value()212 bool FieldGeneratorBase::has_default_value() {
213 switch (descriptor_->type()) {
214 case FieldDescriptor::TYPE_ENUM:
215 case FieldDescriptor::TYPE_MESSAGE:
216 case FieldDescriptor::TYPE_GROUP:
217 return true;
218 case FieldDescriptor::TYPE_DOUBLE:
219 return descriptor_->default_value_double() != 0.0;
220 case FieldDescriptor::TYPE_FLOAT:
221 return descriptor_->default_value_float() != 0.0;
222 case FieldDescriptor::TYPE_INT64:
223 return descriptor_->default_value_int64() != 0L;
224 case FieldDescriptor::TYPE_UINT64:
225 return descriptor_->default_value_uint64() != 0L;
226 case FieldDescriptor::TYPE_INT32:
227 return descriptor_->default_value_int32() != 0;
228 case FieldDescriptor::TYPE_FIXED64:
229 return descriptor_->default_value_uint64() != 0L;
230 case FieldDescriptor::TYPE_FIXED32:
231 return descriptor_->default_value_uint32() != 0;
232 case FieldDescriptor::TYPE_BOOL:
233 return descriptor_->default_value_bool();
234 case FieldDescriptor::TYPE_STRING:
235 return true;
236 case FieldDescriptor::TYPE_BYTES:
237 return true;
238 case FieldDescriptor::TYPE_UINT32:
239 return descriptor_->default_value_uint32() != 0;
240 case FieldDescriptor::TYPE_SFIXED32:
241 return descriptor_->default_value_int32() != 0;
242 case FieldDescriptor::TYPE_SFIXED64:
243 return descriptor_->default_value_int64() != 0L;
244 case FieldDescriptor::TYPE_SINT32:
245 return descriptor_->default_value_int32() != 0;
246 case FieldDescriptor::TYPE_SINT64:
247 return descriptor_->default_value_int64() != 0L;
248 default:
249 GOOGLE_LOG(FATAL)<< "Unknown field type.";
250 return true;
251 }
252 }
253
is_nullable_type()254 bool FieldGeneratorBase::is_nullable_type() {
255 switch (descriptor_->type()) {
256 case FieldDescriptor::TYPE_ENUM:
257 case FieldDescriptor::TYPE_DOUBLE:
258 case FieldDescriptor::TYPE_FLOAT:
259 case FieldDescriptor::TYPE_INT64:
260 case FieldDescriptor::TYPE_UINT64:
261 case FieldDescriptor::TYPE_INT32:
262 case FieldDescriptor::TYPE_FIXED64:
263 case FieldDescriptor::TYPE_FIXED32:
264 case FieldDescriptor::TYPE_BOOL:
265 case FieldDescriptor::TYPE_UINT32:
266 case FieldDescriptor::TYPE_SFIXED32:
267 case FieldDescriptor::TYPE_SFIXED64:
268 case FieldDescriptor::TYPE_SINT32:
269 case FieldDescriptor::TYPE_SINT64:
270 return false;
271
272 case FieldDescriptor::TYPE_MESSAGE:
273 case FieldDescriptor::TYPE_GROUP:
274 case FieldDescriptor::TYPE_STRING:
275 case FieldDescriptor::TYPE_BYTES:
276 return true;
277
278 default:
279 GOOGLE_LOG(FATAL)<< "Unknown field type.";
280 return true;
281 }
282 }
283
AllPrintableAscii(const std::string & text)284 bool AllPrintableAscii(const std::string& text) {
285 for(int i = 0; i < text.size(); i++) {
286 if (text[i] < 0x20 || text[i] > 0x7e) {
287 return false;
288 }
289 }
290 return true;
291 }
292
GetStringDefaultValueInternal()293 std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
294 // No other default values needed for proto3...
295 return "\"\"";
296 }
297
GetBytesDefaultValueInternal()298 std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
299 // No other default values needed for proto3...
300 return "pb::ByteString.Empty";
301 }
302
default_value()303 std::string FieldGeneratorBase::default_value() {
304 return default_value(descriptor_);
305 }
306
default_value(const FieldDescriptor * descriptor)307 std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
308 switch (descriptor->type()) {
309 case FieldDescriptor::TYPE_ENUM:
310 // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
311 // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
312 return "0";
313 case FieldDescriptor::TYPE_MESSAGE:
314 case FieldDescriptor::TYPE_GROUP:
315 if (IsWrapperType(descriptor)) {
316 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
317 return default_value(wrapped_field);
318 } else {
319 return "null";
320 }
321 case FieldDescriptor::TYPE_DOUBLE: {
322 double value = descriptor->default_value_double();
323 if (value == numeric_limits<double>::infinity()) {
324 return "double.PositiveInfinity";
325 } else if (value == -numeric_limits<double>::infinity()) {
326 return "double.NegativeInfinity";
327 } else if (MathLimits<double>::IsNaN(value)) {
328 return "double.NaN";
329 }
330 return SimpleDtoa(value) + "D";
331 }
332 case FieldDescriptor::TYPE_FLOAT: {
333 float value = descriptor->default_value_float();
334 if (value == numeric_limits<float>::infinity()) {
335 return "float.PositiveInfinity";
336 } else if (value == -numeric_limits<float>::infinity()) {
337 return "float.NegativeInfinity";
338 } else if (MathLimits<float>::IsNaN(value)) {
339 return "float.NaN";
340 }
341 return SimpleFtoa(value) + "F";
342 }
343 case FieldDescriptor::TYPE_INT64:
344 return SimpleItoa(descriptor->default_value_int64()) + "L";
345 case FieldDescriptor::TYPE_UINT64:
346 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
347 case FieldDescriptor::TYPE_INT32:
348 return SimpleItoa(descriptor->default_value_int32());
349 case FieldDescriptor::TYPE_FIXED64:
350 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
351 case FieldDescriptor::TYPE_FIXED32:
352 return SimpleItoa(descriptor->default_value_uint32());
353 case FieldDescriptor::TYPE_BOOL:
354 if (descriptor->default_value_bool()) {
355 return "true";
356 } else {
357 return "false";
358 }
359 case FieldDescriptor::TYPE_STRING:
360 return GetStringDefaultValueInternal();
361 case FieldDescriptor::TYPE_BYTES:
362 return GetBytesDefaultValueInternal();
363 case FieldDescriptor::TYPE_UINT32:
364 return SimpleItoa(descriptor->default_value_uint32());
365 case FieldDescriptor::TYPE_SFIXED32:
366 return SimpleItoa(descriptor->default_value_int32());
367 case FieldDescriptor::TYPE_SFIXED64:
368 return SimpleItoa(descriptor->default_value_int64()) + "L";
369 case FieldDescriptor::TYPE_SINT32:
370 return SimpleItoa(descriptor->default_value_int32());
371 case FieldDescriptor::TYPE_SINT64:
372 return SimpleItoa(descriptor->default_value_int64()) + "L";
373 default:
374 GOOGLE_LOG(FATAL)<< "Unknown field type.";
375 return "";
376 }
377 }
378
number()379 std::string FieldGeneratorBase::number() {
380 return SimpleItoa(descriptor_->number());
381 }
382
capitalized_type_name()383 std::string FieldGeneratorBase::capitalized_type_name() {
384 switch (descriptor_->type()) {
385 case FieldDescriptor::TYPE_ENUM:
386 return "Enum";
387 case FieldDescriptor::TYPE_MESSAGE:
388 return "Message";
389 case FieldDescriptor::TYPE_GROUP:
390 return "Group";
391 case FieldDescriptor::TYPE_DOUBLE:
392 return "Double";
393 case FieldDescriptor::TYPE_FLOAT:
394 return "Float";
395 case FieldDescriptor::TYPE_INT64:
396 return "Int64";
397 case FieldDescriptor::TYPE_UINT64:
398 return "UInt64";
399 case FieldDescriptor::TYPE_INT32:
400 return "Int32";
401 case FieldDescriptor::TYPE_FIXED64:
402 return "Fixed64";
403 case FieldDescriptor::TYPE_FIXED32:
404 return "Fixed32";
405 case FieldDescriptor::TYPE_BOOL:
406 return "Bool";
407 case FieldDescriptor::TYPE_STRING:
408 return "String";
409 case FieldDescriptor::TYPE_BYTES:
410 return "Bytes";
411 case FieldDescriptor::TYPE_UINT32:
412 return "UInt32";
413 case FieldDescriptor::TYPE_SFIXED32:
414 return "SFixed32";
415 case FieldDescriptor::TYPE_SFIXED64:
416 return "SFixed64";
417 case FieldDescriptor::TYPE_SINT32:
418 return "SInt32";
419 case FieldDescriptor::TYPE_SINT64:
420 return "SInt64";
421 default:
422 GOOGLE_LOG(FATAL)<< "Unknown field type.";
423 return "";
424 }
425 }
426
427 } // namespace csharp
428 } // namespace compiler
429 } // namespace protobuf
430 } // namespace google
431