diff options
author | Jon Skeet <jonskeet@google.com> | 2015-06-23 16:09:27 +0100 |
---|---|---|
committer | Jon Skeet <jonskeet@google.com> | 2015-06-24 17:56:22 +0100 |
commit | bfee2dfe137b07e64ebd46baf71d932d58d01b1f (patch) | |
tree | 4bf6258a990369335cc82c8a8059eaaf1dc2dd06 /src/google/protobuf/compiler/csharp/csharp_message.cc | |
parent | 94071b54d24d2f2f1cb5933a692b5397a047057c (diff) |
Implement freezing for messages and repeated fields.
Fixes issue #523.
Diffstat (limited to 'src/google/protobuf/compiler/csharp/csharp_message.cc')
-rw-r--r-- | src/google/protobuf/compiler/csharp/csharp_message.cc | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 39938fa3..9580c167 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -211,7 +211,9 @@ void MessageGenerator::Generate(io::Printer* printer) { "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n" " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" "}\n" - "\n"); + "\n" + "private bool _frozen = false;\n" + "public bool IsFrozen { get { return _frozen; } }\n\n"); // Parameterless constructor printer->Print( @@ -219,6 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) { "public $class_name$() { }\n\n"); GenerateCloningCode(printer); + GenerateFreezingCode(printer); // Fields/properties for (int i = 0; i < descriptor_->field_count(); i++) { @@ -260,6 +263,7 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return $name$Case_; }\n" "}\n\n" "public void Clear$property_name$() {\n" + " pb::Freezable.CheckMutable(this);\n" " $name$Case_ = $property_name$OneofCase.None;\n" " $name$_ = null;\n" "}\n\n"); @@ -346,6 +350,36 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { "}\n\n"); } +void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { + map<string, string> vars; + vars["class_name"] = class_name(); + printer->Print( + "public void Freeze() {\n" + " if (IsFrozen) {\n" + " return;\n" + " }\n" + " _frozen = true;\n"); + printer->Indent(); + // Freeze non-oneof fields first (only messages and repeated fields will actually generate any code) + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateFreezingCode(printer); + } + } + + // For each oneof, if the value is freezable, freeze it. We don't actually need to know which type it was. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + printer->Print(vars, + "if ($name$_ is IFreezable) ((IFreezable) $name$_).Freeze();\n"); + } + + printer->Outdent(); + printer->Print("}\n\n"); +} + void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { map<string, string> vars; vars["class_name"] = class_name(); |