• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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