Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>. |
||
3 | * It is copyright by its individual contributors, as recorded in the |
||
4 | * project's Git history. See COPYING.txt at the top level for license |
||
5 | * terms and a link to the Git history. |
||
6 | */ |
||
7 | |||
8 | #pragma once |
||
9 | |||
10 | #include <type_traits> |
||
11 | #include <utility> |
||
12 | #include "dxxsconf.h" |
||
13 | |||
14 | template <bool capture_source_location = false> |
||
15 | class location_wrapper |
||
16 | { |
||
17 | public: |
||
18 | location_wrapper() = default; |
||
19 | /* Allow callers to pass explicit file/line, for signature |
||
20 | * compatibility with `location_wrapper<true>`. |
||
21 | */ |
||
22 | location_wrapper(const char *, unsigned) |
||
23 | { |
||
24 | } |
||
25 | /* This must be a template to be compatible with the `scratch_buffer` |
||
26 | * template-typedef in `location_wrapper<true>`. |
||
27 | */ |
||
28 | template <std::size_t N> |
||
29 | using scratch_buffer = std::false_type; |
||
30 | template <std::size_t N> |
||
31 | static std::pair<char (&)[N], std::integral_constant<std::size_t, N>> insert_location_leader(char (&buffer)[N]) |
||
32 | { |
||
33 | return {buffer, {}}; |
||
34 | } |
||
35 | /* Define overloads to preserve const qualification */ |
||
36 | static std::pair<char *, std::size_t> prepare_buffer(scratch_buffer<0> &, char *const text, const std::size_t len) |
||
37 | { |
||
38 | return {text, len}; |
||
39 | } |
||
40 | static std::pair<const char *, std::size_t> prepare_buffer(scratch_buffer<0> &, const char *const text, const std::size_t len) |
||
41 | { |
||
42 | return {text, len}; |
||
43 | } |
||
44 | }; |
||
45 | |||
46 | #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE |
||
47 | #include <cstdio> |
||
48 | |||
49 | template <> |
||
50 | class location_wrapper<true> |
||
51 | { |
||
52 | const char *file; |
||
53 | unsigned line; |
||
54 | public: |
||
55 | template <std::size_t N> |
||
56 | using scratch_buffer = char[N]; |
||
57 | location_wrapper(const char *const f = __builtin_FILE(), const unsigned l = __builtin_LINE()) : |
||
58 | file(f), line(l) |
||
59 | { |
||
60 | } |
||
61 | template <std::size_t N> |
||
62 | std::pair<char *, std::size_t> insert_location_leader(char (&buffer)[N]) const |
||
63 | { |
||
64 | const auto written = std::snprintf(buffer, sizeof(buffer), "%s:%u: ", file, line); |
||
65 | return {buffer + written, sizeof(buffer) - written}; |
||
66 | } |
||
67 | template <std::size_t N> |
||
68 | std::pair<const char *, std::size_t> prepare_buffer(char (&buffer)[N], const char *const text, const std::size_t len) const |
||
69 | { |
||
70 | const auto written = std::snprintf(buffer, sizeof(buffer), "%s:%u: %.*s", file, line, static_cast<int>(len), text); |
||
71 | return {buffer, len + written}; |
||
72 | } |
||
73 | /* Delegate to the const-qualified version, but return a `char *` to |
||
74 | * match the non-const input `char *`, to preserve the choice of |
||
75 | * overload for the function to receive this result. |
||
76 | */ |
||
77 | template <std::size_t N> |
||
78 | std::pair<char *, std::size_t> prepare_buffer(char (&buffer)[N], char *const text, const std::size_t len) const |
||
79 | { |
||
80 | return {buffer, prepare_buffer(buffer, const_cast<const char *>(text), len).second}; |
||
81 | } |
||
82 | }; |
||
83 | #endif |
||
84 | |||
85 | template <typename T, bool capture_source_location = false> |
||
86 | class location_value_wrapper : public location_wrapper<capture_source_location> |
||
87 | { |
||
88 | T value; |
||
89 | public: |
||
90 | /* Allow callers to pass explicit file/line, for signature |
||
91 | * compatibility with `location_value_wrapper<T, true>`. |
||
92 | */ |
||
93 | #ifndef DXX_HAVE_CXX_BUILTIN_FILE_LINE |
||
94 | location_value_wrapper(const T &v) : |
||
95 | value(v) |
||
96 | { |
||
97 | } |
||
98 | #endif |
||
99 | location_value_wrapper(const T &v, |
||
100 | const char *const f |
||
101 | #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE |
||
102 | = __builtin_FILE() |
||
103 | #endif |
||
104 | , const unsigned l |
||
105 | #ifdef DXX_HAVE_CXX_BUILTIN_FILE_LINE |
||
106 | = __builtin_LINE() |
||
107 | #endif |
||
108 | ) : |
||
109 | location_wrapper<capture_source_location>(f, l), |
||
110 | value(v) |
||
111 | { |
||
112 | } |
||
113 | operator T() const |
||
114 | { |
||
115 | return value; |
||
116 | } |
||
117 | }; |