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