aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/csharp/csharp_message.cc
diff options
context:
space:
mode:
authorSydney Acksman <ObsidianMinor@users.noreply.github.com>2018-09-24 15:42:24 -0500
committerJie Luo <anandolee@gmail.com>2018-09-24 13:42:24 -0700
commit54176b26a9be6c9903b375596b778f51f5947921 (patch)
treea441d2831ecdb3db5e1f867b8fabc94ed523de13 /src/google/protobuf/compiler/csharp/csharp_message.cc
parentfb0a74b66076d6c55022a9bccabf6cdb08dbab83 (diff)
downloadprotobuf-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.cc58
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