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() && !SupportsPresenceApi(descriptor_)) {
100 (*variables)["name_def_message"] =
101 (*variables)["name"] + "_ = " + (*variables)["default_value"];
102 } else {
103 (*variables)["name_def_message"] = (*variables)["name"] + "_";
104 }
105 if (SupportsPresenceApi(descriptor_)) {
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 (SupportsPresenceApi(descriptor_)) {
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
GenerateParsingCode(io::Printer * printer,bool use_parse_context)164 void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
165 // for some field types the value of "use_parse_context" doesn't matter,
166 // so we fallback to the default implementation.
167 GenerateParsingCode(printer);
168 }
169
GenerateSerializationCode(io::Printer * printer,bool use_write_context)170 void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
171 // for some field types the value of "use_write_context" doesn't matter,
172 // so we fallback to the default implementation.
173 GenerateSerializationCode(printer);
174 }
175
AddDeprecatedFlag(io::Printer * printer)176 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
177 if (descriptor_->options().deprecated()) {
178 printer->Print("[global::System.ObsoleteAttribute]\n");
179 } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
180 descriptor_->message_type()->options().deprecated()) {
181 printer->Print("[global::System.ObsoleteAttribute]\n");
182 }
183 }
184
AddPublicMemberAttributes(io::Printer * printer)185 void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
186 AddDeprecatedFlag(printer);
187 WriteGeneratedCodeAttributes(printer);
188 }
189
oneof_property_name()190 std::string FieldGeneratorBase::oneof_property_name() {
191 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
192 }
193
oneof_name()194 std::string FieldGeneratorBase::oneof_name() {
195 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
196 }
197
property_name()198 std::string FieldGeneratorBase::property_name() {
199 return GetPropertyName(descriptor_);
200 }
201
name()202 std::string FieldGeneratorBase::name() {
203 return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
204 }
205
type_name()206 std::string FieldGeneratorBase::type_name() {
207 return type_name(descriptor_);
208 }
209
type_name(const FieldDescriptor * descriptor)210 std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
211 switch (descriptor->type()) {
212 case FieldDescriptor::TYPE_ENUM:
213 return GetClassName(descriptor->enum_type());
214 case FieldDescriptor::TYPE_MESSAGE:
215 case FieldDescriptor::TYPE_GROUP:
216 if (IsWrapperType(descriptor)) {
217 const FieldDescriptor* wrapped_field =
218 descriptor->message_type()->field(0);
219 string wrapped_field_type_name = type_name(wrapped_field);
220 // String and ByteString go to the same type; other wrapped types
221 // go to the nullable equivalent.
222 if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
223 wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
224 return wrapped_field_type_name;
225 } else {
226 return wrapped_field_type_name + "?";
227 }
228 }
229 return GetClassName(descriptor->message_type());
230 case FieldDescriptor::TYPE_DOUBLE:
231 return "double";
232 case FieldDescriptor::TYPE_FLOAT:
233 return "float";
234 case FieldDescriptor::TYPE_INT64:
235 return "long";
236 case FieldDescriptor::TYPE_UINT64:
237 return "ulong";
238 case FieldDescriptor::TYPE_INT32:
239 return "int";
240 case FieldDescriptor::TYPE_FIXED64:
241 return "ulong";
242 case FieldDescriptor::TYPE_FIXED32:
243 return "uint";
244 case FieldDescriptor::TYPE_BOOL:
245 return "bool";
246 case FieldDescriptor::TYPE_STRING:
247 return "string";
248 case FieldDescriptor::TYPE_BYTES:
249 return "pb::ByteString";
250 case FieldDescriptor::TYPE_UINT32:
251 return "uint";
252 case FieldDescriptor::TYPE_SFIXED32:
253 return "int";
254 case FieldDescriptor::TYPE_SFIXED64:
255 return "long";
256 case FieldDescriptor::TYPE_SINT32:
257 return "int";
258 case FieldDescriptor::TYPE_SINT64:
259 return "long";
260 default:
261 GOOGLE_LOG(FATAL)<< "Unknown field type.";
262 return "";
263 }
264 }
265
has_default_value()266 bool FieldGeneratorBase::has_default_value() {
267 switch (descriptor_->type()) {
268 case FieldDescriptor::TYPE_ENUM:
269 case FieldDescriptor::TYPE_MESSAGE:
270 case FieldDescriptor::TYPE_GROUP:
271 return true;
272 case FieldDescriptor::TYPE_DOUBLE:
273 return descriptor_->default_value_double() != 0.0;
274 case FieldDescriptor::TYPE_FLOAT:
275 return descriptor_->default_value_float() != 0.0;
276 case FieldDescriptor::TYPE_INT64:
277 return descriptor_->default_value_int64() != 0L;
278 case FieldDescriptor::TYPE_UINT64:
279 return descriptor_->default_value_uint64() != 0L;
280 case FieldDescriptor::TYPE_INT32:
281 return descriptor_->default_value_int32() != 0;
282 case FieldDescriptor::TYPE_FIXED64:
283 return descriptor_->default_value_uint64() != 0L;
284 case FieldDescriptor::TYPE_FIXED32:
285 return descriptor_->default_value_uint32() != 0;
286 case FieldDescriptor::TYPE_BOOL:
287 return descriptor_->default_value_bool();
288 case FieldDescriptor::TYPE_STRING:
289 return true;
290 case FieldDescriptor::TYPE_BYTES:
291 return true;
292 case FieldDescriptor::TYPE_UINT32:
293 return descriptor_->default_value_uint32() != 0;
294 case FieldDescriptor::TYPE_SFIXED32:
295 return descriptor_->default_value_int32() != 0;
296 case FieldDescriptor::TYPE_SFIXED64:
297 return descriptor_->default_value_int64() != 0L;
298 case FieldDescriptor::TYPE_SINT32:
299 return descriptor_->default_value_int32() != 0;
300 case FieldDescriptor::TYPE_SINT64:
301 return descriptor_->default_value_int64() != 0L;
302 default:
303 GOOGLE_LOG(FATAL)<< "Unknown field type.";
304 return true;
305 }
306 }
307
AllPrintableAscii(const std::string & text)308 bool AllPrintableAscii(const std::string& text) {
309 for(int i = 0; i < text.size(); i++) {
310 if (text[i] < 0x20 || text[i] > 0x7e) {
311 return false;
312 }
313 }
314 return true;
315 }
316
GetStringDefaultValueInternal(const FieldDescriptor * descriptor)317 std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
318 if (descriptor->default_value_string().empty())
319 return "\"\"";
320 else
321 return "global::System.Text.Encoding.UTF8.GetString(global::System."
322 "Convert.FromBase64String(\"" +
323 StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")";
324 }
325
GetBytesDefaultValueInternal(const FieldDescriptor * descriptor)326 std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
327 if (descriptor->default_value_string().empty())
328 return "pb::ByteString.Empty";
329 else
330 return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
331 }
332
default_value()333 std::string FieldGeneratorBase::default_value() {
334 return default_value(descriptor_);
335 }
336
default_value(const FieldDescriptor * descriptor)337 std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
338 switch (descriptor->type()) {
339 case FieldDescriptor::TYPE_ENUM:
340 return GetClassName(descriptor->default_value_enum()->type()) + "." +
341 GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
342 case FieldDescriptor::TYPE_MESSAGE:
343 case FieldDescriptor::TYPE_GROUP:
344 if (IsWrapperType(descriptor)) {
345 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
346 return default_value(wrapped_field);
347 } else {
348 return "null";
349 }
350 case FieldDescriptor::TYPE_DOUBLE: {
351 double value = descriptor->default_value_double();
352 if (value == std::numeric_limits<double>::infinity()) {
353 return "double.PositiveInfinity";
354 } else if (value == -std::numeric_limits<double>::infinity()) {
355 return "double.NegativeInfinity";
356 } else if (std::isnan(value)) {
357 return "double.NaN";
358 }
359 return StrCat(value) + "D";
360 }
361 case FieldDescriptor::TYPE_FLOAT: {
362 float value = descriptor->default_value_float();
363 if (value == std::numeric_limits<float>::infinity()) {
364 return "float.PositiveInfinity";
365 } else if (value == -std::numeric_limits<float>::infinity()) {
366 return "float.NegativeInfinity";
367 } else if (std::isnan(value)) {
368 return "float.NaN";
369 }
370 return StrCat(value) + "F";
371 }
372 case FieldDescriptor::TYPE_INT64:
373 return StrCat(descriptor->default_value_int64()) + "L";
374 case FieldDescriptor::TYPE_UINT64:
375 return StrCat(descriptor->default_value_uint64()) + "UL";
376 case FieldDescriptor::TYPE_INT32:
377 return StrCat(descriptor->default_value_int32());
378 case FieldDescriptor::TYPE_FIXED64:
379 return StrCat(descriptor->default_value_uint64()) + "UL";
380 case FieldDescriptor::TYPE_FIXED32:
381 return StrCat(descriptor->default_value_uint32());
382 case FieldDescriptor::TYPE_BOOL:
383 if (descriptor->default_value_bool()) {
384 return "true";
385 } else {
386 return "false";
387 }
388 case FieldDescriptor::TYPE_STRING:
389 return GetStringDefaultValueInternal(descriptor);
390 case FieldDescriptor::TYPE_BYTES:
391 return GetBytesDefaultValueInternal(descriptor);
392 case FieldDescriptor::TYPE_UINT32:
393 return StrCat(descriptor->default_value_uint32());
394 case FieldDescriptor::TYPE_SFIXED32:
395 return StrCat(descriptor->default_value_int32());
396 case FieldDescriptor::TYPE_SFIXED64:
397 return StrCat(descriptor->default_value_int64()) + "L";
398 case FieldDescriptor::TYPE_SINT32:
399 return StrCat(descriptor->default_value_int32());
400 case FieldDescriptor::TYPE_SINT64:
401 return StrCat(descriptor->default_value_int64()) + "L";
402 default:
403 GOOGLE_LOG(FATAL)<< "Unknown field type.";
404 return "";
405 }
406 }
407
number()408 std::string FieldGeneratorBase::number() {
409 return StrCat(descriptor_->number());
410 }
411
capitalized_type_name()412 std::string FieldGeneratorBase::capitalized_type_name() {
413 switch (descriptor_->type()) {
414 case FieldDescriptor::TYPE_ENUM:
415 return "Enum";
416 case FieldDescriptor::TYPE_MESSAGE:
417 return "Message";
418 case FieldDescriptor::TYPE_GROUP:
419 return "Group";
420 case FieldDescriptor::TYPE_DOUBLE:
421 return "Double";
422 case FieldDescriptor::TYPE_FLOAT:
423 return "Float";
424 case FieldDescriptor::TYPE_INT64:
425 return "Int64";
426 case FieldDescriptor::TYPE_UINT64:
427 return "UInt64";
428 case FieldDescriptor::TYPE_INT32:
429 return "Int32";
430 case FieldDescriptor::TYPE_FIXED64:
431 return "Fixed64";
432 case FieldDescriptor::TYPE_FIXED32:
433 return "Fixed32";
434 case FieldDescriptor::TYPE_BOOL:
435 return "Bool";
436 case FieldDescriptor::TYPE_STRING:
437 return "String";
438 case FieldDescriptor::TYPE_BYTES:
439 return "Bytes";
440 case FieldDescriptor::TYPE_UINT32:
441 return "UInt32";
442 case FieldDescriptor::TYPE_SFIXED32:
443 return "SFixed32";
444 case FieldDescriptor::TYPE_SFIXED64:
445 return "SFixed64";
446 case FieldDescriptor::TYPE_SINT32:
447 return "SInt32";
448 case FieldDescriptor::TYPE_SINT64:
449 return "SInt64";
450 default:
451 GOOGLE_LOG(FATAL)<< "Unknown field type.";
452 return "";
453 }
454 }
455
456 } // namespace csharp
457 } // namespace compiler
458 } // namespace protobuf
459 } // namespace google
460