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
#pragma once
8
 
9
#include <functional>
10
#include <cstddef>
11
#include "dxxsconf.h"
12
#include "cpp-valptridx.h"
13
 
14
#if defined(DXX_HAVE_CXX_BUILTIN_FILE_LINE)
15
#define DXX_VALPTRIDX_ENABLE_REPORT_FILENAME
16
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS  const char *filename = __builtin_FILE(), const unsigned lineno = __builtin_LINE()
17
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS  , DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS
18
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS  const char *const filename, const unsigned lineno
19
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS  DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS,
20
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_ filename, lineno
21
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_VOID_VARS()        static_cast<void>(filename), static_cast<void>(lineno)
22
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_PASS_VARS  , DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_
23
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS  DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_,
24
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VA(...)       DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_PASS_VARS_, ## __VA_ARGS__
25
#define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS     "rm" (filename), "rm" (lineno)
26
#define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS     DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS,
27
#else
28
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DECL_VARS
29
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS
30
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_DEFN_VARS
31
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS
32
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_N_VOID_VARS()        static_cast<void>(0)
33
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_PASS_VARS
34
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS
35
#define DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VA(...)       __VA_ARGS__
36
#define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_N_VARS
37
#define DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS
38
#endif
39
 
40
template <typename managed_type>
41
class valptridx :
42
        protected valptridx_specialized_types<managed_type>::type
43
{
44
        using specialized_types = typename valptridx_specialized_types<managed_type>::type;
45
        using specialized_types::array_size;
46
        class partial_policy
47
        {
48
        public:
49
                class require_valid;
50
                class allow_invalid;
51
                template <template <typename> class policy>
52
                        class apply_cv_policy;
53
        };
54
        class vc;       /* require_valid + const_policy */
55
        class ic;       /* allow_invalid + const_policy */
56
        class vm;       /* require_valid + mutable_policy */
57
        class im;       /* allow_invalid + mutable_policy */
58
        template <typename>
59
                class guarded;
60
        class array_base_count_type;
61
        using array_base_storage_type = std::array<managed_type, array_size>;
62
protected:
63
        using const_pointer_type = const managed_type *;
64
        using const_reference_type = const managed_type &;
65
        using mutable_pointer_type = managed_type *;
66
        /* integral_type must be a primitive integer type capable of holding
67
         * all legal values used with managed_type.  Legal values are valid
68
         * indexes in array_managed_type and any magic out-of-range values.
69
         */
70
        using typename specialized_types::integral_type;
71
        using index_type = integral_type;       // deprecated; should be dedicated UDT
72
 
73
public:
74
        class array_managed_type;
75
        using typename specialized_types::report_error_uses_exception;
76
        /* ptridx<policy> publicly inherits from idx<policy> and
77
         * ptr<policy>, but should not be implicitly sliced to one of the
78
         * base types.  To prevent slicing, define
79
         * DXX_VALPTRIDX_ENFORCE_STRICT_PI_SEPARATION to a non-zero value.
80
         * When enabled, slicing prevention makes *ptr and *idx derive from
81
         * ptr<policy> / idx<policy>.  When disabled, *ptr and *idx are
82
         * typedef aliases for ptr<policy> / idx<policy>.
83
         */
84
        template <typename policy>
85
                class idx;
86
        template <typename policy>
87
                class ptr;
88
        template <typename policy>
89
                class ptridx;
90
protected:
91
        template <typename Pc, typename Pm>
92
                class basic_ival_member_factory;
93
        template <typename Pc, typename Pm>
94
                class basic_vval_member_factory;
95
        using typename specialized_types::allow_end_construction;
96
        using typename specialized_types::assume_nothrow_index;
97
 
98
        template <typename handle_index_mismatch>
99
        static inline void check_index_match(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, index_type, const array_managed_type &);
100
        template <
101
                typename handle_index_range_error,
102
                template <typename> class Compare = std::less
103
                >
104
        static inline index_type check_index_range(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS index_type, const array_managed_type *);
105
        template <typename handle_index_mismatch, typename handle_index_range_error>
106
        static inline void check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, std::size_t, const array_managed_type &);
107
        template <typename handle_index_mismatch, typename handle_index_range_error>
108
        static inline void check_implicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, const array_managed_type &);
109
        template <typename handle_null_pointer>
110
        static inline void check_null_pointer_conversion(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type);
111
        template <typename handle_null_pointer>
112
        static inline void check_null_pointer(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type, const array_managed_type &);
113
 
114
#define DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX)    \
115
        VERB(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, m);        \
116
        VERB(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, c)
117
 
118
#define DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX)      \
119
        DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, i);  \
120
        DXX_VALPTRIDX_FOR_EACH_VC_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, v)
121
 
122
#define DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
123
        DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, idx)
124
 
125
#define DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
126
        DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, ptr)
127
 
128
#define DXX_VALPTRIDX_FOR_EACH_PTRIDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)    \
129
        DXX_VALPTRIDX_FOR_EACH_IV_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, ptridx)
130
 
131
#define DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)       \
132
        DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT);      \
133
        DXX_VALPTRIDX_FOR_EACH_PTRIDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)
134
 
135
#define DXX_VALPTRIDX_FOR_EACH_IPPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)      \
136
        DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT);      \
137
        DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(VERB, MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT)
138
 
139
        class index_mismatch_exception;
140
        class index_range_exception;
141
        class null_pointer_exception;
142
public:
143
        /* This is a special placeholder that allows segiter to bypass the
144
         * normal rules.  The calling code is responsible for providing the
145
         * safety that is bypassed.  Use this bypass only if you understand
146
         * exactly what you are skipping and why your use is safe despite
147
         * the lack of checking.
148
         */
149
        using typename specialized_types::allow_none_construction;
150
        using typename specialized_types::rebind_policy;
151
        typedef ptridx<ic>      icptridx;
152
        typedef ptridx<im>      imptridx;
153
        typedef ptridx<vc>      vcptridx;
154
        typedef ptridx<vm>      vmptridx;
155
 
156
#define DXX_VALPTRIDX_DECLARE_PI_TYPE(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX) \
157
        using IVPREFIX ## MCPREFIX ## PISUFFIX = typename specialized_types::template wrapper< PISUFFIX < IVPREFIX ## MCPREFIX > >
158
        DXX_VALPTRIDX_FOR_EACH_IDX_TYPE(DXX_VALPTRIDX_DECLARE_PI_TYPE,,,);
159
        DXX_VALPTRIDX_FOR_EACH_PTR_TYPE(DXX_VALPTRIDX_DECLARE_PI_TYPE,,,);
160
#undef DXX_VALPTRIDX_DEFINE_PI_TYPE
161
 
162
#define DXX_VALPTRIDX_MC_qualifier_m
163
#define DXX_VALPTRIDX_MC_qualifier_c    const
164
#define DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)        \
165
        using f ## IVPREFIX ## MCPREFIX ## PISUFFIX =   \
166
        DXX_VALPTRIDX_MC_qualifier_ ## MCPREFIX \
167
        basic_ ## IVPREFIX ## val_member_factory<       \
168
                IVPREFIX ## c ## PISUFFIX,      \
169
                IVPREFIX ## m ## PISUFFIX       \
170
        >
171
        DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES,,,);
172
#undef DXX_VALPTRIDX_DECLARE_MEMBER_FACTORIES
173
#undef DXX_VALPTRIDX_MC_qualifier_c
174
#undef DXX_VALPTRIDX_MC_qualifier_m
175
 
176
        /* Commit a DRY violation here so that tools can easily find these
177
         * types.  Strict DRY compliance would mean using a macro to
178
         * generate the `using` line, since the typedef, the dispatcher type
179
         * it references, and an argument to that type are all dependent on
180
         * the same string.
181
         */
182
        template <typename T>
183
                using index_mismatch_error_type = typename specialized_types::template dispatch_index_mismatch_error<T, index_mismatch_exception>;
184
        template <typename T>
185
                using index_range_error_type = typename specialized_types::template dispatch_index_range_error<T, index_range_exception>;
186
        template <typename T>
187
                using null_pointer_error_type = typename specialized_types::template dispatch_null_pointer_error<T, null_pointer_exception>;
188
 
189
        template <integral_type constant>
190
                class magic_constant
191
                {
192
                public:
193
                        constexpr operator integral_type() const { return constant; }   // integral_type conversion deprecated
194
                };
195
};
196
 
197
#define DXX_VALPTRIDX_DEFINE_FACTORY_TYPEDEF(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)  \
198
        using f ## IVPREFIX ## MCPREFIX ## DERIVED_TYPE_PREFIX ## PISUFFIX = valptridx<MANAGED_TYPE>::f ## IVPREFIX ## MCPREFIX ## PISUFFIX
199
 
200
#define DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEF(MANAGED_TYPE, DERIVED_TYPE_PREFIX, CONTEXT, PISUFFIX, IVPREFIX, MCPREFIX)  \
201
        using IVPREFIX ## MCPREFIX ## DERIVED_TYPE_PREFIX ## PISUFFIX ## _t = valptridx<MANAGED_TYPE>::IVPREFIX ## MCPREFIX ## PISUFFIX
202
 
203
#define DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEFS(MANAGED_TYPE, DERIVED_TYPE_PREFIX)        \
204
        using MANAGED_TYPE ## _array = valptridx<MANAGED_TYPE>::array_managed_type;     \
205
        DXX_VALPTRIDX_FOR_EACH_PPI_TYPE(DXX_VALPTRIDX_DEFINE_FACTORY_TYPEDEF, MANAGED_TYPE, DERIVED_TYPE_PREFIX,);      \
206
        DXX_VALPTRIDX_FOR_EACH_IPPI_TYPE(DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEF, MANAGED_TYPE, DERIVED_TYPE_PREFIX,)