diff options
author | Sydney Acksman <ObsidianMinor@users.noreply.github.com> | 2018-09-24 15:42:24 -0500 |
---|---|---|
committer | Jie Luo <anandolee@gmail.com> | 2018-09-24 13:42:24 -0700 |
commit | 54176b26a9be6c9903b375596b778f51f5947921 (patch) | |
tree | a441d2831ecdb3db5e1f867b8fabc94ed523de13 /src/google/protobuf/compiler/csharp/csharp_message.cc | |
parent | fb0a74b66076d6c55022a9bccabf6cdb08dbab83 (diff) | |
download | protobuf-54176b26a9be6c9903b375596b778f51f5947921.tar.gz protobuf-54176b26a9be6c9903b375596b778f51f5947921.tar.bz2 protobuf-54176b26a9be6c9903b375596b778f51f5947921.zip |
C# Proto2 feature : Field presence and default values (#4642)
* Compiler changes
* Generated code changes
* Library changes
* Compiler style changes
* Generated style changes
* Fix Windows build errors
* Implement changes from review
* Reintroduce proto2 check
* Compiler changes (required handling review)
* Generated code changes (required handling review)
* Library changes (required handling review
* Field presence rewrite (compiler changes)
* Field presence rewrite (generated code changes)
* Compiler comment
* IFieldAccessor.HasValue library implementation
* Remove Clear methods and default values from proto3 code (Compiler)
* Remove Clear methods and default values from proto3 code (Generated)
* Remove Clear methods and default values from proto3 code (Library)
* Fix distcheck error
* Rewrite default string values to use base64 and convert
* Library changes (IMessage2)
* Compiler changes (IMessage2)
* Generated changes (IMessage2)
* Rebased and regenerated
* Compiler changes (initialized extension)
* Generated changes (initialized extension)
* Library changes (initialized extension)
* Refactor MessageExtensions.IsRequired
* Move string default value creator and bytes default value creator back to seperate methods
* Dead code cleanup
* Fixed segmentation fault
Removed unused header method declarations
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_message.cc')
-rw-r--r-- | src/google/protobuf/compiler/csharp/csharp_message.cc | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 8a4307f1..1daae6f5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -61,20 +61,27 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) { MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Options* options) : SourceGeneratorBase(descriptor->file(), options), - descriptor_(descriptor) { - - // sorted field names - for (int i = 0; i < descriptor_->field_count(); i++) { - field_names_.push_back(descriptor_->field(i)->name()); - } - std::sort(field_names_.begin(), field_names_.end()); - + descriptor_(descriptor), + has_bit_field_count_(0) { // fields by number for (int i = 0; i < descriptor_->field_count(); i++) { fields_by_number_.push_back(descriptor_->field(i)); } std::sort(fields_by_number_.begin(), fields_by_number_.end(), CompareFieldNumbers); + + if (IsProto2(descriptor_->file())) { + int primitiveCount = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!IsNullable(field)) { + primitiveCount++; + if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) { + has_bit_field_count_++; + } + } + } + } } MessageGenerator::~MessageGenerator() { @@ -88,10 +95,6 @@ std::string MessageGenerator::full_class_name() { return GetClassName(descriptor_); } -const std::vector<std::string>& MessageGenerator::field_names() { - return field_names_; -} - const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() { return fields_by_number_; } @@ -123,6 +126,12 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( "private pb::UnknownFieldSet _unknownFields;\n"); + for (int i = 0; i < has_bit_field_count_; i++) { + // don't use arrays since all arrays are heap allocated, saving allocations + // use ints instead of bytes since bytes lack bitwise operators, saving casts + printer->Print("private int _hasBits$i$;\n", "i", SimpleItoa(i)); + } + WriteGeneratedCodeAttributes(printer); printer->Print( @@ -288,6 +297,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { vars, "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); + for (int i = 0; i < has_bit_field_count_; i++) { + printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", SimpleItoa(i)); + } // Clone non-oneof fields first for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { @@ -559,19 +571,29 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print("}\n\n"); // method } -int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { - for (int i = 0; i < field_names().size(); i++) { - if (field_names()[i] == descriptor->name()) { - return i; +// it's a waste of space to track presence for all values, so we only track them if they're not nullable +int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { + if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) { + return -1; + } + + int index = 0; + for (int i = 0; i < fields_by_number().size(); i++) { + const FieldDescriptor* field = fields_by_number()[i]; + if (field == descriptor) { + return index; + } + if (!IsNullable(field)) { + index++; } } - GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name(); + GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name(); return -1; } FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( const FieldDescriptor* descriptor) { - return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options()); + return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options()); } } // namespace csharp |