79 using from_char_type = from_encoder_type::char_type;
80 using to_char_type = to_encoder_type::char_type;
84 template<
typename OutRange,
typename InRange>
85 [[nodiscard]]
constexpr OutRange convert(InRange&& src)
const noexcept
92 hilet[size, valid] = _size(cbegin(src), cend(src));
95 if constexpr (From == To and std::is_same_v<InRange, OutRange>) {
97 r = std::forward<InRange>(src);
108 if (From == To and valid) {
114 _convert(cbegin(src), cend(src), begin(r));
119 template<
typename OutRange,
typename It,
typename EndIt>
120 [[nodiscard]]
constexpr OutRange convert(It first, EndIt last)
const noexcept
124 hilet[size, valid] = _size(first, last);
131 if (From == To and valid) {
136 _convert(first, last, begin(r));
141 template<
typename OutRange = std::basic_
string<to_
char_type>>
142 [[nodiscard]] OutRange read(
void const *ptr,
size_t size, std::endian endian = std::endian::native)
noexcept
144 hi_axiom(ptr !=
nullptr);
146 hilet num_chars = size /
sizeof(from_char_type);
149 if (endian == std::endian::native) {
150 if (floor(ptr,
sizeof(from_char_type)) == ptr) {
151 return convert<OutRange>(
152 reinterpret_cast<from_char_type
const *
>(ptr),
reinterpret_cast<from_char_type
const *
>(ptr) + num_chars);
157 return convert<OutRange>(
std::move(tmp));
166 return convert<OutRange>(
std::move(tmp));
170 template<
typename InRange>
171 [[nodiscard]]
constexpr to_string_type operator()(InRange&& src)
const noexcept
173 return convert<to_string_type>(std::forward<InRange>(src));
177#if defined(HI_HAS_SSE2)
178 using chunk16_type = __m128i;
180 using chunk16_type = void;
183 constexpr static bool _has_read_ascii_chunk16 =
true;
184 constexpr static bool _has_write_ascii_chunk16 =
true;
186 template<
typename It,
typename EndIt>
187 [[nodiscard]]
constexpr void _size_ascii(It& it, EndIt last,
size_t& count)
const noexcept
189 if (not std::is_constant_evaluated()) {
190#if defined(HI_HAS_SSE2)
191 if constexpr (_has_read_ascii_chunk16 and _has_write_ascii_chunk16) {
194 hilet ascii_mask = _mm_movemask_epi8(chunk);
197 auto partial_count = std::countr_zero(truncate<uint16_t>(ascii_mask));
199 count += partial_count;
210 template<
typename SrcIt,
typename SrcEndIt,
typename DstIt>
211 void _convert_ascii(SrcIt& src, SrcEndIt src_last, DstIt& dst)
const noexcept
213 if (not std::is_constant_evaluated()) {
214#if defined(HI_HAS_SSE2)
215 if constexpr (_has_read_ascii_chunk16 and _has_write_ascii_chunk16) {
218 hilet ascii_mask = _mm_movemask_epi8(chunk);
233 template<
typename It,
typename EndIt>
241 _size_ascii(it, last, count);
251 count += write_count;
252 valid &= write_valid;
255 return {count, valid};
258 template<
typename SrcIt,
typename SrcEndIt,
typename DstIt>
259 void _convert(SrcIt src, SrcEndIt src_last, DstIt dst)
const noexcept
264 _convert_ascii(src, src_last, dst);
266 if (src == src_last) {