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
48namespace google {
49namespace protobuf {
50namespace compiler {
51namespace csharp {
52
53void FieldGeneratorBase::SetCommonFieldVariables(
54 std::map<std::string, std::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(field_number: descriptor_->number(), type: 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(field: descriptor_);
64 uint8_t tag_array[5];
65 io::CodedOutputStream::WriteTagToArray(value: tag, target: tag_array);
66 std::string tag_bytes = StrCat(a: tag_array[0]);
67 for (int i = 1; i < part_tag_size; i++) {
68 tag_bytes += ", " + StrCat(a: tag_array[i]);
69 }
70
71 (*variables)["tag"] = StrCat(a: tag);
72 (*variables)["tag_size"] = StrCat(a: tag_size);
73 (*variables)["tag_bytes"] = tag_bytes;
74
75 if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
76 tag = internal::WireFormatLite::MakeTag(
77 field_number: descriptor_->number(),
78 type: internal::WireFormatLite::WIRETYPE_END_GROUP);
79 io::CodedOutputStream::WriteTagToArray(value: tag, target: tag_array);
80 tag_bytes = StrCat(a: tag_array[0]);
81 for (int i = 1; i < part_tag_size; i++) {
82 tag_bytes += ", " + StrCat(a: tag_array[i]);
83 }
84
85 variables_["end_tag"] = StrCat(a: 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: 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: 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: 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 std::string hasBitsNumber = StrCat(a: presenceIndex_ / 32);
112 std::string hasBitsMask = StrCat(a: 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
125void FieldGeneratorBase::SetCommonOneofFieldVariables(
126 std::map<std::string, std::string>* variables) {
127 (*variables)["oneof_name"] = oneof_name();
128 if (SupportsPresenceApi(descriptor: 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." + oneof_case_name();
134 }
135 (*variables)["oneof_case_name"] = oneof_case_name();
136 (*variables)["oneof_property_name"] = oneof_property_name();
137}
138
139FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
140 int presenceIndex, const Options* options)
141 : SourceGeneratorBase(options),
142 descriptor_(descriptor),
143 presenceIndex_(presenceIndex) {
144 SetCommonFieldVariables(&variables_);
145}
146
147FieldGeneratorBase::~FieldGeneratorBase() {
148}
149
150void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
151 // No-op: only message fields and repeated fields need
152 // special handling for freezing, so default to not generating any code.
153}
154
155void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
156 // No-op: expect this to be overridden by appropriate types.
157 // Could fail if we get called here though...
158}
159
160void FieldGeneratorBase::GenerateExtensionCode(io::Printer* printer) {
161 // No-op: only message fields, enum fields, primitives,
162 // and repeated fields need this default is to not generate any code
163}
164
165void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
166 // for some field types the value of "use_parse_context" doesn't matter,
167 // so we fallback to the default implementation.
168 GenerateParsingCode(printer);
169}
170
171void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
172 // for some field types the value of "use_write_context" doesn't matter,
173 // so we fallback to the default implementation.
174 GenerateSerializationCode(printer);
175}
176
177void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
178 if (descriptor_->options().deprecated()) {
179 printer->Print(text: "[global::System.ObsoleteAttribute]\n");
180 } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE &&
181 descriptor_->message_type()->options().deprecated()) {
182 printer->Print(text: "[global::System.ObsoleteAttribute]\n");
183 }
184}
185
186void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) {
187 AddDeprecatedFlag(printer);
188 WriteGeneratedCodeAttributes(printer);
189}
190
191std::string FieldGeneratorBase::oneof_case_name() {
192 return GetOneofCaseName(descriptor: descriptor_);
193}
194
195std::string FieldGeneratorBase::oneof_property_name() {
196 return UnderscoresToCamelCase(input: descriptor_->containing_oneof()->name(), cap_next_letter: true);
197}
198
199std::string FieldGeneratorBase::oneof_name() {
200 return UnderscoresToCamelCase(input: descriptor_->containing_oneof()->name(), cap_next_letter: false);
201}
202
203std::string FieldGeneratorBase::property_name() {
204 return GetPropertyName(descriptor: descriptor_);
205}
206
207std::string FieldGeneratorBase::name() {
208 return UnderscoresToCamelCase(input: GetFieldName(descriptor: descriptor_), cap_next_letter: false);
209}
210
211std::string FieldGeneratorBase::type_name() {
212 return type_name(descriptor: descriptor_);
213}
214
215std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
216 switch (descriptor->type()) {
217 case FieldDescriptor::TYPE_ENUM:
218 return GetClassName(descriptor: descriptor->enum_type());
219 case FieldDescriptor::TYPE_MESSAGE:
220 case FieldDescriptor::TYPE_GROUP:
221 if (IsWrapperType(descriptor)) {
222 const FieldDescriptor* wrapped_field =
223 descriptor->message_type()->field(index: 0);
224 std::string wrapped_field_type_name = type_name(descriptor: wrapped_field);
225 // String and ByteString go to the same type; other wrapped types
226 // go to the nullable equivalent.
227 if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
228 wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
229 return wrapped_field_type_name;
230 } else {
231 return wrapped_field_type_name + "?";
232 }
233 }
234 return GetClassName(descriptor: descriptor->message_type());
235 case FieldDescriptor::TYPE_DOUBLE:
236 return "double";
237 case FieldDescriptor::TYPE_FLOAT:
238 return "float";
239 case FieldDescriptor::TYPE_INT64:
240 return "long";
241 case FieldDescriptor::TYPE_UINT64:
242 return "ulong";
243 case FieldDescriptor::TYPE_INT32:
244 return "int";
245 case FieldDescriptor::TYPE_FIXED64:
246 return "ulong";
247 case FieldDescriptor::TYPE_FIXED32:
248 return "uint";
249 case FieldDescriptor::TYPE_BOOL:
250 return "bool";
251 case FieldDescriptor::TYPE_STRING:
252 return "string";
253 case FieldDescriptor::TYPE_BYTES:
254 return "pb::ByteString";
255 case FieldDescriptor::TYPE_UINT32:
256 return "uint";
257 case FieldDescriptor::TYPE_SFIXED32:
258 return "int";
259 case FieldDescriptor::TYPE_SFIXED64:
260 return "long";
261 case FieldDescriptor::TYPE_SINT32:
262 return "int";
263 case FieldDescriptor::TYPE_SINT64:
264 return "long";
265 default:
266 GOOGLE_LOG(FATAL)<< "Unknown field type.";
267 return "";
268 }
269}
270
271bool FieldGeneratorBase::has_default_value() {
272 switch (descriptor_->type()) {
273 case FieldDescriptor::TYPE_ENUM:
274 case FieldDescriptor::TYPE_MESSAGE:
275 case FieldDescriptor::TYPE_GROUP:
276 return true;
277 case FieldDescriptor::TYPE_DOUBLE:
278 return descriptor_->default_value_double() != 0.0;
279 case FieldDescriptor::TYPE_FLOAT:
280 return descriptor_->default_value_float() != 0.0;
281 case FieldDescriptor::TYPE_INT64:
282 return descriptor_->default_value_int64() != 0L;
283 case FieldDescriptor::TYPE_UINT64:
284 return descriptor_->default_value_uint64() != 0L;
285 case FieldDescriptor::TYPE_INT32:
286 return descriptor_->default_value_int32() != 0;
287 case FieldDescriptor::TYPE_FIXED64:
288 return descriptor_->default_value_uint64() != 0L;
289 case FieldDescriptor::TYPE_FIXED32:
290 return descriptor_->default_value_uint32() != 0;
291 case FieldDescriptor::TYPE_BOOL:
292 return descriptor_->default_value_bool();
293 case FieldDescriptor::TYPE_STRING:
294 return true;
295 case FieldDescriptor::TYPE_BYTES:
296 return true;
297 case FieldDescriptor::TYPE_UINT32:
298 return descriptor_->default_value_uint32() != 0;
299 case FieldDescriptor::TYPE_SFIXED32:
300 return descriptor_->default_value_int32() != 0;
301 case FieldDescriptor::TYPE_SFIXED64:
302 return descriptor_->default_value_int64() != 0L;
303 case FieldDescriptor::TYPE_SINT32:
304 return descriptor_->default_value_int32() != 0;
305 case FieldDescriptor::TYPE_SINT64:
306 return descriptor_->default_value_int64() != 0L;
307 default:
308 GOOGLE_LOG(FATAL)<< "Unknown field type.";
309 return true;
310 }
311}
312
313bool AllPrintableAscii(const std::string& text) {
314 for(int i = 0; i < text.size(); i++) {
315 if (text[i] < 0x20 || text[i] > 0x7e) {
316 return false;
317 }
318 }
319 return true;
320}
321
322std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
323 if (descriptor->default_value_string().empty())
324 return "\"\"";
325 else
326 return "global::System.Text.Encoding.UTF8.GetString(global::System."
327 "Convert.FromBase64String(\"" +
328 StringToBase64(input: descriptor->default_value_string()) + "\"), 0, " + StrCat(a: descriptor->default_value_string().length()) + ")";
329}
330
331std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
332 if (descriptor->default_value_string().empty())
333 return "pb::ByteString.Empty";
334 else
335 return "pb::ByteString.FromBase64(\"" + StringToBase64(input: descriptor->default_value_string()) + "\")";
336}
337
338std::string FieldGeneratorBase::default_value() {
339 return default_value(descriptor: descriptor_);
340}
341
342std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
343 switch (descriptor->type()) {
344 case FieldDescriptor::TYPE_ENUM:
345 return GetClassName(descriptor: descriptor->default_value_enum()->type()) + "." +
346 GetEnumValueName(enum_name: descriptor->default_value_enum()->type()->name(), enum_value_name: descriptor->default_value_enum()->name());
347 case FieldDescriptor::TYPE_MESSAGE:
348 case FieldDescriptor::TYPE_GROUP:
349 if (IsWrapperType(descriptor)) {
350 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(index: 0);
351 return default_value(descriptor: wrapped_field);
352 } else {
353 return "null";
354 }
355 case FieldDescriptor::TYPE_DOUBLE: {
356 double value = descriptor->default_value_double();
357 if (value == std::numeric_limits<double>::infinity()) {
358 return "double.PositiveInfinity";
359 } else if (value == -std::numeric_limits<double>::infinity()) {
360 return "double.NegativeInfinity";
361 } else if (std::isnan(x: value)) {
362 return "double.NaN";
363 }
364 return StrCat(a: value) + "D";
365 }
366 case FieldDescriptor::TYPE_FLOAT: {
367 float value = descriptor->default_value_float();
368 if (value == std::numeric_limits<float>::infinity()) {
369 return "float.PositiveInfinity";
370 } else if (value == -std::numeric_limits<float>::infinity()) {
371 return "float.NegativeInfinity";
372 } else if (std::isnan(x: value)) {
373 return "float.NaN";
374 }
375 return StrCat(a: value) + "F";
376 }
377 case FieldDescriptor::TYPE_INT64:
378 return StrCat(a: descriptor->default_value_int64()) + "L";
379 case FieldDescriptor::TYPE_UINT64:
380 return StrCat(a: descriptor->default_value_uint64()) + "UL";
381 case FieldDescriptor::TYPE_INT32:
382 return StrCat(a: descriptor->default_value_int32());
383 case FieldDescriptor::TYPE_FIXED64:
384 return StrCat(a: descriptor->default_value_uint64()) + "UL";
385 case FieldDescriptor::TYPE_FIXED32:
386 return StrCat(a: descriptor->default_value_uint32());
387 case FieldDescriptor::TYPE_BOOL:
388 if (descriptor->default_value_bool()) {
389 return "true";
390 } else {
391 return "false";
392 }
393 case FieldDescriptor::TYPE_STRING:
394 return GetStringDefaultValueInternal(descriptor);
395 case FieldDescriptor::TYPE_BYTES:
396 return GetBytesDefaultValueInternal(descriptor);
397 case FieldDescriptor::TYPE_UINT32:
398 return StrCat(a: descriptor->default_value_uint32());
399 case FieldDescriptor::TYPE_SFIXED32:
400 return StrCat(a: descriptor->default_value_int32());
401 case FieldDescriptor::TYPE_SFIXED64:
402 return StrCat(a: descriptor->default_value_int64()) + "L";
403 case FieldDescriptor::TYPE_SINT32:
404 return StrCat(a: descriptor->default_value_int32());
405 case FieldDescriptor::TYPE_SINT64:
406 return StrCat(a: descriptor->default_value_int64()) + "L";
407 default:
408 GOOGLE_LOG(FATAL)<< "Unknown field type.";
409 return "";
410 }
411}
412
413std::string FieldGeneratorBase::number() {
414 return StrCat(a: descriptor_->number());
415}
416
417std::string FieldGeneratorBase::capitalized_type_name() {
418 switch (descriptor_->type()) {
419 case FieldDescriptor::TYPE_ENUM:
420 return "Enum";
421 case FieldDescriptor::TYPE_MESSAGE:
422 return "Message";
423 case FieldDescriptor::TYPE_GROUP:
424 return "Group";
425 case FieldDescriptor::TYPE_DOUBLE:
426 return "Double";
427 case FieldDescriptor::TYPE_FLOAT:
428 return "Float";
429 case FieldDescriptor::TYPE_INT64:
430 return "Int64";
431 case FieldDescriptor::TYPE_UINT64:
432 return "UInt64";
433 case FieldDescriptor::TYPE_INT32:
434 return "Int32";
435 case FieldDescriptor::TYPE_FIXED64:
436 return "Fixed64";
437 case FieldDescriptor::TYPE_FIXED32:
438 return "Fixed32";
439 case FieldDescriptor::TYPE_BOOL:
440 return "Bool";
441 case FieldDescriptor::TYPE_STRING:
442 return "String";
443 case FieldDescriptor::TYPE_BYTES:
444 return "Bytes";
445 case FieldDescriptor::TYPE_UINT32:
446 return "UInt32";
447 case FieldDescriptor::TYPE_SFIXED32:
448 return "SFixed32";
449 case FieldDescriptor::TYPE_SFIXED64:
450 return "SFixed64";
451 case FieldDescriptor::TYPE_SINT32:
452 return "SInt32";
453 case FieldDescriptor::TYPE_SINT64:
454 return "SInt64";
455 default:
456 GOOGLE_LOG(FATAL)<< "Unknown field type.";
457 return "";
458 }
459}
460
461} // namespace csharp
462} // namespace compiler
463} // namespace protobuf
464} // namespace google
465