DAW JSON Link
Loading...
Searching...
No Matches
daw_json_assert.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
12
14
15#include <daw/daw_attributes.h>
16#include <daw/daw_cpp_feature_check.h>
17#include <daw/daw_likely.h>
18#include <daw/daw_not_null.h>
19#include <daw/daw_static_warn_if.h>
20
21#include <cstddef>
22#include <daw/stdinc/move_fwd_exch.h>
23#include <exception>
24#include <string_view>
25#include <utility>
26
27#if defined( DAW_JSON_SHOW_ERROR_BEFORE_TERMINATE )
28#include <iostream>
29#endif
30
31namespace daw::json {
32#if defined( DAW_USE_EXCEPTIONS )
33 inline constexpr bool use_daw_json_exceptions_v = true;
34#else
35 inline constexpr bool use_daw_json_exceptions_v = false;
36#endif
37
38 inline thread_local void *daw_json_error_handler_data = nullptr;
39
40#if defined( DAW_USE_EXCEPTIONS )
41 [[noreturn, maybe_unused]] DAW_ATTRIB_NOINLINE inline void
42 default_error_handler_throwing( json_exception &&jex, void * ) {
43 throw std::move( jex );
44 }
45#endif
46
47 [[noreturn, maybe_unused]] DAW_ATTRIB_NOINLINE inline void
48 default_error_handler_terminating( json_exception &&jex, void * ) {
49#if defined( DAW_JSON_SHOW_ERROR_BEFORE_TERMINATE )
50 std::cerr << "Error: " << jex.reason( ) << '\n';
51#else
52 (void)jex;
53#endif
54 std::terminate( );
55 }
56
58 daw::not_null<void ( * )( json_exception &&, void * )>;
59
60#if defined( DAW_USE_EXCEPTIONS )
62 default_error_handler_throwing;
63#else
66#endif
67
68 inline namespace DAW_JSON_VER {
69 namespace json_details {
70#if defined( DAW_ATTRIB_ENABLE_IF )
71#if defined( DAW_HAS_CPP26_DELETED_REASON )
72 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
73 handle_error( bool b, json_exception &&jex )
74 DAW_ATTRIB_ENABLE_IF( __builtin_constant_p( b ) and b,
75 "daw_json_ensure check failed" ) =
76 delete( "daw_json_ensure check failed" );
77#endif
78 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
79 handle_error( bool b, json_exception &&jex )
80 DAW_ATTRIB_ENABLE_IF( __builtin_constant_p( b ) and not b,
81 "daw_json_ensure check failed" ) {
82 daw_json_error_handler.get( )( std::move( jex ),
84 DAW_UNREACHABLE( );
85 }
86
87 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
88 handle_error( bool b, json_exception &&jex )
89 DAW_ATTRIB_ENABLE_IF( not __builtin_constant_p( b ), " " ) {
90 daw_json_error_handler.get( )( std::move( jex ),
92 DAW_UNREACHABLE( );
93 }
94#else
95 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
96 handle_error( bool, json_exception &&jex ) {
97 daw_json_error_handler.get( )( std::move( jex ),
99 DAW_UNREACHABLE( );
100 }
101#endif
102 } // namespace json_details
103
104 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
105 daw_json_error( bool b, ErrorReason reason ) {
106 json_details::handle_error( b, json_exception( reason ) );
107 }
108
109 template<typename ParseState>
110 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
111 daw_json_error( bool b, ErrorReason reason, ParseState const &location ) {
112 if( location.first ) {
113 json_details::handle_error( b,
114 json_exception( reason, location.first ) );
115 }
116 if( location.class_first ) {
117 json_details::handle_error(
118 b, json_exception( reason, location.class_first ) );
119 }
120 json_details::handle_error( b, json_exception( reason ) );
121 }
122
123 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
124 daw_json_error( bool b, json_details::missing_member reason ) {
125 json_details::handle_error( b, json_exception( reason ) );
126 }
127
128 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
129 daw_json_error( bool b, json_details::missing_token reason ) {
130 json_details::handle_error( b, json_exception( reason ) );
131 }
132
133 template<typename ParseState>
134 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
135 daw_json_error( bool b, json_details::missing_member reason,
136 ParseState const &location ) {
137 if( location.class_first and location.first ) {
138 static constexpr std::size_t max_len = 150;
139 std::size_t const len = [&]( ) -> std::size_t {
140 if( location.first == nullptr or location.class_first == nullptr ) {
141 if( location.class_first == nullptr or
142 location.class_last == nullptr ) {
143 return 0;
144 }
145 auto const dist = static_cast<std::size_t>( location.class_last -
146 location.class_first );
147 if( dist < max_len ) {
148 return dist;
149 }
150 return max_len;
151 }
152 auto const dist = static_cast<std::size_t>( location.class_first -
153 location.first + 1 );
154 if( dist < max_len ) {
155 return dist;
156 }
157 return max_len;
158 }( );
159 json_details::handle_error(
160 b,
161 json_exception( reason,
162 std::string_view( location.class_first, len ) ) );
163 }
164 json_details::handle_error( b, json_exception( reason ) );
165 }
166
167 template<typename ParseState>
168 [[noreturn]] DAW_ATTRIB_NOINLINE inline void
169 daw_json_error( bool b, json_details::missing_token reason,
170 ParseState const &location ) {
171 if( location.first ) {
172 json_details::handle_error( b,
173 json_exception( reason, location.first ) );
174 }
175 if( location.class_first ) {
176 json_details::handle_error(
177 b, json_exception( reason, location.class_first ) );
178 }
179 json_details::handle_error( b, json_exception( reason ) );
180 }
181 } // namespace DAW_JSON_VER
182} // namespace daw::json
183
186#define daw_json_ensure( Bool, ... ) \
187 do { \
188 if( DAW_UNLIKELY( not( Bool ) ) ) { \
189 daw_static_warn_if( not( Bool ), \
190 "Error handler will always be called: " #Bool ); \
191 daw_json_error( not( Bool ), __VA_ARGS__ ); \
192 } \
193 } while( false )
194
197#if defined( DAW_HAS_IF_CONSTEVAL )
198#define daw_json_assert_weak( Bool, ... ) \
199 do { \
200 if consteval { \
201 if( DAW_UNLIKELY( not( Bool ) ) ) { \
202 daw_json_error( not( Bool ), __VA_ARGS__ ); \
203 } \
204 } else { \
205 if constexpr( not ParseState::is_unchecked_input ) { \
206 if( DAW_UNLIKELY( not( Bool ) ) ) { \
207 daw_static_warn_if( not( Bool ), \
208 "Error handler will always be called: " #Bool ); \
209 daw_json_error( not( Bool ), __VA_ARGS__ ); \
210 } \
211 } \
212 } \
213 } while( false )
214#elif defined( DAW_HAS_IS_CONSTANT_EVALUATED )
215#define daw_json_assert_weak( Bool, ... ) \
216 do { \
217 if( DAW_IS_CONSTANT_EVALUATED( ) ) { \
218 if( DAW_UNLIKELY( not( Bool ) ) ) { \
219 daw_json_error( not( Bool ), __VA_ARGS__ ); \
220 } \
221 } else { \
222 if constexpr( not ParseState::is_unchecked_input ) { \
223 if( DAW_UNLIKELY( not( Bool ) ) ) { \
224 daw_static_warn_if( not( Bool ), \
225 "Error handler will always be called: " #Bool ); \
226 daw_json_error( not( Bool ), __VA_ARGS__ ); \
227 } \
228 } \
229 } \
230 } while( false )
231#else
232#define daw_json_assert_weak( Bool, ... ) \
233 do { \
234 if constexpr( not ParseState::is_unchecked_input ) { \
235 if( DAW_UNLIKELY( not( Bool ) ) ) { \
236 daw_static_warn_if( not( Bool ), \
237 "Error handler will always be called: " #Bool ); \
238 daw_json_error( not( Bool ), __VA_ARGS__ ); \
239 } \
240 } \
241 } while( false )
242#endif
243
244#if defined( DEBUG ) or not defined( NDEBUG )
245#define daw_json_dbg_ensure( Bool, ... ) \
246 do { \
247 if( DAW_UNLIKELY( not( Bool ) ) ) { \
248 daw_static_warn_if( not( Bool ), \
249 "Error handler will always be called: " #Bool ); \
250 daw_json_error( not( Bool ), __VA_ARGS__ ); \
251 } \
252 } while( false )
253
254#else
255#define daw_json_dbg_ensure( ... ) \
256 do { \
257 } while( false )
258#endif
DAW_ATTRIB_NOINLINE void daw_json_error(bool b, ErrorReason reason)
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
daw::not_null< void(*)(json_exception &&, void *)> daw_json_error_handler_t
constexpr bool use_daw_json_exceptions_v
DAW_ATTRIB_NOINLINE void default_error_handler_terminating(json_exception &&jex, void *)
thread_local daw_json_error_handler_t daw_json_error_handler
thread_local void * daw_json_error_handler_data
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20