1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2024 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 "google/protobuf/compiler/cpp/ifndef_guard.h"
9
10 #include <string>
11
12 #include "absl/functional/any_invocable.h"
13 #include "absl/log/die_if_null.h"
14 #include "absl/strings/ascii.h"
15 #include "absl/strings/str_cat.h"
16 #include "absl/strings/str_replace.h"
17 #include "absl/strings/string_view.h"
18 #include "absl/strings/substitute.h"
19 #include "google/protobuf/io/printer.h"
20
21 namespace google {
22 namespace protobuf {
23 namespace compiler {
24 namespace cpp {
25
26 namespace {
27
MakeIfdefGuardIdentifier(const absl::string_view header_path)28 std::string MakeIfdefGuardIdentifier(const absl::string_view header_path) {
29 return absl::StrCat(absl::AsciiStrToUpper(absl::StrReplaceAll(header_path,
30 {
31 {"/", "_"},
32 {".", "_"},
33 {"-", "_"},
34 })),
35 "_");
36 }
37
38 } // namespace
39
IfdefGuardPrinter(google::protobuf::io::Printer * const p,const absl::string_view filename)40 IfdefGuardPrinter::IfdefGuardPrinter(google::protobuf::io::Printer* const p,
41 const absl::string_view filename)
42 : IfdefGuardPrinter(p, filename, MakeIfdefGuardIdentifier) {}
43
IfdefGuardPrinter(google::protobuf::io::Printer * const p,const absl::string_view filename,absl::AnyInvocable<std::string (absl::string_view)> make_ifdef_identifier)44 IfdefGuardPrinter::IfdefGuardPrinter(
45 google::protobuf::io::Printer* const p, const absl::string_view filename,
46 absl::AnyInvocable<std::string(absl::string_view)> make_ifdef_identifier)
47 : p_(ABSL_DIE_IF_NULL(p)),
48 ifdef_identifier_(make_ifdef_identifier(filename)) {
49 // We can't use variable substitution, because we don't know what delimiter
50 // to use.
51 p->Print(absl::Substitute(
52 R"(#ifndef $0
53 #define $0
54
55 )",
56 ifdef_identifier_));
57 }
58
~IfdefGuardPrinter()59 IfdefGuardPrinter::~IfdefGuardPrinter() {
60 // We can't use variable substitution, because we don't know what delimiter
61 // to use.
62 p_->Print(absl::Substitute(
63 R"(
64 #endif // $0
65 )",
66 ifdef_identifier_));
67 }
68
69 } // namespace cpp
70 } // namespace compiler
71 } // namespace protobuf
72 } // namespace google
73