DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_policy_policy_details.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
11#include "version.h"
12
13#include "daw_json_assert.h"
14
15#include <daw/daw_attributes.h>
16#include <type_traits>
17
18namespace daw::json {
19 inline namespace DAW_JSON_VER {
20 namespace json_details {
21 // Translate a read-only scanner result back into the input range's
22 // pointer type. Non-null positions must belong to the same buffer.
23 template<typename Char>
24 [[nodiscard]] constexpr Char *input_pointer( Char *origin, char const *position ) {
25 if constexpr( std::is_const_v<Char> ) {
26 return position;
27 } else {
28 return position ? origin + ( position - origin ) : nullptr;
29 }
30 }
31
32 enum class SkipBracketedType { Array, Class };
33 } // namespace json_details
34
35 namespace parse_policy_details {
36 template<char... keys>
37 [[nodiscard]] DAW_ATTRIB_FLATINLINE static constexpr bool in( char c ) {
38 auto const eq = [c]( char k ) {
39 return c == k;
40 };
41 return nsc_or( eq( keys )... );
42 }
43
44 [[nodiscard]] DAW_ATTRIB_FLATINLINE static constexpr bool
45 at_end_of_item( char c ) {
46 return static_cast<bool>( static_cast<unsigned>( c == ',' ) |
47 static_cast<unsigned>( c == '}' ) |
48 static_cast<unsigned>( c == ']' ) |
49 static_cast<unsigned>( c == ':' ) |
50 static_cast<unsigned>( c <= 0x20 ) );
51 }
52
53 [[nodiscard]] DAW_ATTRIB_FLATINLINE static inline constexpr bool
54 is_number( char c ) {
55 return static_cast<unsigned>( static_cast<unsigned char>( c ) -
56 static_cast<unsigned char>( '0' ) ) < 10U;
57 }
58
59 template<typename ParseState>
60 DAW_ATTRIB_FLATINLINE static inline constexpr void
61 validate_unsigned_first( ParseState const &parse_state ) {
62 if constexpr( not ParseState::is_unchecked_input ) {
63 switch( parse_state.front( ) ) {
64 case '1':
65 case '2':
66 case '3':
67 case '4':
68 case '5':
69 case '6':
70 case '7':
71 case '8':
72 case '9':
73 return;
74 case '0':
75 if( parse_state.size( ) > 1 ) {
76 daw_json_ensure( is_number( *( parse_state.first + 1 ) ),
77 ErrorReason::InvalidNumberStart,
78 parse_state );
79 }
80 return;
81 default:
82 daw_json_error( true, ErrorReason::InvalidNumberStart, parse_state );
83 }
84 }
85 }
86
87 /***
88 * Validate that this is a valid number start, an optional '-' then
89 * 1-9 or a 0 that is not followed by a digit. When checked, callers
90 * can rely on at least one whole digit and no leading zero
91 * @return sign value
92 */
93 template<typename ParseState>
94 [[nodiscard]] DAW_ATTRIB_FLATINLINE static constexpr int
95 validate_signed_first( ParseState &parse_state ) {
96 daw_json_assert_weak( parse_state.has_more( ),
97 ErrorReason::UnexpectedEndOfData,
98 parse_state );
99 if constexpr( ParseState::is_unchecked_input ) {
100 auto const c = parse_state.front( );
101 if( c == '-' ) {
102 parse_state.remove_prefix( );
103 return -1;
104 }
105 if( DAW_LIKELY( c >= '0' ) and DAW_LIKELY( c <= '9' ) ) {
106 return 1;
107 }
108 } else {
109 int sign = 1;
110 if( parse_state.front( ) == '-' ) {
111 parse_state.remove_prefix( );
112 sign = -1;
113 // A digit must follow, e.g. "-" and "-.5" are invalid
114 daw_json_assert_weak( ( ParseState::is_zero_terminated_string or
115 parse_state.has_more( ) ) and
116 is_number( parse_state.front( ) ),
117 ErrorReason::InvalidNumber,
118 parse_state );
119 }
120 auto const c = parse_state.front( );
121 if( c >= '1' and c <= '9' ) {
122 return sign;
123 }
124 if( DAW_LIKELY( c == '0' ) ) {
125 if( parse_state.size( ) > 1 ) {
126 auto const next_dig = static_cast<unsigned>(
127 static_cast<unsigned char>( *( parse_state.first + 1 ) ) );
128 auto const tst = next_dig - static_cast<unsigned char>( '0' );
129 // Cannot be a digit
131 tst >= 10U, ErrorReason::InvalidNumberStart, parse_state );
132 }
133 return sign;
134 }
135 }
136 daw_json_error( true, ErrorReason::InvalidNumberStart, parse_state );
137 }
138
139 [[nodiscard]] DAW_ATTRIB_FLATINLINE static constexpr bool
140 is_number_start( char c ) {
141 switch( c ) {
142 case '0': // TODO: CONFORMANCE We are accepting starting with zero for
143 // now
144 case '1':
145 case '2':
146 case '3':
147 case '4':
148 case '5':
149 case '6':
150 case '7':
151 case '8':
152 case '9':
153 case '-':
154 return true;
155 }
156 return false;
157 }
158 } // namespace parse_policy_details
159 } // namespace DAW_JSON_VER
160} // namespace daw::json
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
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,...
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20