15#include <daw/algorithms/daw_algorithm_accumulate.h>
16#include <daw/daw_string_view.h>
17#include <daw/daw_traits.h>
18#include <daw/daw_unreachable.h>
27 namespace json_details {
28 struct missing_member {
29 char const *member_name;
31 explicit constexpr missing_member( daw::string_view name )
32 : member_name(
std::data( name ) ) {
33 if( member_name and member_name[0] ==
'\a' ) {
34 member_name =
"no_name";
39 struct missing_token {
42 explicit constexpr missing_token(
char c )
48 enum class ErrorReason {
53 InvalidNumberUnexpectedQuoting,
60 InvalidStringHighASCII,
61 ExpectedKeyValueToStartWithBrace,
62 ExpectedKeyValueArrayToStartWithBracket,
81 ExpectedArrayOrClassStart,
84 AttemptToAccessPastEndOfValue,
85 OutOfOrderOrderedMembers,
86 MissingMemberNameOrEndOfClass,
89 ExpectedMemberNotFound,
90 ExpectedTokenNotFound,
91 UnexpectedJSONVariantType,
93 AttemptToCallOpStarOnConstIterator
96 constexpr std::string_view reason_message( ErrorReason er ) {
97 using namespace std::string_view_literals;
99 case ErrorReason::Unknown:
100 return "Unknown reason for error"sv;
101 case ErrorReason::UnexpectedEndOfData:
102 return "Unexpected end of data"sv;
103 case ErrorReason::InvalidNumber:
104 return "Invalid Number"sv;
105 case ErrorReason::InvalidNumberStart:
106 return R
"(Invalid Number started, expected a "0123456789-")"sv;
107 case ErrorReason::InvalidNumberUnexpectedQuoting:
108 return "Unexpected double quote prior to number"sv;
109 case ErrorReason::InvalidTimestamp:
110 return "Invalid Timestamp"sv;
111 case ErrorReason::InvalidUTFEscape:
112 return "Invalid UTF Escape"sv;
113 case ErrorReason::InvalidUTFCodepoint:
114 return "Invalid UTF Codepoint"sv;
115 case ErrorReason::InvalidEndOfValue:
116 return R
"(Did not find \",}]" at end of value)"sv;
117 case ErrorReason::InvalidLiteral:
118 return "Literal data was corrupt"sv;
119 case ErrorReason::InvalidString:
120 return "Invalid or corrupt string"sv;
121 case ErrorReason::InvalidStringHighASCII:
122 return "String support limited to 0x20 < chr <= 0x7F when "
123 "DisallowHighEightBit or InvalidStringHighASCII is true"sv;
124 case ErrorReason::ExpectedKeyValueToStartWithBrace:
125 return "Expected key/value's JSON type to be of class type and "
128 case ErrorReason::ExpectedKeyValueArrayToStartWithBracket:
129 return "Expected key/value's JSON type to be of array type and "
132 case ErrorReason::InvalidArrayStart:
133 return "Expected array type to begin with '['"sv;
134 case ErrorReason::InvalidClassStart:
135 return "Expected class type to begin with '{'"sv;
136 case ErrorReason::InvalidStartOfValue:
137 return "Unexpected character data at start of value"sv;
138 case ErrorReason::InvalidTrue:
139 return "Expected true not found"sv;
140 case ErrorReason::InvalidFalse:
141 return "Expected false not found"sv;
142 case ErrorReason::InvalidNull:
143 return "Expected null not found"sv;
144 case ErrorReason::UnexpectedNull:
145 return "An unexpected null value was encountered while serializing"sv;
146 case ErrorReason::NumberIsNaN:
147 return "NaN encountered while serializing to JSON Number literal"sv;
148 case ErrorReason::NumberIsInf:
149 return "Infinity encountered while serializing to JSON Number literal"sv;
150 case ErrorReason::NumberOutOfRange:
151 return "Number is outside of the representable range"sv;
152 case ErrorReason::EmptyJSONDocument:
153 return "Attempt to parse an empty JSON document"sv;
154 case ErrorReason::EmptyJSONPath:
155 return "Empty JSON Path specified"sv;
156 case ErrorReason::JSONPathNotFound:
157 return "JSON Path specified not found in document"sv;
158 case ErrorReason::InvalidJSONPath:
159 return "Invalid JSON Path specified"sv;
160 case ErrorReason::NullOutputIterator:
161 return "Null pointer specified for output"sv;
162 case ErrorReason::OutputError:
163 return "General error while performing output"sv;
164 case ErrorReason::MissingMemberNameOrEndOfClass:
165 return "Missing member name or end of class"sv;
166 case ErrorReason::MissingMemberName:
167 return "Missing member name"sv;
168 case ErrorReason::InvalidMemberName:
169 return "Member names must be JSON strings"sv;
170 case ErrorReason::ExpectedArrayOrClassStart:
171 return "Expected start of a JSON class or array"sv;
172 case ErrorReason::UnknownMember:
173 return "Could not find member in JSON class"sv;
174 case ErrorReason::InvalidBracketing:
175 return "Invalid Bracketing"sv;
176 case ErrorReason::AttemptToAccessPastEndOfValue:
177 return "A value of known size was accessed past the end"sv;
178 case ErrorReason::OutOfOrderOrderedMembers:
179 return "Order of ordered members must be ascending"sv;
180 case ErrorReason::MemberNotFound:
181 return "Expected member not found"sv;
182 case ErrorReason::TagMemberNotFound:
183 return "Expected tag member not found, they are required for tagged "
185 case ErrorReason::ExpectedMemberNotFound:
186 return "Expected member missing"sv;
187 case ErrorReason::ExpectedTokenNotFound:
188 return "Expected token missing"sv;
189 case ErrorReason::UnexpectedJSONVariantType:
190 return "Unexpected JSON Variant Type"sv;
191 case ErrorReason::TrailingComma:
192 return "Trailing comma"sv;
193 case ErrorReason::AttemptToCallOpStarOnConstIterator:
194 return "Use of operator*( ) on const iterator";
205 class json_exception :
public std::exception {
206 ErrorReason m_reason = ErrorReason::Unknown;
212 explicit constexpr data_t(
char const *p )
215 explicit constexpr data_t(
char t )
219 char const *m_parse_loc =
nullptr;
222 explicit json_exception( ) =
default;
225 : m_reason( reason ) {}
228 json_exception( json_details::missing_member mm )
229 : m_reason( ErrorReason::MemberNotFound )
230 , m_data( mm.member_name ) {}
233 json_exception( json_details::missing_token mt )
234 : m_reason( ErrorReason::ExpectedTokenNotFound )
235 , m_data( mt.token ) {}
238 json_exception( json_details::missing_member mm,
239 std::string_view location )
240 : m_reason( ErrorReason::MemberNotFound )
241 , m_data( mm.member_name )
242 , m_parse_loc(
std::data( location ) ) {}
245 json_exception( json_details::missing_token mt,
char const *location )
246 : m_reason( ErrorReason::ExpectedTokenNotFound )
248 , m_parse_loc( location ) {}
251 char const *location )
253 , m_parse_loc( location ) {}
261#if defined( DAW_HAS_CLANG )
262#pragma clang diagnostic push
263#pragma clang diagnostic ignored "-Wswitch-enum"
266 case ErrorReason::MemberNotFound: {
267 using namespace std::string_literals;
268 auto result =
"Could not find required class member '"s;
269 result += m_data.pointer;
273 case ErrorReason::ExpectedTokenNotFound: {
274 using namespace std::string_literals;
275 DAW_CPP23_STATIC_LOCAL
constexpr std::string_view m =
276 "Could not find expected parse token '";
277 auto result = std::string( );
278 result.reserve( m.size( ) + 2 );
280 result += m_data.token;
285 return static_cast<std::string
>( ( reason_message( m_reason ) ) );
287#if defined( DAW_HAS_CLANG )
288#pragma clang diagnostic pop
292 DAW_ATTRIB_NOINLINE [[nodiscard]]
constexpr char const *
293 parse_location( )
const {
297 DAW_ATTRIB_INLINE
char const *what( ) const noexcept
override {
299 return reason_message( m_reason ).data( );
302 json_exception( json_exception
const & ) =
default;
303 json_exception( json_exception && ) noexcept = default;
304 ~json_exception( ) override = default;
306 json_exception &operator=( json_exception const & ) = default;
308 json_exception &operator=( json_exception && ) noexcept = default;
317 to_formatted_string( json_exception const &je,
318 char const *json_document =
nullptr ) {
319 using namespace std::string_literals;
320 std::string result =
"reason: "s + je.reason( );
321 if( json_document ==
nullptr or je.parse_location( ) ==
nullptr ) {
324 char const *last_nl =
nullptr;
326 daw::algorithm::accumulate( json_document,
327 je.parse_location( ),
329 [&]( std::size_t count,
char const &c ) {
337 static_cast<std::size_t
>( je.parse_location( ) - last_nl ) + 1U;
338 auto const previous_char_count =
339 (std::min)( {
static_cast<std::size_t
>( 50 ),
340 static_cast<std::size_t
>( std::distance(
341 json_document, je.parse_location( ) + 1 ) ) } );
342 auto const loc_data = std::string_view(
343 std::prev( je.parse_location( ),
344 static_cast<std::ptrdiff_t
>( previous_char_count ) ),
345 previous_char_count + 1 );
346 result +=
" \nlocation: near line: " + std::to_string( line_no ) +
347 " col: " + std::to_string( col_no ) +
"\n\"";
348#if not defined( DAW_JSON_NO_COLOUR )
351 result.reserve( result.size( ) + std::size( loc_data ) );
352 result += daw::algorithm::accumulate( std::data( loc_data ),
353 daw::data_end( loc_data ),
355 []( std::string s,
char c )
356 DAW_CPP23_STATIC_CALL_OP {
361#if defined( DAW_JSON_NO_COLOUR )
372#if not defined( DAW_JSON_NO_COLOUR )
#define DAW_JSON_CPP26_CX_EXCEPT
@ Unknown
Array - An array type where each element is mapped to the member of a C++ class.
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.