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 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 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 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 111 FieldGeneratorBase::~FieldGeneratorBase() { 112 } 113 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 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 124 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { 125 if (descriptor_->options().deprecated()) 126 { 127 printer->Print("[global::System.ObsoleteAttribute()]\n"); 128 } 129 } 130 131 void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) { 132 AddDeprecatedFlag(printer); 133 } 134 135 std::string FieldGeneratorBase::oneof_property_name() { 136 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true); 137 } 138 139 std::string FieldGeneratorBase::oneof_name() { 140 return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false); 141 } 142 143 std::string FieldGeneratorBase::property_name() { 144 return GetPropertyName(descriptor_); 145 } 146 147 std::string FieldGeneratorBase::name() { 148 return UnderscoresToCamelCase(GetFieldName(descriptor_), false); 149 } 150 151 std::string FieldGeneratorBase::type_name() { 152 return type_name(descriptor_); 153 } 154 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 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 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 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 292 std::string FieldGeneratorBase::GetStringDefaultValueInternal() { 293 // No other default values needed for proto3... 294 return "\"\""; 295 } 296 297 std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { 298 // No other default values needed for proto3... 299 return "pb::ByteString.Empty"; 300 } 301 302 std::string FieldGeneratorBase::default_value() { 303 return default_value(descriptor_); 304 } 305 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 378 std::string FieldGeneratorBase::number() { 379 return SimpleItoa(descriptor_->number()); 380 } 381 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