OGLplus  (0.59.0) a C++ wrapper for rendering APIs

multi_byte_seq.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_MULTI_BYTE_SEQ_HPP
10 #define EAGINE_MULTI_BYTE_SEQ_HPP
11 
12 #include "span.hpp"
13 #include "string_span.hpp"
14 #include "types.hpp"
15 #include "valid_if/always.hpp"
16 #include "valid_if/between.hpp"
17 #include "valid_if/le_size_ge0.hpp"
18 #include "valid_if/less_than.hpp"
19 #include "valid_if/not_empty.hpp"
20 #include "valid_if/not_zero.hpp"
21 #include "valid_if/size_gt.hpp"
22 #include <cstdint>
23 #include <string>
24 
25 namespace eagine {
26 namespace mbs {
27 //------------------------------------------------------------------------------
28 using code_point_t = std::uint32_t;
29 static constexpr code_point_t invalid_code_point = 0x7FFFFFFFU;
30 using code_point = valid_if_less_than<code_point_t, 0x7FFFFFFFU>;
31 //------------------------------------------------------------------------------
32 using valid_sequence_length = valid_if_between<span_size_t, 1, 6>;
33 using valid_byte_span = valid_if_size_gt<span<byte>, span_size_t>;
34 //------------------------------------------------------------------------------
35 static inline auto make_byte_span(span<byte> s) noexcept -> valid_byte_span {
36  return {s};
37 }
38 //------------------------------------------------------------------------------
39 static inline auto make_byte_span(span<char> s) noexcept -> valid_byte_span {
40  return {memory::accomodate<byte>(s)};
41 }
42 //------------------------------------------------------------------------------
43 using valid_cbyte_span = valid_if_size_gt<span<const byte>, span_size_t>;
44 //------------------------------------------------------------------------------
45 static inline auto make_cbyte_span(span<const byte> s) noexcept
46  -> valid_cbyte_span {
47  return {s};
48 }
49 //------------------------------------------------------------------------------
50 static inline auto make_cbyte_span(span<const char> s) noexcept
51  -> valid_cbyte_span {
52  return {memory::accomodate<const byte>(s)};
53 }
54 //------------------------------------------------------------------------------
55 static constexpr auto max_code_point(const valid_sequence_length& len) noexcept
56  -> valid_if_not_zero<code_point_t> {
57  return len == 1 ? 0x0000007F : // 7b
58  len == 2 ? 0x000007FF : // 11b
59  len == 3 ? 0x0000FFFF : // 16b
60  len == 4 ? 0x001FFFFF : // 21b
61  len == 5 ? 0x03FFFFFF : // 26b
62  len == 6 ? 0x7FFFFFFF : // 31b
63  0x00000000;
64 }
65 //------------------------------------------------------------------------------
66 static constexpr auto head_data_bitshift(
67  const valid_sequence_length& len) noexcept -> valid_span_size {
68  return {len.is_valid() ? (extract(len) - 1) * 6 : -1};
69 }
70 //------------------------------------------------------------------------------
71 static constexpr auto tail_data_bitshift(
72  const valid_sequence_length& idx,
73  const valid_sequence_length& len) noexcept -> valid_span_size {
74  return {
75  (idx.is_valid() && len.is_valid()) ? (extract(len) - extract(idx) - 1) * 6
76  : -1};
77 }
78 //------------------------------------------------------------------------------
79 static constexpr auto head_code_mask(const valid_sequence_length& len) noexcept
80  -> valid_if_not_zero<byte> {
81  return len == 1
82  ? 0x80
83  : len == 2
84  ? 0xE0
85  : len == 3
86  ? 0xF0
87  : len == 4 ? 0xF8
88  : len == 5 ? 0xFC : len == 6 ? 0xFE : 0x00;
89 }
90 //------------------------------------------------------------------------------
91 template <typename P>
92 static constexpr auto inverted_byte(const valid_if<byte, P> b) noexcept
93  -> optionally_valid<byte> {
94  return {byte(~b.value_anyway()), b.is_valid()};
95 }
96 //------------------------------------------------------------------------------
97 static constexpr auto head_data_mask(const valid_sequence_length& len) noexcept
98  -> optionally_valid<byte> {
99  return inverted_byte(head_code_mask(len));
100 }
101 //------------------------------------------------------------------------------
102 static constexpr auto tail_code_mask() noexcept -> always_valid<byte> {
103  return 0xC0;
104 }
105 //------------------------------------------------------------------------------
106 static constexpr auto tail_data_mask() noexcept -> always_valid<byte> {
107  return 0x3F;
108 }
109 //------------------------------------------------------------------------------
110 template <typename P>
111 static constexpr auto head_code_from_mask(const valid_if<byte, P> mask) noexcept
112  -> optionally_valid<byte> {
113  // NOLINTNEXTLINE(hicpp-signed-bitwise)
114  return {byte((mask.value_anyway() << 1) & 0xFF), mask.is_valid()};
115 }
116 //------------------------------------------------------------------------------
117 static constexpr auto head_code(const valid_sequence_length& len) noexcept
118  -> optionally_valid<byte> {
119  return head_code_from_mask(head_code_mask(len));
120 }
121 //------------------------------------------------------------------------------
122 static constexpr auto tail_code() noexcept -> always_valid<byte> {
123  return 0x80;
124 }
125 //------------------------------------------------------------------------------
126 template <typename P1, typename P2>
127 static constexpr auto is_valid_masked_code(
128  const byte b,
129  const valid_if<byte, P1> mask,
130  const valid_if<byte, P2> code) noexcept -> bool {
131  return (mask.is_valid() && code.is_valid())
132  ? (b & extract(mask)) == extract(code)
133  : false;
134 }
135 //------------------------------------------------------------------------------
136 static constexpr auto
137 is_valid_head_byte(const byte b, const valid_sequence_length& l) noexcept
138  -> bool {
139  return is_valid_masked_code(b, head_code_mask(l), head_code(l));
140 }
141 //------------------------------------------------------------------------------
142 static constexpr auto is_valid_head_byte(const byte b) noexcept -> bool {
143  return is_valid_head_byte(b, 1) || is_valid_head_byte(b, 2) ||
144  is_valid_head_byte(b, 3) || is_valid_head_byte(b, 4) ||
145  is_valid_head_byte(b, 5) || is_valid_head_byte(b, 6);
146 }
147 //------------------------------------------------------------------------------
148 static constexpr auto is_valid_tail_byte(
149  const byte b,
150  const valid_sequence_length&,
151  const valid_sequence_length&) noexcept -> bool {
152  return is_valid_masked_code(b, tail_code_mask(), tail_code());
153 }
154 //------------------------------------------------------------------------------
155 static constexpr auto required_sequence_length(const code_point_t cp) noexcept
156  -> valid_sequence_length {
157  return (max_code_point(1) > cp)
158  ? 1
159  : (max_code_point(2) > cp)
160  ? 2
161  : (max_code_point(3) > cp)
162  ? 3
163  : (max_code_point(4) > cp)
164  ? 4
165  : (max_code_point(5) > cp)
166  ? 5
167  : (max_code_point(6) > cp) ? 6 : 0;
168 }
169 //------------------------------------------------------------------------------
170 auto do_decode_sequence_length(const byte b) noexcept -> valid_sequence_length;
171 //------------------------------------------------------------------------------
172 static inline auto decode_sequence_length(const valid_cbyte_span& seq) noexcept
173  -> valid_sequence_length {
174  return do_decode_sequence_length(byte(seq.value(0)[0]));
175 }
176 //------------------------------------------------------------------------------
177 auto is_valid_encoding(const valid_cbyte_span& vseq) noexcept -> bool;
178 //------------------------------------------------------------------------------
179 auto do_decode_code_point(
180  const valid_cbyte_span& vsrc,
181  const valid_sequence_length& vl) noexcept -> code_point;
182 //------------------------------------------------------------------------------
183 static inline auto decode_code_point(const valid_cbyte_span& src) noexcept
184  -> code_point {
185  return do_decode_code_point(src, decode_sequence_length(src));
186 }
187 //------------------------------------------------------------------------------
188 auto do_encode_code_point(
189  const code_point& cp,
190  const valid_byte_span& vdest,
191  const valid_sequence_length& vl) noexcept -> bool;
192 //------------------------------------------------------------------------------
193 auto encode_code_point(
194  const code_point& cp,
195  const valid_byte_span& dest) noexcept -> valid_sequence_length;
196 //------------------------------------------------------------------------------
197 auto encode_code_point(const code_point& cp) -> valid_if_not_empty<std::string>;
198 //------------------------------------------------------------------------------
199 auto encoding_bytes_required(span<const code_point_t> cps) noexcept
200  -> optionally_valid<span_size_t>;
201 //------------------------------------------------------------------------------
202 auto encoding_bytes_required(span<const code_point> cps) noexcept
203  -> optionally_valid<span_size_t>;
204 //------------------------------------------------------------------------------
205 auto decoding_code_points_required(const valid_cbyte_span& bytes) noexcept
206  -> optionally_valid<span_size_t>;
207 //------------------------------------------------------------------------------
208 auto encode_code_points(
209  span<const code_point> cps,
210  const valid_byte_span& bytes) noexcept -> bool;
211 //------------------------------------------------------------------------------
212 auto decode_code_points(const valid_cbyte_span& bytes, span<code_point> cps)
213  -> bool;
214 //------------------------------------------------------------------------------
215 } // namespace mbs
216 } // namespace eagine
217 
218 #include <eagine/multi_byte_seq.inl>
219 
220 #endif // EAGINE_MULTI_BYTE_SEQ_HPP
std::ptrdiff_t span_size_t
Signed span size type used by eagine.
Definition: types.hpp:36
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
unsigned char byte
Byte type alias.
Definition: types.hpp:24
valid_if< T, always_valid_policy > always_valid
Specialization of valid_if, for always valid values.
Definition: always.hpp:39
valid_if_nonnegative< span_size_t > valid_span_size
Valid size type.
Definition: types.hpp:40

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).