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 }
134
oneof_property_name()135 std::string FieldGeneratorBase::oneof_property_name() {
136 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true);
137 }
138
oneof_name()139 std::string FieldGeneratorBase::oneof_name() {
140 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false);
141 }
142
property_name()143 std::string FieldGeneratorBase::property_name() {
144 return GetPropertyName(descriptor_);
145 }
146
name()147 std::string FieldGeneratorBase::name() {
148 return UnderscoresToCamelCase(GetFieldName(descriptor_), false);
149 }
150
type_name()151 std::string FieldGeneratorBase::type_name() {
152 return type_name(descriptor_);
153 }
154
type_name(const FieldDescriptor * descriptor)155 std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
156 switch (descriptor->type()) {
157 case FieldDescriptor::TYPE_ENUM:
158 return GetClassName(descriptor->enum_type());
159 case FieldDescriptor::TYPE_MESSAGE:
160 case FieldDescriptor::TYPE_GROUP:
161 if (IsWrapperType(descriptor)) {
162 const FieldDescriptor* wrapped_field =
163 descriptor->message_type()->field(0);
164 string wrapped_field_type_name = type_name(wrapped_field);
165 // String and ByteString go to the same type; other wrapped types
166 // go to the nullable equivalent.
167 if (wrapped_field->type() == FieldDescriptor::TYPE_STRING ||
168 wrapped_field->type() == FieldDescriptor::TYPE_BYTES) {
169 return wrapped_field_type_name;
170 } else {
171 return wrapped_field_type_name + "?";
172 }
173 }
174 return GetClassName(descriptor->message_type());
175 case FieldDescriptor::TYPE_DOUBLE:
176 return "double";
177 case FieldDescriptor::TYPE_FLOAT:
178 return "float";
179 case FieldDescriptor::TYPE_INT64:
180 return "long";
181 case FieldDescriptor::TYPE_UINT64:
182 return "ulong";
183 case FieldDescriptor::TYPE_INT32:
184 return "int";
185 case FieldDescriptor::TYPE_FIXED64:
186 return "ulong";
187 case FieldDescriptor::TYPE_FIXED32:
188 return "uint";
189 case FieldDescriptor::TYPE_BOOL:
190 return "bool";
191 case FieldDescriptor::TYPE_STRING:
192 return "string";
193 case FieldDescriptor::TYPE_BYTES:
194 return "pb::ByteString";
195 case FieldDescriptor::TYPE_UINT32:
196 return "uint";
197 case FieldDescriptor::TYPE_SFIXED32:
198 return "int";
199 case FieldDescriptor::TYPE_SFIXED64:
200 return "long";
201 case FieldDescriptor::TYPE_SINT32:
202 return "int";
203 case FieldDescriptor::TYPE_SINT64:
204 return "long";
205 default:
206 GOOGLE_LOG(FATAL)<< "Unknown field type.";
207 return "";
208 }
209 }
210
has_default_value()211 bool FieldGeneratorBase::has_default_value() {
212 switch (descriptor_->type()) {
213 case FieldDescriptor::TYPE_ENUM:
214 case FieldDescriptor::TYPE_MESSAGE:
215 case FieldDescriptor::TYPE_GROUP:
216 return true;
217 case FieldDescriptor::TYPE_DOUBLE:
218 return descriptor_->default_value_double() != 0.0;
219 case FieldDescriptor::TYPE_FLOAT:
220 return descriptor_->default_value_float() != 0.0;
221 case FieldDescriptor::TYPE_INT64:
222 return descriptor_->default_value_int64() != 0L;
223 case FieldDescriptor::TYPE_UINT64:
224 return descriptor_->default_value_uint64() != 0L;
225 case FieldDescriptor::TYPE_INT32:
226 return descriptor_->default_value_int32() != 0;
227 case FieldDescriptor::TYPE_FIXED64:
228 return descriptor_->default_value_uint64() != 0L;
229 case FieldDescriptor::TYPE_FIXED32:
230 return descriptor_->default_value_uint32() != 0;
231 case FieldDescriptor::TYPE_BOOL:
232 return descriptor_->default_value_bool();
233 case FieldDescriptor::TYPE_STRING:
234 return true;
235 case FieldDescriptor::TYPE_BYTES:
236 return true;
237 case FieldDescriptor::TYPE_UINT32:
238 return descriptor_->default_value_uint32() != 0;
239 case FieldDescriptor::TYPE_SFIXED32:
240 return descriptor_->default_value_int32() != 0;
241 case FieldDescriptor::TYPE_SFIXED64:
242 return descriptor_->default_value_int64() != 0L;
243 case FieldDescriptor::TYPE_SINT32:
244 return descriptor_->default_value_int32() != 0;
245 case FieldDescriptor::TYPE_SINT64:
246 return descriptor_->default_value_int64() != 0L;
247 default:
248 GOOGLE_LOG(FATAL)<< "Unknown field type.";
249 return true;
250 }
251 }
252
is_nullable_type()253 bool FieldGeneratorBase::is_nullable_type() {
254 switch (descriptor_->type()) {
255 case FieldDescriptor::TYPE_ENUM:
256 case FieldDescriptor::TYPE_DOUBLE:
257 case FieldDescriptor::TYPE_FLOAT:
258 case FieldDescriptor::TYPE_INT64:
259 case FieldDescriptor::TYPE_UINT64:
260 case FieldDescriptor::TYPE_INT32:
261 case FieldDescriptor::TYPE_FIXED64:
262 case FieldDescriptor::TYPE_FIXED32:
263 case FieldDescriptor::TYPE_BOOL:
264 case FieldDescriptor::TYPE_UINT32:
265 case FieldDescriptor::TYPE_SFIXED32:
266 case FieldDescriptor::TYPE_SFIXED64:
267 case FieldDescriptor::TYPE_SINT32:
268 case FieldDescriptor::TYPE_SINT64:
269 return false;
270
271 case FieldDescriptor::TYPE_MESSAGE:
272 case FieldDescriptor::TYPE_GROUP:
273 case FieldDescriptor::TYPE_STRING:
274 case FieldDescriptor::TYPE_BYTES:
275 return true;
276
277 default:
278 GOOGLE_LOG(FATAL)<< "Unknown field type.";
279 return true;
280 }
281 }
282
AllPrintableAscii(const std::string & text)283 bool AllPrintableAscii(const std::string& text) {
284 for(int i = 0; i < text.size(); i++) {
285 if (text[i] < 0x20 || text[i] > 0x7e) {
286 return false;
287 }
288 }
289 return true;
290 }
291
GetStringDefaultValueInternal()292 std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
293 // No other default values needed for proto3...
294 return "\"\"";
295 }
296
GetBytesDefaultValueInternal()297 std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
298 // No other default values needed for proto3...
299 return "pb::ByteString.Empty";
300 }
301
default_value()302 std::string FieldGeneratorBase::default_value() {
303 return default_value(descriptor_);
304 }
305
default_value(const FieldDescriptor * descriptor)306 std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
307 switch (descriptor->type()) {
308 case FieldDescriptor::TYPE_ENUM:
309 // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
310 // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
311 return "0";
312 case FieldDescriptor::TYPE_MESSAGE:
313 case FieldDescriptor::TYPE_GROUP:
314 if (IsWrapperType(descriptor)) {
315 const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
316 return default_value(wrapped_field);
317 } else {
318 return "null";
319 }
320 case FieldDescriptor::TYPE_DOUBLE: {
321 double value = descriptor->default_value_double();
322 if (value == numeric_limits<double>::infinity()) {
323 return "double.PositiveInfinity";
324 } else if (value == -numeric_limits<double>::infinity()) {
325 return "double.NegativeInfinity";
326 } else if (MathLimits<double>::IsNaN(value)) {
327 return "double.NaN";
328 }
329 return SimpleDtoa(value) + "D";
330 }
331 case FieldDescriptor::TYPE_FLOAT: {
332 float value = descriptor->default_value_float();
333 if (value == numeric_limits<float>::infinity()) {
334 return "float.PositiveInfinity";
335 } else if (value == -numeric_limits<float>::infinity()) {
336 return "float.NegativeInfinity";
337 } else if (MathLimits<float>::IsNaN(value)) {
338 return "float.NaN";
339 }
340 return SimpleFtoa(value) + "F";
341 }
342 case FieldDescriptor::TYPE_INT64:
343 return SimpleItoa(descriptor->default_value_int64()) + "L";
344 case FieldDescriptor::TYPE_UINT64:
345 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
346 case FieldDescriptor::TYPE_INT32:
347 return SimpleItoa(descriptor->default_value_int32());
348 case FieldDescriptor::TYPE_FIXED64:
349 return SimpleItoa(descriptor->default_value_uint64()) + "UL";
350 case FieldDescriptor::TYPE_FIXED32:
351 return SimpleItoa(descriptor->default_value_uint32());
352 case FieldDescriptor::TYPE_BOOL:
353 if (descriptor->default_value_bool()) {
354 return "true";
355 } else {
356 return "false";
357 }
358 case FieldDescriptor::TYPE_STRING:
359 return GetStringDefaultValueInternal();
360 case FieldDescriptor::TYPE_BYTES:
361 return GetBytesDefaultValueInternal();
362 case FieldDescriptor::TYPE_UINT32:
363 return SimpleItoa(descriptor->default_value_uint32());
364 case FieldDescriptor::TYPE_SFIXED32:
365 return SimpleItoa(descriptor->default_value_int32());
366 case FieldDescriptor::TYPE_SFIXED64:
367 return SimpleItoa(descriptor->default_value_int64()) + "L";
368 case FieldDescriptor::TYPE_SINT32:
369 return SimpleItoa(descriptor->default_value_int32());
370 case FieldDescriptor::TYPE_SINT64:
371 return SimpleItoa(descriptor->default_value_int64()) + "L";
372 default:
373 GOOGLE_LOG(FATAL)<< "Unknown field type.";
374 return "";
375 }
376 }
377
number()378 std::string FieldGeneratorBase::number() {
379 return SimpleItoa(descriptor_->number());
380 }
381
capitalized_type_name()382 std::string FieldGeneratorBase::capitalized_type_name() {
383 switch (descriptor_->type()) {
384 case FieldDescriptor::TYPE_ENUM:
385 return "Enum";
386 case FieldDescriptor::TYPE_MESSAGE:
387 return "Message";
388 case FieldDescriptor::TYPE_GROUP:
389 return "Group";
390 case FieldDescriptor::TYPE_DOUBLE:
391 return "Double";
392 case FieldDescriptor::TYPE_FLOAT:
393 return "Float";
394 case FieldDescriptor::TYPE_INT64:
395 return "Int64";
396 case FieldDescriptor::TYPE_UINT64:
397 return "UInt64";
398 case FieldDescriptor::TYPE_INT32:
399 return "Int32";
400 case FieldDescriptor::TYPE_FIXED64:
401 return "Fixed64";
402 case FieldDescriptor::TYPE_FIXED32:
403 return "Fixed32";
404 case FieldDescriptor::TYPE_BOOL:
405 return "Bool";
406 case FieldDescriptor::TYPE_STRING:
407 return "String";
408 case FieldDescriptor::TYPE_BYTES:
409 return "Bytes";
410 case FieldDescriptor::TYPE_UINT32:
411 return "UInt32";
412 case FieldDescriptor::TYPE_SFIXED32:
413 return "SFixed32";
414 case FieldDescriptor::TYPE_SFIXED64:
415 return "SFixed64";
416 case FieldDescriptor::TYPE_SINT32:
417 return "SInt32";
418 case FieldDescriptor::TYPE_SINT64:
419 return "SInt64";
420 default:
421 GOOGLE_LOG(FATAL)<< "Unknown field type.";
422 return "";
423 }
424 }
425
426 } // namespace csharp
427 } // namespace compiler
428 } // namespace protobuf
429 } // namespace google
430