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,) |