/work/include/simdutf/error.h
Line | Count | Source |
1 | | #ifndef SIMDUTF_ERROR_H |
2 | | #define SIMDUTF_ERROR_H |
3 | | #include <string_view> |
4 | | |
5 | | namespace simdutf { |
6 | | |
7 | | enum error_code { |
8 | | SUCCESS = 0, |
9 | | HEADER_BITS, // Any byte must have fewer than 5 header bits. |
10 | | TOO_SHORT, // The leading byte must be followed by N-1 continuation bytes, |
11 | | // where N is the UTF-8 character length This is also the error |
12 | | // when the input is truncated. |
13 | | TOO_LONG, // We either have too many consecutive continuation bytes or the |
14 | | // string starts with a continuation byte. |
15 | | OVERLONG, // The decoded character must be above U+7F for two-byte characters, |
16 | | // U+7FF for three-byte characters, and U+FFFF for four-byte |
17 | | // characters. |
18 | | TOO_LARGE, // The decoded character must be less than or equal to |
19 | | // U+10FFFF,less than or equal than U+7F for ASCII OR less than |
20 | | // equal than U+FF for Latin1 |
21 | | SURROGATE, // The decoded character must be not be in U+D800...DFFF (UTF-8 or |
22 | | // UTF-32) |
23 | | // OR |
24 | | // a high surrogate must be followed by a low surrogate |
25 | | // and a low surrogate must be preceded by a high surrogate |
26 | | // (UTF-16) |
27 | | // OR |
28 | | // there must be no surrogate at all and one is |
29 | | // found (Latin1 functions) |
30 | | // OR |
31 | | // *specifically* for the function |
32 | | // utf8_length_from_utf16_with_replacement, a surrogate (whether |
33 | | // in error or not) has been found (I.e., whether we are in the |
34 | | // Basic Multilingual Plane or not). |
35 | | INVALID_BASE64_CHARACTER, // Found a character that cannot be part of a valid |
36 | | // base64 string. This may include a misplaced |
37 | | // padding character ('='). |
38 | | BASE64_INPUT_REMAINDER, // The base64 input terminates with a single |
39 | | // character, excluding padding (=). It is also used |
40 | | // in strict mode when padding is not adequate. |
41 | | BASE64_EXTRA_BITS, // The base64 input terminates with non-zero |
42 | | // padding bits. |
43 | | OUTPUT_BUFFER_TOO_SMALL, // The provided buffer is too small. |
44 | | OTHER // Not related to validation/transcoding. |
45 | | }; |
46 | | |
47 | 0 | inline std::string_view error_to_string(error_code code) noexcept { |
48 | 0 | switch (code) { |
49 | 0 | case SUCCESS: |
50 | 0 | return "SUCCESS"; |
51 | 0 | case HEADER_BITS: |
52 | 0 | return "HEADER_BITS"; |
53 | 0 | case TOO_SHORT: |
54 | 0 | return "TOO_SHORT"; |
55 | 0 | case TOO_LONG: |
56 | 0 | return "TOO_LONG"; |
57 | 0 | case OVERLONG: |
58 | 0 | return "OVERLONG"; |
59 | 0 | case TOO_LARGE: |
60 | 0 | return "TOO_LARGE"; |
61 | 0 | case SURROGATE: |
62 | 0 | return "SURROGATE"; |
63 | 0 | case INVALID_BASE64_CHARACTER: |
64 | 0 | return "INVALID_BASE64_CHARACTER"; |
65 | 0 | case BASE64_INPUT_REMAINDER: |
66 | 0 | return "BASE64_INPUT_REMAINDER"; |
67 | 0 | case BASE64_EXTRA_BITS: |
68 | 0 | return "BASE64_EXTRA_BITS"; |
69 | 0 | case OUTPUT_BUFFER_TOO_SMALL: |
70 | 0 | return "OUTPUT_BUFFER_TOO_SMALL"; |
71 | 0 | default: |
72 | 0 | return "OTHER"; |
73 | 0 | } |
74 | 0 | } |
75 | | |
76 | | struct result { |
77 | | error_code error; |
78 | | size_t count; // In case of error, indicates the position of the error. In |
79 | | // case of success, indicates the number of code units |
80 | | // validated/written. |
81 | | |
82 | | simdutf_really_inline simdutf_constexpr23 result() noexcept |
83 | 13.6k | : error{error_code::SUCCESS}, count{0} {} |
84 | | |
85 | | simdutf_really_inline simdutf_constexpr23 result(error_code err, |
86 | | size_t pos) noexcept |
87 | | : error{err}, count{pos} {} |
88 | | |
89 | 0 | simdutf_really_inline simdutf_constexpr23 bool is_ok() const noexcept { |
90 | 0 | return error == error_code::SUCCESS; |
91 | 0 | } |
92 | | |
93 | | simdutf_really_inline simdutf_constexpr23 bool is_err() const noexcept { |
94 | | return error != error_code::SUCCESS; |
95 | | } |
96 | | }; |
97 | | |
98 | | struct full_result { |
99 | | error_code error; |
100 | | size_t input_count; |
101 | | size_t output_count; |
102 | | bool padding_error = false; // true if the error is due to padding, only |
103 | | // meaningful when error is not SUCCESS |
104 | | |
105 | | simdutf_really_inline simdutf_constexpr23 full_result() noexcept |
106 | | : error{error_code::SUCCESS}, input_count{0}, output_count{0} {} |
107 | | |
108 | | simdutf_really_inline simdutf_constexpr23 full_result(error_code err, |
109 | | size_t pos_in, |
110 | | size_t pos_out) noexcept |
111 | | : error{err}, input_count{pos_in}, output_count{pos_out} {} |
112 | | simdutf_really_inline simdutf_constexpr23 full_result( |
113 | | error_code err, size_t pos_in, size_t pos_out, bool padding_err) noexcept |
114 | | : error{err}, input_count{pos_in}, output_count{pos_out}, |
115 | | padding_error{padding_err} {} |
116 | | |
117 | | simdutf_really_inline simdutf_constexpr23 operator result() const noexcept { |
118 | | if (error == error_code::SUCCESS) { |
119 | | return result{error, output_count}; |
120 | | } else { |
121 | | return result{error, input_count}; |
122 | | } |
123 | | } |
124 | | }; |
125 | | |
126 | | struct utf8_result { |
127 | | error_code error; |
128 | | size_t input_count; |
129 | | size_t continuation_count; |
130 | | size_t four_byte_count; |
131 | | |
132 | | simdutf_really_inline simdutf_constexpr23 utf8_result() noexcept |
133 | | : error{error_code::SUCCESS}, input_count{0}, continuation_count{0}, |
134 | 0 | four_byte_count{0} {} |
135 | | |
136 | | simdutf_really_inline simdutf_constexpr23 |
137 | | utf8_result(error_code err, size_t pos_in, size_t continuation_count_, |
138 | | size_t four_byte_count_) noexcept |
139 | | : error{err}, input_count{pos_in}, |
140 | | continuation_count{continuation_count_}, |
141 | | four_byte_count{four_byte_count_} {} |
142 | | |
143 | | simdutf_really_inline simdutf_constexpr23 size_t |
144 | | utf16_length() const noexcept { |
145 | | return input_count - continuation_count + four_byte_count; |
146 | | } |
147 | | |
148 | | // The number of code points in the valid prefix, which is also the number of |
149 | | // UTF-32 code units. |
150 | | simdutf_really_inline simdutf_constexpr23 size_t |
151 | 0 | utf32_length() const noexcept { |
152 | 0 | return input_count - continuation_count; |
153 | 0 | } |
154 | | }; |
155 | | |
156 | | // UTF-16 size of a possibly ill-formed UTF-8 string, plus the first few |
157 | | // ill-formed subsequences. Pass this to convert_utf8_to_utf16_with_replacement |
158 | | // on the same bytes. error_offset entries are byte indexes from the start of |
159 | | // that input. count is always the full number of char16_t. more_errors is |
160 | | // true when the input has ill-formed subsequences past the stored ones. |
161 | | struct utf8_to_utf16_result { |
162 | | static constexpr size_t max_errors = 16; |
163 | | error_code error; |
164 | | size_t count; |
165 | | size_t error_count; |
166 | | bool more_errors; |
167 | | size_t error_offset[max_errors]; |
168 | | |
169 | | simdutf_really_inline simdutf_constexpr23 utf8_to_utf16_result() noexcept |
170 | | : error{error_code::SUCCESS}, count{0}, error_count{0}, |
171 | | more_errors{false}, error_offset{} {} |
172 | | }; |
173 | | |
174 | | } // namespace simdutf |
175 | | #endif |