Subversion Repositories Games.Descent

Rev

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
};