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