aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/csharp/csharp_message.cc
diff options
context:
space:
mode:
authorGravatar Jon Skeet <jonskeet@google.com>2015-06-23 16:09:27 +0100
committerGravatar Jon Skeet <jonskeet@google.com>2015-06-24 17:56:22 +0100
commitbfee2dfe137b07e64ebd46baf71d932d58d01b1f (patch)
tree4bf6258a990369335cc82c8a8059eaaf1dc2dd06 /src/google/protobuf/compiler/csharp/csharp_message.cc
parent94071b54d24d2f2f1cb5933a692b5397a047057c (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.cc36
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();