96 using from_char_type = from_encoder_type::char_type;
97 using to_char_type = to_encoder_type::char_type;
107 template<
typename OutRange,
typename InRange>
108 [[nodiscard]]
constexpr OutRange
convert(InRange&& src)
const noexcept
115 hilet[size, valid] = _size(cbegin(src), cend(src));
118 if constexpr (From == To and std::is_same_v<InRange, OutRange>) {
120 r = std::forward<InRange>(src);
131 if (From == To and valid) {
137 _convert(cbegin(src), cend(src),
begin(r));
149 template<
typename OutRange,
typename It,
typename EndIt>
150 [[nodiscard]]
constexpr OutRange
convert(It first, EndIt last)
const noexcept
154 hilet[size, valid] = _size(first, last);
161 if (From == To and valid) {
166 _convert(first, last,
begin(r));
179 template<
typename OutRange = std::basic_
string<to_
char_type>>
180 [[nodiscard]] OutRange
read(
void const *ptr,
size_t size, std::endian endian = std::endian::native)
noexcept
184 hilet num_chars = size /
sizeof(from_char_type);
187 if (endian == std::endian::native) {
188 if (floor(ptr,
sizeof(from_char_type)) == ptr) {
189 return convert<OutRange>(
190 reinterpret_cast<from_char_type
const *
>(ptr),
reinterpret_cast<from_char_type
const *
>(ptr) + num_chars);
195 return convert<OutRange>(
std::move(tmp));
201 for (
auto& c : tmp) {
204 return convert<OutRange>(
std::move(tmp));
213 template<
typename InRange>
216 return convert<to_string_type>(std::forward<InRange>(src));
220#if defined(HI_HAS_SSE2)
221 using chunk16_type = __m128i;
223 using chunk16_type = void;
226 constexpr static bool _has_read_ascii_chunk16 =
true;
227 constexpr static bool _has_write_ascii_chunk16 =
true;
229 template<
typename It,
typename EndIt>
230 [[nodiscard]]
constexpr void _size_ascii(It& it, EndIt last,
size_t& count)
const noexcept
232 if (not std::is_constant_evaluated()) {
233#if defined(HI_HAS_SSE2)
234 if constexpr (_has_read_ascii_chunk16 and _has_write_ascii_chunk16) {
236 hilet chunk = from_encoder_type{}.read_ascii_chunk16(it);
237 hilet ascii_mask = _mm_movemask_epi8(chunk);
240 auto partial_count = std::countr_zero(truncate<uint16_t>(ascii_mask));
242 count += partial_count;
253 template<
typename SrcIt,
typename SrcEndIt,
typename DstIt>
254 void _convert_ascii(SrcIt& src, SrcEndIt src_last, DstIt& dst)
const noexcept
256 if (not std::is_constant_evaluated()) {
257#if defined(HI_HAS_SSE2)
258 if constexpr (_has_read_ascii_chunk16 and _has_write_ascii_chunk16) {
260 hilet chunk = from_encoder_type{}.read_ascii_chunk16(src);
261 hilet ascii_mask = _mm_movemask_epi8(chunk);
267 to_encoder_type{}.write_ascii_chunk16(chunk, dst);
276 template<
typename It,
typename EndIt>
284 _size_ascii(it, last, count);
290 hilet[code_point, read_valid] = from_encoder_type{}.read(it, last);
293 hilet[write_count, write_valid] = to_encoder_type{}.size(code_point);
294 count += write_count;
295 valid &= write_valid;
298 return {
count, valid};
301 template<
typename SrcIt,
typename SrcEndIt,
typename DstIt>
302 void _convert(SrcIt src, SrcEndIt src_last, DstIt dst)
const noexcept
307 _convert_ascii(src, src_last, dst);
309 if (src == src_last) {
313 hilet[code_point, from_valid] = from_encoder_type{}.read(src, src_last);
314 to_encoder_type{}.write(code_point, dst);
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hi_assert_not_null(x,...)
Assert if an expression is not nullptr.
Definition assert.hpp:238
constexpr OutRange convert(It first, EndIt last) const noexcept
Convert text between the given encodings.
Definition char_converter.hpp:150
OutRange read(void const *ptr, size_t size, std::endian endian=std::endian::native) noexcept
Read text from a byte array.
Definition char_converter.hpp:180