microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
source_location.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
9#include "../microfmt.hpp"
10#include <cstdint>
11#include <string_view>
12
13namespace microfmt {
14
15#if MICROFMT_HAS_SOURCE_LOCATION
16template <typename Location> struct basic_source_loc_view {
17 Location loc;
18 bool show_function{true};
19 bool file_basename_only{true};
20};
21
22#if MICROFMT_HAS_STD_SOURCE_LOCATION
23// NOLINTBEGIN(reloco-banned-std-type): std::source_location is the portable C++20 interop type
24// (reloco::call_location_ref is freestanding-only)
25using std_source_loc_view = basic_source_loc_view<std::source_location>;
26
27[[nodiscard]] constexpr std_source_loc_view source_loc(std::source_location loc = std::source_location::current(),
28 bool show_fn = true, bool basename_only = true) noexcept {
29 return std_source_loc_view{loc, show_fn, basename_only};
30}
31#endif
32// NOLINTEND(reloco-banned-std-type)
33
34#if MICROFMT_HAS_BOOST_SOURCE_LOCATION
35using boost_source_loc_view = basic_source_loc_view<boost::source_location>;
36
37[[nodiscard]] constexpr boost_source_loc_view source_loc(boost::source_location loc, bool show_fn = true,
38 bool basename_only = true) noexcept {
39 return boost_source_loc_view{loc, show_fn, basename_only};
40}
41#endif
42
43#if MICROFMT_HAS_STD_SOURCE_LOCATION
44using source_loc_view = std_source_loc_view;
45#elif MICROFMT_HAS_BOOST_SOURCE_LOCATION
46using source_loc_view = boost_source_loc_view;
47#endif
48
49template <typename Location> struct formatter<basic_source_loc_view<Location>> {
50 bool parse_short{false};
51 bool parse_fn{true};
52
53 constexpr void parse(format_parse_context &ctx) noexcept {
54 for (char c : ctx.spec()) {
55 if (c == 's' || c == 'S')
56 parse_short = true; // {:s} -> file:line only
57 if (c == 'f' || c == 'F')
58 parse_fn = true;
59 }
60 }
61
62 void format(const basic_source_loc_view<Location> &sv, const sink &out) const noexcept {
63 microfmt::string_view file = sv.loc.file_name();
64
65 if (sv.file_basename_only) {
66 // Extract filename after last '/' or '\'
67 size_t last_slash = file.find_last_of("/\\");
68 if (last_slash != microfmt::string_view::npos) {
69 file = file.substr(last_slash + 1);
70 }
71 }
72
73 out.write(file);
74 out.put(':');
75 detail::format_unsigned<detail::radix::decimal>(out, sv.loc.line(), false, 0);
76
77 const bool emit_fn = (sv.show_function && parse_fn && !parse_short);
78 if (emit_fn) {
79 out.write(" in ");
80 out.write(sv.loc.function_name());
81 out.write("()");
82 }
83 }
84};
85
86// NOLINTBEGIN(reloco-banned-std-type): std::source_location is the portable C++20 interop type
87// (reloco::call_location_ref is freestanding-only)
88#if MICROFMT_HAS_STD_SOURCE_LOCATION
89template <> struct formatter<std::source_location> {
90 constexpr void parse(format_parse_context &) noexcept {}
91
92 void format(const std::source_location &loc, const sink &out) const noexcept {
93 const formatter<std_source_loc_view> f;
94 f.format(source_loc(loc), out);
95 }
96};
97// NOLINTEND(reloco-banned-std-type)
98#endif
99
100#if MICROFMT_HAS_BOOST_SOURCE_LOCATION
101template <> struct formatter<boost::source_location> {
102 constexpr void parse(format_parse_context &) noexcept {}
103
104 void format(const boost::source_location &loc, const sink &out) const noexcept {
105 const formatter<boost_source_loc_view> f;
106 f.format(source_loc(loc), out);
107 }
108};
109#endif
110
111#endif // MICROFMT_HAS_SOURCE_LOCATION
112
113} // namespace microfmt
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 buffer_sink< N > format(microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1786