• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  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 "upb_generator/c/names.h"
9 
10 #include <array>
11 #include <cstdint>
12 #include <string>
13 #include <vector>
14 
15 #include "absl/container/flat_hash_map.h"
16 #include "absl/strings/match.h"
17 #include "absl/strings/str_cat.h"
18 #include "absl/strings/str_join.h"
19 #include "absl/strings/str_replace.h"
20 #include "absl/strings/str_split.h"
21 #include "absl/strings/string_view.h"
22 #include "upb_generator/c/names_internal.h"
23 
24 namespace upb {
25 namespace generator {
26 
27 namespace {
28 
ToCIdent(absl::string_view str)29 std::string ToCIdent(absl::string_view str) {
30   return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}});
31 }
32 
33 }  // namespace
34 
CApiHeaderFilename(absl::string_view proto_filename)35 std::string CApiHeaderFilename(absl::string_view proto_filename) {
36   return CApiHeaderFilename(proto_filename, false);
37 }
38 
CApiMessageType(absl::string_view full_name)39 std::string CApiMessageType(absl::string_view full_name) {
40   return ToCIdent(full_name);
41 }
42 
CApiEnumType(absl::string_view full_name)43 std::string CApiEnumType(absl::string_view full_name) {
44   return ToCIdent(full_name);
45 }
46 
CApiEnumValueSymbol(absl::string_view full_name)47 std::string CApiEnumValueSymbol(absl::string_view full_name) {
48   return ToCIdent(full_name);
49 }
50 
CApiExtensionIdentBase(absl::string_view full_name)51 std::string CApiExtensionIdentBase(absl::string_view full_name) {
52   std::vector<std::string> parts = absl::StrSplit(full_name, '.');
53   parts.pop_back();
54   return ToCIdent(absl::StrJoin(parts, "."));
55 }
56 
CApiOneofIdentBase(absl::string_view full_name)57 std::string CApiOneofIdentBase(absl::string_view full_name) {
58   return ToCIdent(full_name);
59 }
60 
61 namespace {
62 
63 struct Prefix {
64   absl::string_view name;
65   uint32_t conflict_set;
66 };
67 
68 constexpr uint32_t kAnyField = UINT32_MAX;
69 
70 // Prefixes used by C code generator for field access.
71 static constexpr std::array<Prefix, 6> kPrefixes{
72     Prefix{"clear_", kContainerField | kStringField},
73     Prefix{"delete_", kContainerField},
74     Prefix{"add_", kContainerField},
75     Prefix{"resize_", kContainerField},
76     Prefix{"set_", kAnyField},
77     Prefix{"has_", kAnyField},
78 };
79 
HasConflict(absl::string_view name,const absl::flat_hash_map<std::string,FieldClass> & fields)80 bool HasConflict(absl::string_view name,
81                  const absl::flat_hash_map<std::string, FieldClass>& fields) {
82   for (const auto& prefix : kPrefixes) {
83     if (!absl::StartsWith(name, prefix.name)) continue;
84     auto match = fields.find(name.substr(prefix.name.size()));
85     if (match == fields.end()) continue;
86     if (prefix.conflict_set & match->second) return true;
87   }
88   return false;
89 }
90 
91 }  // namespace
92 
NameMangler(const absl::flat_hash_map<std::string,FieldClass> & fields)93 NameMangler::NameMangler(
94     const absl::flat_hash_map<std::string, FieldClass>& fields) {
95   for (const auto& pair : fields) {
96     const std::string& field_name = pair.first;
97     if (HasConflict(field_name, fields)) {
98       names_.emplace(field_name, absl::StrCat(field_name, "_"));
99     }
100   }
101 }
102 
103 }  // namespace generator
104 }  // namespace upb
105