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