1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 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 <memory>
9 #include <string>
10 #include <vector>
11
12 #include "absl/strings/ascii.h"
13 #include "absl/strings/str_cat.h"
14 #include "absl/strings/string_view.h"
15 #include "absl/strings/substitute.h"
16 #include "google/protobuf/compiler/cpp/field.h"
17 #include "google/protobuf/compiler/cpp/helpers.h"
18 #include "google/protobuf/compiler/cpp/options.h"
19 #include "google/protobuf/descriptor.h"
20 #include "google/protobuf/io/printer.h"
21
22 namespace google {
23 namespace protobuf {
24 namespace compiler {
25 namespace cpp {
26 namespace {
27 using Sub = ::google::protobuf::io::Printer::Sub;
28
Vars(const FieldDescriptor * field,const Options & opts,bool lite)29 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts,
30 bool lite) {
31 const auto* key = field->message_type()->map_key();
32 const auto* val = field->message_type()->map_value();
33
34 std::string key_type = PrimitiveTypeName(opts, key->cpp_type());
35 std::string val_type;
36 switch (val->cpp_type()) {
37 case FieldDescriptor::CPPTYPE_MESSAGE:
38 val_type = FieldMessageTypeName(val, opts);
39 break;
40 case FieldDescriptor::CPPTYPE_ENUM:
41 val_type = ClassName(val->enum_type(), true);
42 break;
43 default:
44 val_type = PrimitiveTypeName(opts, val->cpp_type());
45 break;
46 }
47
48 return {
49 {"Map", absl::Substitute("::google::protobuf::Map<$0, $1>", key_type, val_type)},
50 {"Entry", ClassName(field->message_type(), false)},
51 {"Key", PrimitiveTypeName(opts, key->cpp_type())},
52 {"Val", val_type},
53 {"MapField", lite ? "MapFieldLite" : "MapField"},
54 };
55 }
56
EmitFuncs(const FieldDescriptor * field,io::Printer * p)57 void EmitFuncs(const FieldDescriptor* field, io::Printer* p) {
58 const auto* key = field->message_type()->map_key();
59 const auto* val = field->message_type()->map_value();
60 p->Emit(
61 {
62 {"key_wire_type",
63 absl::StrCat("TYPE_", absl::AsciiStrToUpper(
64 DeclaredTypeMethodName(key->type())))},
65 {"val_wire_type",
66 absl::StrCat("TYPE_", absl::AsciiStrToUpper(
67 DeclaredTypeMethodName(val->type())))},
68 },
69 R"cc(_pbi::MapEntryFuncs<$Key$, $Val$,
70 _pbi::WireFormatLite::$key_wire_type$,
71 _pbi::WireFormatLite::$val_wire_type$>)cc");
72 }
73
74 class Map : public FieldGeneratorBase {
75 public:
Map(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)76 Map(const FieldDescriptor* field, const Options& opts,
77 MessageSCCAnalyzer* scc)
78 : FieldGeneratorBase(field, opts, scc),
79 key_(field->message_type()->map_key()),
80 val_(field->message_type()->map_value()),
81 opts_(&opts),
82 has_required_(scc->HasRequiredFields(field->message_type())),
83 lite_(!HasDescriptorMethods(field->file(), opts)) {}
84 ~Map() override = default;
85
MakeVars() const86 std::vector<Sub> MakeVars() const override {
87 return Vars(field_, *opts_, lite_);
88 }
89
GenerateClearingCode(io::Printer * p) const90 void GenerateClearingCode(io::Printer* p) const override {
91 p->Emit(R"cc(
92 $field_$.Clear();
93 )cc");
94 }
95
GenerateMergingCode(io::Printer * p) const96 void GenerateMergingCode(io::Printer* p) const override {
97 p->Emit(R"cc(
98 _this->$field_$.MergeFrom(from.$field_$);
99 )cc");
100 }
101
GenerateSwappingCode(io::Printer * p) const102 void GenerateSwappingCode(io::Printer* p) const override {
103 p->Emit(R"cc(
104 $field_$.InternalSwap(&other->$field_$);
105 )cc");
106 }
107
GenerateCopyConstructorCode(io::Printer * p) const108 void GenerateCopyConstructorCode(io::Printer* p) const override {
109 GenerateConstructorCode(p);
110 GenerateMergingCode(p);
111 }
112
GenerateIsInitialized(io::Printer * p) const113 void GenerateIsInitialized(io::Printer* p) const override {
114 if (!NeedsIsInitialized()) return;
115
116 p->Emit(R"cc(
117 if (!$pbi$::AllAreInitialized(this_.$field_$)) {
118 return false;
119 }
120 )cc");
121 }
122
NeedsIsInitialized() const123 bool NeedsIsInitialized() const override { return has_required_; }
124
GenerateConstexprAggregateInitializer(io::Printer * p) const125 void GenerateConstexprAggregateInitializer(io::Printer* p) const override {
126 p->Emit(R"cc(
127 /* decltype($field_$) */ {},
128 )cc");
129 }
130
GenerateCopyAggregateInitializer(io::Printer * p) const131 void GenerateCopyAggregateInitializer(io::Printer* p) const override {
132 // MapField has no move constructor, which prevents explicit aggregate
133 // initialization pre-C++17.
134 p->Emit(R"cc(
135 /* decltype($field_$) */ {},
136 )cc");
137 }
138
GenerateAggregateInitializer(io::Printer * p) const139 void GenerateAggregateInitializer(io::Printer* p) const override {
140 if (should_split()) {
141 p->Emit(R"cc(
142 /* decltype($Msg$::Split::$name$_) */ {
143 $pbi$::ArenaInitialized(),
144 arena,
145 },
146 )cc");
147 } else {
148 p->Emit(R"cc(
149 /* decltype($field_$) */ {$pbi$::ArenaInitialized(), arena},
150 )cc");
151 }
152 }
153
GenerateConstructorCode(io::Printer * p) const154 void GenerateConstructorCode(io::Printer* p) const override {}
155
GenerateDestructorCode(io::Printer * p) const156 void GenerateDestructorCode(io::Printer* p) const override {
157 if (should_split()) {
158 p->Emit(R"cc(
159 $cached_split_ptr$->$name$_.~$MapField$();
160 )cc");
161 return;
162 }
163 }
164
165 void GeneratePrivateMembers(io::Printer* p) const override;
166 void GenerateAccessorDeclarations(io::Printer* p) const override;
167 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
168 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
169 void GenerateByteSize(io::Printer* p) const override;
170
171 private:
172 const FieldDescriptor* key_;
173 const FieldDescriptor* val_;
174 const Options* opts_;
175 bool has_required_;
176 bool lite_;
177 };
178
GeneratePrivateMembers(io::Printer * p) const179 void Map::GeneratePrivateMembers(io::Printer* p) const {
180 if (lite_) {
181 p->Emit(
182 R"cc(
183 $pbi$::MapFieldLite<$Key$, $Val$> $name$_;
184 )cc");
185 } else {
186 p->Emit({{"kKeyType",
187 absl::AsciiStrToUpper(DeclaredTypeMethodName(key_->type()))},
188 {"kValType",
189 absl::AsciiStrToUpper(DeclaredTypeMethodName(val_->type()))}},
190 R"cc(
191 $pbi$::$MapField$<$Entry$, $Key$, $Val$,
192 $pbi$::WireFormatLite::TYPE_$kKeyType$,
193 $pbi$::WireFormatLite::TYPE_$kValType$>
194 $name$_;
195 )cc");
196 }
197 }
198
GenerateAccessorDeclarations(io::Printer * p) const199 void Map::GenerateAccessorDeclarations(io::Printer* p) const {
200 auto v1 = p->WithVars(
201 AnnotatedAccessors(field_, {"", "_internal_", "_internal_mutable_"}));
202 auto v2 = p->WithVars(AnnotatedAccessors(field_, {"mutable_"},
203 io::AnnotationCollector::kAlias));
204 p->Emit(R"cc(
205 $DEPRECATED$ const $Map$& $name$() const;
206 $DEPRECATED$ $Map$* $mutable_name$();
207
208 private:
209 const $Map$& $_internal_name$() const;
210 $Map$* $_internal_mutable_name$();
211
212 public:
213 )cc");
214 }
215
GenerateInlineAccessorDefinitions(io::Printer * p) const216 void Map::GenerateInlineAccessorDefinitions(io::Printer* p) const {
217 p->Emit(R"cc(
218 inline const $Map$& $Msg$::_internal_$name_internal$() const {
219 $TsanDetectConcurrentRead$;
220 return $field_$.GetMap();
221 }
222 )cc");
223 p->Emit(R"cc(
224 inline const $Map$& $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
225 $WeakDescriptorSelfPin$;
226 $annotate_get$;
227 // @@protoc_insertion_point(field_map:$pkg.Msg.field$)
228 return _internal_$name_internal$();
229 }
230 )cc");
231 p->Emit(R"cc(
232 inline $Map$* $Msg$::_internal_mutable_$name_internal$() {
233 $PrepareSplitMessageForWrite$;
234 $TsanDetectConcurrentMutation$;
235 return $field_$.MutableMap();
236 }
237 )cc");
238 p->Emit(R"cc(
239 inline $Map$* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
240 $WeakDescriptorSelfPin$;
241 $annotate_mutable$;
242 // @@protoc_insertion_point(field_mutable_map:$pkg.Msg.field$)
243 return _internal_mutable_$name_internal$();
244 }
245 )cc");
246 }
247
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const248 void Map::GenerateSerializeWithCachedSizesToArray(io::Printer* p) const {
249 bool string_key = key_->type() == FieldDescriptor::TYPE_STRING;
250 bool string_val = val_->type() == FieldDescriptor::TYPE_STRING;
251
252 p->Emit(
253 {
254 {"Sorter", string_key ? "MapSorterPtr" : "MapSorterFlat"},
255 {
256 "CheckUtf8",
257 [&] {
258 if (string_key) {
259 GenerateUtf8CheckCodeForString(
260 p, key_, *opts_, /*for_parse=*/false,
261 "entry.first.data(), "
262 "static_cast<int>(entry.first.length()),\n");
263 }
264 if (string_val) {
265 GenerateUtf8CheckCodeForString(
266 p, val_, *opts_, /*for_parse=*/false,
267 "entry.second.data(), "
268 "static_cast<int>(entry.second.length()),\n");
269 }
270 },
271 },
272 {"Funcs",
273 [&] {
274 EmitFuncs(field_, p);
275 p->Emit(";");
276 }},
277 },
278 R"cc(
279 if (!this_._internal_$name$().empty()) {
280 using MapType = $Map$;
281 using WireHelper = $Funcs$;
282 const auto& field = this_._internal_$name$();
283
284 if (stream->IsSerializationDeterministic() && field.size() > 1) {
285 for (const auto& entry : $pbi$::$Sorter$<MapType>(field)) {
286 target = WireHelper::InternalSerialize(
287 $number$, entry.first, entry.second, target, stream);
288 $CheckUtf8$;
289 }
290 } else {
291 for (const auto& entry : field) {
292 target = WireHelper::InternalSerialize(
293 $number$, entry.first, entry.second, target, stream);
294 $CheckUtf8$;
295 }
296 }
297 }
298 )cc");
299 }
300
GenerateByteSize(io::Printer * p) const301 void Map::GenerateByteSize(io::Printer* p) const {
302 p->Emit(
303 {
304 {"Funcs", [&] { EmitFuncs(field_, p); }},
305 },
306 R"cc(
307 total_size +=
308 $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$_size());
309 for (const auto& entry : this_._internal_$name$()) {
310 total_size += $Funcs$::ByteSizeLong(entry.first, entry.second);
311 }
312 )cc");
313 }
314 } // namespace
315
MakeMapGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)316 std::unique_ptr<FieldGeneratorBase> MakeMapGenerator(
317 const FieldDescriptor* desc, const Options& options,
318 MessageSCCAnalyzer* scc) {
319 return std::make_unique<Map>(desc, options, scc);
320 }
321
322 } // namespace cpp
323 } // namespace compiler
324 } // namespace protobuf
325 } // namespace google
326