1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2015 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/csharp/csharp_map_field.h"
9
10 #include <sstream>
11
12 #include "google/protobuf/compiler/code_generator.h"
13 #include "google/protobuf/descriptor.h"
14 #include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
15 #include "google/protobuf/compiler/csharp/csharp_helpers.h"
16 #include "google/protobuf/descriptor.pb.h"
17 #include "google/protobuf/io/printer.h"
18
19 namespace google {
20 namespace protobuf {
21 namespace compiler {
22 namespace csharp {
23
MapFieldGenerator(const FieldDescriptor * descriptor,int presenceIndex,const Options * options)24 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
25 int presenceIndex,
26 const Options* options)
27 : FieldGeneratorBase(descriptor, presenceIndex, options) {
28 }
29
~MapFieldGenerator()30 MapFieldGenerator::~MapFieldGenerator() {
31 }
32
GenerateMembers(io::Printer * printer)33 void MapFieldGenerator::GenerateMembers(io::Printer* printer) {
34 const FieldDescriptor* key_descriptor =
35 descriptor_->message_type()->map_key();
36 const FieldDescriptor* value_descriptor =
37 descriptor_->message_type()->map_value();
38 variables_["key_type_name"] = type_name(key_descriptor);
39 variables_["value_type_name"] = type_name(value_descriptor);
40 std::unique_ptr<FieldGeneratorBase> key_generator(
41 CreateFieldGenerator(key_descriptor, 1, this->options()));
42 std::unique_ptr<FieldGeneratorBase> value_generator(
43 CreateFieldGenerator(value_descriptor, 2, this->options()));
44
45 printer->Print(
46 variables_,
47 "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
48 " = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
49 key_generator->GenerateCodecCode(printer);
50 printer->Print(", ");
51 value_generator->GenerateCodecCode(printer);
52 printer->Print(
53 variables_,
54 ", $tag$);\n"
55 "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
56 WritePropertyDocComment(printer, options(), descriptor_);
57 AddPublicMemberAttributes(printer);
58 printer->Print(
59 variables_,
60 "$access_level$ pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
61 " get { return $name$_; }\n"
62 "}\n");
63 }
64
GenerateMergingCode(io::Printer * printer)65 void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
66 printer->Print(variables_,
67 "$name$_.MergeFrom(other.$name$_);\n");
68 }
69
GenerateParsingCode(io::Printer * printer)70 void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
71 GenerateParsingCode(printer, true);
72 }
73
GenerateParsingCode(io::Printer * printer,bool use_parse_context)74 void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse_context) {
75 printer->Print(
76 variables_,
77 use_parse_context
78 ? "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"
79 : "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
80 }
81
GenerateSerializationCode(io::Printer * printer)82 void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
83 GenerateSerializationCode(printer, true);
84 }
85
GenerateSerializationCode(io::Printer * printer,bool use_write_context)86 void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) {
87 printer->Print(
88 variables_,
89 use_write_context
90 ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n"
91 : "$name$_.WriteTo(output, _map_$name$_codec);\n");
92 }
93
GenerateSerializedSizeCode(io::Printer * printer)94 void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
95 printer->Print(
96 variables_,
97 "size += $name$_.CalculateSize(_map_$name$_codec);\n");
98 }
99
WriteHash(io::Printer * printer)100 void MapFieldGenerator::WriteHash(io::Printer* printer) {
101 printer->Print(
102 variables_,
103 "hash ^= $property_name$.GetHashCode();\n");
104 }
WriteEquals(io::Printer * printer)105 void MapFieldGenerator::WriteEquals(io::Printer* printer) {
106 printer->Print(
107 variables_,
108 "if (!$property_name$.Equals(other.$property_name$)) return false;\n");
109 }
110
WriteToString(io::Printer * printer)111 void MapFieldGenerator::WriteToString(io::Printer* printer) {
112 // TODO: If we ever actually use ToString, we'll need to impleme this...
113 }
114
GenerateCloningCode(io::Printer * printer)115 void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
116 printer->Print(variables_,
117 "$name$_ = other.$name$_.Clone();\n");
118 }
119
GenerateFreezingCode(io::Printer * printer)120 void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
121 }
122
123 } // namespace csharp
124 } // namespace compiler
125 } // namespace protobuf
126 } // namespace google
127