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