19#ifndef MTSTD_ENCODINGS_HPP
20#define MTSTD_ENCODINGS_HPP
39 constexpr char32_t bom = 0xFEFF;
45 constexpr auto is_bom(
const char32_t ch) {
return ch ==
bom; }
57 template<std::endian target,
typename T =
char32_t>
103 template<
typename T,
size_t MaxLen>
107 std::array<Elem, MaxLen> elems;
109 [[nodiscard]]
size_t size()
const {
114 T &operator[](
size_t i) {
115 ensure(i <= MaxLen,
"out of bounds");
116 ensure(
static_cast<int>(i) < len,
"out of bounds");
120 const T &operator[](
size_t i)
const {
121 ensure(i <= MaxLen,
"out of bounds");
122 ensure(
static_cast<int>(i) < len,
"out of bounds");
126 [[nodiscard]] T &at(
size_t i)
noexcept {
return (*
this)[i]; }
127 [[nodiscard]]
constexpr const T &at(
size_t i)
const noexcept {
return (*
this)[i]; }
129 [[nodiscard]]
decltype(
auto) ptr_iter()
noexcept {
return iter::ptr(*
this); }
130 [[nodiscard]]
decltype(
auto) ptr_iter()
const noexcept {
return iter::const_ptr(*
this); }
131 [[nodiscard]]
decltype(
auto) iter()
const noexcept {
return iter::val(*
this); }
136 using U8Seq = impl::ShortSeq<char8_t, 4>;
137 using U16Seq = impl::ShortSeq<char16_t, 2>;
143 constexpr bool is_surrogate(
char16_t ch) {
return ch >= 0xD800 && ch <= 0xDFFF; }
157 template<std::endian E = std::endian::native>
158 constexpr auto oppositeEndian = E == std::endian::big ? std::endian::little : std::endian::big;
172 template<
class T, std::endian Endian = std::endian::native>
174 static_assert(std::is_same_v<T, const char16_t> || std::is_same_v<T, char16_t> ||
175 std::is_same_v<T, const char32_t> || std::is_same_v<T, char32_t>);
183 [[nodiscard]]
decltype(
auto)
iter()
const noexcept {
return iter::val(*
this); }
187 return {
static_cast<std::add_pointer_t<std::add_const_t<T>
>>(
head),
len};
215 constexpr operator T()
const {
return as_endian(std::endian::native); }
217 [[nodiscard]]
constexpr auto native()
const {
return as_endian(std::endian::native); }
223 [[nodiscard]]
constexpr T
as_endian(std::endian viewAs)
const {
227 if (viewAs != Endian) {
246 constexpr operator T()
const {
return as_endian(std::endian::native); }
259 [[nodiscard]]
constexpr T
as_endian(std::endian viewAs)
const {
263 if (viewAs != Endian) {
277 if (setAs != Endian) {
290 [[nodiscard]]
constexpr ConstEndianWrapper
operator[](
size_t i)
const noexcept {
291 ensure(i <
len,
"SLICE ACCESS OUT OF BOUNDS");
293 return ConstEndianWrapper{*
this, i};
302 ensure(i <
len,
"SLICE ACCESS OUT OF BOUNDS");
304 return EndianWrapper{*
this, i};
312 EndianWrapper
at(
size_t i)
noexcept {
return (*
this)[i]; }
319 [[nodiscard]]
constexpr ConstEndianWrapper
at(
size_t i)
const noexcept {
return (*
this)[i]; }
324 [[nodiscard]]
constexpr size_t size() const noexcept {
return head !=
nullptr ?
len : 0; }
329 [[nodiscard]]
constexpr bool empty() const noexcept {
return head ==
nullptr ||
len == 0; }
338 res.
init(
nullptr, 0);
354 auto res =
sub(start);
355 res.len = res.len >
len ?
len : res.len;
365 template<std::endian E>
367 return *this <=> other.to_const();
375 template<std::endian E>
379 return std::strong_ordering::less;
381 return std::strong_ordering::equal;
384 for (
size_t i = 0; i <
len && i < other.len; ++i) {
385 auto tv = (*this)[i].native();
386 auto ov = other[i].native();
388 return std::strong_ordering::greater;
391 return std::strong_ordering::less;
395 if (
len == other.len) {
396 return std::strong_ordering::equal;
398 else if (
len < other.len) {
399 return std::strong_ordering::less;
402 return std::strong_ordering::greater;
406 template<std::endian E>
408 return (*this <=> o) == std::strong_ordering::equal;
411 template<std::endian E>
413 return (*this <=> o) != std::strong_ordering::equal;
416 template<std::endian E>
418 return (*this <=> o) == std::strong_ordering::less;
421 template<std::endian E>
423 return (*this <=> o) == std::strong_ordering::greater;
426 template<std::endian E>
428 const auto cmp = *this <=> o;
429 return (cmp == std::strong_ordering::less || cmp == std::strong_ordering::equal);
432 template<std::endian E>
434 const auto cmp = *this <=> o;
435 return (cmp == std::strong_ordering::greater || cmp == std::strong_ordering::equal);
438 template<std::endian E>
440 return (*this <=> o) == std::strong_ordering::equal;
443 template<std::endian E>
445 return (*this <=> o) != std::strong_ordering::equal;
448 template<std::endian E>
450 return (*this <=> o) == std::strong_ordering::less;
453 template<std::endian E>
455 return (*this <=> o) == std::strong_ordering::greater;
458 template<std::endian E>
460 const auto cmp = *this <=> o;
461 return (cmp == std::strong_ordering::less || cmp == std::strong_ordering::equal);
464 template<std::endian E>
466 const auto cmp = *this <=> o;
467 return (cmp == std::strong_ordering::greater || cmp == std::strong_ordering::equal);
472 template<
typename T, std::endian E>
473 struct EndianSliceWriterImpl {
474 static_assert(!std::is_const_v<T>,
"Cannot write to const pointer!");
475 EndianSlice<T, E> out;
476 size_t curWriteIndex = 0;
481 Result<size_t, ErrType> write(Slice<std::add_const_t<T>> bytes) {
483 for (; i < bytes.size() && curWriteIndex < out.size(); ++i, ++curWriteIndex) {
484 out[curWriteIndex] = bytes[i];
489 template<std::endian E2>
490 Result<size_t, ErrType> write(EndianSlice<std::add_const_t<T>, E2> bytes) {
492 for (; i < bytes.size() && curWriteIndex < out.size(); ++i, ++curWriteIndex) {
493 out[curWriteIndex] = bytes[i].native();
592 return {.head = s.head, .len = s.len};
599 return {.head = s.head, .len = s.len};
635 auto subbed = s.
sub(1);
636 if (detect.value() == std::endian::little) {
637 return SliceU16Le{.head = subbed.head, .len = subbed.len};
640 return SliceU16Be{.head = subbed.head, .len = subbed.len};
658 auto subbed = s.
sub(1);
659 if (detect.value() == std::endian::little) {
660 return SliceU32Le{.head = subbed.head, .len = subbed.len};
663 return SliceU32Be{.head = subbed.head, .len = subbed.len};
678 inline std::variant<SliceConstU16Le, SliceConstU16Be>
endian_from_slice(Slice<const char16_t> s) {
681 auto subbed = s.sub(1);
682 if (detect.value() == std::endian::little) {
704 auto subbed = s.sub(1);
705 if (detect.value() == std::endian::little) {
726 return {.head = s.
head, .len = s.
len};
738 return {.head = s.
head, .len = s.
len};
810 namespace impl::unicode {
811 constexpr char16_t utf16HighOffset = 0xD800;
812 constexpr char16_t utf16LowOffset = 0xDC00;
813 constexpr char32_t utf16Sub = 0x10000;
815 constexpr uint8_t continueFlag = 0b10000000;
817 constexpr auto runeMasks = std::array{
818 static_cast<u32>(0b111110000000000000000),
819 static_cast<u32>(0b000001111100000000000),
820 static_cast<u32>(0b000000000011110000000),
823 constexpr auto utf8StartFlags = std::array<std::tuple<uint8_t, int, uint8_t>, 5>{
824 std::make_tuple(0b11110000, 4, 0b00000111), std::make_tuple(0b11100000, 3, 0b00001111),
825 std::make_tuple(0b11000000, 2, 0b00011111), std::make_tuple(continueFlag, -1, 0b00111111),
826 std::make_tuple(0b00000000, 1, 0b01111111),
829 constexpr auto num_bytes(
char8_t byte) ->
int {
830 for (
const auto &[flagSet, bytes, _flag_removal]: utf8StartFlags) {
831 if (
byte >= flagSet) {
838 constexpr auto without_flag(
char8_t byte) -> uint8_t {
839 for (
const auto &[flagSet, _bytes, removeFlag]: utf8StartFlags) {
840 if (
byte >= flagSet) {
841 return byte & removeFlag;
847 constexpr auto get_flag(
char8_t byte) -> uint8_t {
848 for (
const auto &[flagSet, _bytes, _removeFlag]: utf8StartFlags) {
849 if (
byte >= flagSet) {
883 char32_t currentRune = 0;
884 auto numBytes = impl::unicode::num_bytes(
data[curIndex]);
889 else if (curIndex + numBytes - 1 >=
data.size()) {
894 for (
size_t index = curIndex; index <
strIndex; ++index) {
895 auto flag = impl::unicode::get_flag(
data[index]);
896 if (index > curIndex && flag != impl::unicode::continueFlag) {
901 auto noFlag = impl::unicode::without_flag(
data[index]);
903 currentRune |= noFlag;
950 char32_t currentRune = 0;
952 auto ch =
data[curIndex];
958 if (curIndex + 1 >=
data.size()) {
963 auto chNext =
data[curIndex + 1];
968 const auto high = (ch - impl::unicode::utf16HighOffset) * 0x400;
969 const auto low = chNext - impl::unicode::utf16LowOffset;
970 currentRune = high + low + impl::unicode::utf16Sub;
976 currentRune =
static_cast<char32_t>(ch);
1009 return {.data = s, .strIndex = 0};
1018 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::little};
1027 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::big};
1036 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::little};
1045 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::big};
1058 return {.data = s, .strIndex = 0};
1067 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::little};
1076 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::big};
1085 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::little};
1094 .data = {.head = s.
head, .len = s.
len}, .strIndex = 0, .reverseBom = std::endian::native != std::endian::big};
1107 template<WriterImpl WI>
1115 if (
auto res = writer.write(
bom); res.is_error()) {
1121 while (
iter.next().copy_if_present(cur)) {
1124 auto iter2 = seq.iter();
1125 while (iter2.next().copy_if_present(curCh)) {
1126 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1127 return writeRes.error();
1145 template<WriterImpl WI>
1153 if (
auto res = writer.write(
bom); res.is_error()) {
1159 while (
iter.next().copy_if_present(cur)) {
1162 auto iter2 = seq.iter();
1163 while (iter2.next().copy_if_present(curCh)) {
1164 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1165 return writeRes.error();
1183 template<WriterImpl WI>
1197 template<WriterImpl WI>
1202 while (
iter.next().copy_if_present(cur)) {
1205 auto iter2 = seq.iter();
1206 while (iter2.next().copy_if_present(curCh)) {
1207 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1208 return writeRes.error();
1224 template<WriterImpl WI>
1229 while (
iter.next().copy_if_present(cur)) {
1232 auto iter2 = seq.iter();
1233 while (iter2.next().copy_if_present(curCh)) {
1234 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1235 return writeRes.error();
1251 template<WriterImpl WI>
1265 template<WriterImpl WI>
1270 while (
iter.next().copy_if_present(cur)) {
1273 auto iter2 = seq.iter();
1274 while (iter2.next().copy_if_present(curCh)) {
1275 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1276 return writeRes.error();
1292 template<WriterImpl WI>
1297 while (
iter.next().copy_if_present(cur)) {
1300 auto iter2 = seq.iter();
1301 while (iter2.next().copy_if_present(curCh)) {
1302 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1303 return writeRes.error();
1319 template<WriterImpl WI>
1334 template<WriterImpl WI>
1342 if (
auto res = writer.write(
bom); res.is_error()) {
1348 while (runeIter.next().copy_if_present(rune)) {
1349 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
1350 return writeRes.error();
1366 template<WriterImpl WI>
1374 if (
auto res = writer.write(
bom); res.is_error()) {
1380 while (runeIter.next().copy_if_present(rune)) {
1381 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
1382 return writeRes.error();
1397 template<WriterImpl WI>
1402 while (runeIter.next().copy_if_present(rune)) {
1405 auto charIter = seq.iter();
1406 while (charIter.next().copy_if_present(curCh)) {
1407 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1408 return writeRes.error();
1426 template<WriterImpl WI>
1434 if (
auto res = writer.write(
bom); res.is_error()) {
1440 while (runeIter.next().copy_if_present(rune)) {
1441 if (
auto writeres = writer.write(rune); writeres.is_error()) {
1442 return writeres.error();
1458 template<WriterImpl WI>
1466 if (
auto res = writer.write(
bom); res.is_error()) {
1472 while (runeIter.next().copy_if_present(rune)) {
1473 if (
auto writeres = writer.write(rune); writeres.is_error()) {
1474 return writeres.error();
1490 template<WriterImpl WI>
1504 template<WriterImpl WI>
1509 while (runeIter.next().copy_if_present(rune)) {
1512 auto charIter = seq.iter();
1513 while (charIter.next().copy_if_present(curCh)) {
1514 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1515 return writeRes.error();
1531 template<WriterImpl WI>
1536 while (runeIter.next().copy_if_present(rune)) {
1539 auto charIter = seq.iter();
1540 while (charIter.next().copy_if_present(curCh)) {
1541 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1542 return writeRes.error();
1558 template<WriterImpl WI>
1563 while (runeIter.next().copy_if_present(rune)) {
1566 auto charIter = seq.iter();
1567 while (charIter.next().copy_if_present(curCh)) {
1568 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1569 return writeRes.error();
1585 template<WriterImpl WI>
1599 template<WriterImpl WI>
1614 template<WriterImpl WI>
1622 if (
auto res = writer.write(
bom); res.is_error()) {
1628 while (runeIter.next().copy_if_present(rune)) {
1631 auto charIter = seq.iter();
1632 while (charIter.next().copy_if_present(curCh)) {
1633 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1634 return writeRes.error();
1651 template<WriterImpl WI>
1659 if (
auto res = writer.write(
bom); res.is_error()) {
1665 while (runeIter.next().copy_if_present(rune)) {
1668 auto charIter = seq.iter();
1669 while (charIter.next().copy_if_present(curCh)) {
1670 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1671 return writeRes.error();
1687 template<WriterImpl WI>
1693 while (runeIter.next().copy_if_present(rune)) {
1696 auto charIter = seq.iter();
1697 while (charIter.next().copy_if_present(curCh)) {
1698 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1699 return writeRes.error();
1715 template<WriterImpl WI>
1720 while (runeIter.next().copy_if_present(rune)) {
1723 auto charIter = seq.iter();
1724 while (charIter.next().copy_if_present(curCh)) {
1725 if (
auto writeRes = writer.write(curCh); writeRes.is_error()) {
1726 return writeRes.error();
1743 template<WriterImpl WI>
1757 while (runeIter.next().copy_if_present(rune)) {
1760 auto seqIter = seq.iter();
1761 while (seqIter.next().copy_if_present(cur)) {
1762 if constexpr (std::endian::native != std::endian::little) {
1765 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1766 return writeRes.error();
1783 template<WriterImpl WI>
1798 template<WriterImpl WI>
1812 while (runeIter.next().copy_if_present(rune)) {
1815 auto seqIter = seq.iter();
1816 while (seqIter.next().copy_if_present(cur)) {
1817 if constexpr (std::endian::native != std::endian::big) {
1820 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1821 return writeRes.error();
1838 template<WriterImpl WI>
1853 template<WriterImpl WI>
1867 while (runeIter.next().copy_if_present(rune)) {
1870 auto seqIter = seq.iter();
1871 while (seqIter.next().copy_if_present(cur)) {
1872 if constexpr (std::endian::native != std::endian::big) {
1875 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1876 return writeRes.error();
1893 template<WriterImpl WI>
1907 while (runeIter.next().copy_if_present(rune)) {
1910 auto seqIter = seq.iter();
1911 while (seqIter.next().copy_if_present(cur)) {
1912 if constexpr (std::endian::native != std::endian::little) {
1915 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1916 return writeRes.error();
1933 template<WriterImpl WI>
1947 while (runeIter.next().copy_if_present(rune)) {
1950 auto seqIter = seq.iter();
1951 while (seqIter.next().copy_if_present(cur)) {
1952 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1953 return writeRes.error();
1970 template<WriterImpl WI>
1984 while (runeIter.next().copy_if_present(rune)) {
1987 auto seqIter = seq.iter();
1988 while (seqIter.next().copy_if_present(cur)) {
1989 if (
auto writeRes = writer.write(cur); writeRes.is_error()) {
1990 return writeRes.error();
2007 template<WriterImpl WI>
2021 while (runeIter.next().copy_if_present(rune)) {
2022 if constexpr (std::endian::native != std::endian::little) {
2025 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2026 return writeRes.error();
2042 template<WriterImpl WI>
2057 template<WriterImpl WI>
2071 while (runeIter.next().copy_if_present(rune)) {
2072 if constexpr (std::endian::native != std::endian::big) {
2075 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2076 return writeRes.error();
2092 template<WriterImpl WI>
2107 template<WriterImpl WI>
2121 while (runeIter.next().copy_if_present(rune)) {
2122 if constexpr (std::endian::native != std::endian::big) {
2125 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2126 return writeRes.error();
2142 template<WriterImpl WI>
2156 while (runeIter.next().copy_if_present(rune)) {
2157 if constexpr (std::endian::native != std::endian::little) {
2160 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2161 return writeRes.error();
2177 template<WriterImpl WI>
2191 while (runeIter.next().copy_if_present(rune)) {
2192 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2193 return writeRes.error();
2209 template<WriterImpl WI>
2223 while (runeIter.next().copy_if_present(rune)) {
2224 if (
auto writeRes = writer.write(rune); writeRes.is_error()) {
2225 return writeRes.error();
ValIter< T > val(const T &r)
Generic value iterator that uses the operator[] and incrementing indexes to iterate over a collection...
constexpr auto nullopt
Placeholder value for an empty Optional.
ConstPtrIter< T > const_ptr(const T &r)
Generic constant pointer iterator that uses the operator[] and incrementing indexes to iterate over a...
PtrIter< T > ptr(T &r)
Generic pointer iterator that uses the operator[] and incrementing indexes to iterate over a collecti...
constexpr char32_t flip_endian_ch32(const char32_t ch)
Flips the endianness of a char32.
constexpr char16_t flip_endian_ch16(const char16_t ch)
Flips the endianness of a char16.
constexpr auto opposite
endian that is opposite of machine (opposite of std::endian::native)
constexpr auto flip_endian(const T bytes)
Flips the endian of a u16, char16, u32, or char32.
constexpr auto machine
endian of machine (alias for std::endian::native)
RuneConversionError
Errors that can occur when doing conversions to a rune.
SliceWriteError
Errors when writing to a slice.
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Success< void > success()
Creates a successful void Result object.
uint32_t u32
Alias for 32-bit unsigned ints.
constexpr auto is_bom(const char32_t ch)
Checks if a character is a BOM in native ordering.
EndianSlice< const char16_t, std::endian::big > SliceConstU16Be
Slice type representing const big endian UTF-16 string *.
auto utf32_to_utf32le(io::Writer< WI > &writer, const SliceConstU32Native &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Native Endian to UTF-32 Little Endian.
auto utf32le_to_utf32(io::Writer< WI > &writer, const SliceConstU32Le &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Little Endian to UTF-32 Native Endian.
EndianSlice< const char32_t, std::endian::little > SliceConstU32Le
Slice type representing const little endian UTF-32 string.
Slice< char16_t > slice_from_native_endian(SliceU16Native s)
Gets a normal slice from a native endian slice.
RuneIterator< char8_t > utf8_rune_iterator(const Slice< const char8_t > &s)
Rune iterator for a UTF8 sequence.
auto utf16_to_utf16le(io::Writer< WI > &writer, const SliceConstU16Native &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts native UTF-16 to UTF-16 Little Endian.
Optional< std::endian > u16_detect_endian(const char16_t ch)
Tries to detect the endian encoding based on a possible BOM mark.
EndianSlice< const char32_t, std::endian::big > SliceConstU32Be
Slice type representing const big endian UTF-32 string.
auto utf32le_to_utf32be(io::Writer< WI > &writer, const SliceConstU32Le &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Little Endian to UTF-32 Big Endian.
auto utf32_to_utf32be(io::Writer< WI > &writer, const SliceConstU32Native &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Native Endian to UTF-32 Big Endian.
SliceU16Le endian_from_le_slice(Slice< char16_t > s)
Gets a UTF-16 endian slice from a slice which is assumed ot be little endian.
Slice< char16_t > slice_from_le_endian(SliceU16Native s)
Gets a normal slice from a little endian slice.
auto utf32be_to_utf32(io::Writer< WI > &writer, const SliceConstU32Be &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Big Endian to UTF-32 Native Endian.
EndianSlice< char16_t, std::endian::native > SliceU16Native
Slice type representing native UTF-16 string *.
auto utf16_to_utf32(io::Writer< WI > &writer, const SliceConstU16Le &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-16 string to UTF-32.
constexpr bool is_low_surrogate(char16_t ch)
Checks if UTF-16 character is a low surrogate *.
auto utf8_to_utf32(io::Writer< WI > &writer, const Slice< const char8_t > &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-8 string to UTF-32.
EndianSlice< const char16_t, std::endian::native > SliceConstU16Native
Slice type representing const native UTF-16 string *.
Optional< std::endian > u32_detect_endian(const char32_t ch)
Tries to detect the endian encoding based on a possible BOM mark.
auto str_to_utf32(io::Writer< WI > &writer, const Slice< const char > &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-8 string to UTF-32.
auto utf32_to_str(io::Writer< WI > &writer, const SliceConstU32Be &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-32 string to character sequence (UTF-8 encoded chars)
RuneIterator< char32_t > utf32_rune_iterator(const Slice< const char32_t > &s)
Rune iterator for a UTF32 sequence.
auto utf16be_to_utf16le(io::Writer< WI > &writer, const SliceConstU16Be &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-16 Big Endian to UTF-16 Little Endian.
Slice< char16_t > slice_from_be_endian(SliceU16Native s)
Gets a normal slice from a big endian slice.
auto utf16be_to_utf16(io::Writer< WI > &writer, const SliceConstU16Be &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-16 Big Endian to Native UTF-16.
constexpr char32_t bom
Native representation of Byte Order Mark (BOM)
auto utf16le_to_utf16be(io::Writer< WI > &writer, const SliceConstU16Le &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-16 Little Endian to UTF-16 Big Endian.
auto utf32_to_utf8(io::Writer< WI > &writer, const SliceConstU32Be &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-32 string to UTF-8 string.
SliceU16Be endian_from_be_slice(Slice< char16_t > s)
Gets a UTF-16 endian slice from a slice which is assumed ot be big endian.
EndianSlice< char16_t, std::endian::little > SliceU16Le
Slice type representing little endian UTF-16 string *.
auto utf16_to_str(io::Writer< WI > &writer, const SliceConstU16Be &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-16 string to UTF-8.
auto utf32be_to_utf32le(io::Writer< WI > &writer, const SliceConstU32Be &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-32 Big Endian to UTF-32 Little Endian.
constexpr bool is_high_surrogate(char16_t ch)
Checks if UTF-16 character is a high surrogate *.
EndianSlice< char16_t, std::endian::big > SliceU16Be
Slice type representing big endian UTF-16 string *.
auto utf32_to_utf16(io::Writer< WI > &writer, const SliceConstU32Be &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-32 string to UTF-16 string Can optionally write a BOM to the prefix.
constexpr auto is_bom_rev_16_bit(const char16_t ch)
Checks if a 16-bit character is a BOM in reverse ordering.
auto utf16_to_utf16be(io::Writer< WI > &writer, const SliceConstU16Native &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts native UTF-16 to UTF-16 Big Endian.
auto utf8_to_str(io::Writer< WI > &writer, const Slice< const char8_t > &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-8 string to character sequence.
RuneIterator< char16_t > utf16_rune_iterator(const Slice< const char16_t > &s)
Rune iterator for a UTF16 sequence.
RuneIterator< char > str_rune_iterator(const Slice< const char > &s)
Rune iterator for a slice of characters.
U8Seq rune_to_utf8(Rune rune)
Converts a UTF-32 Rune to a utf-8 sequence.
EndianSlice< char32_t, std::endian::little > SliceU32Le
Slice type representing little endian UTF-32 string *.
constexpr auto is_bom_rev_32_bit(const char32_t ch)
Checks if a 32-bit character is a BOM in reverse ordering.
constexpr bool is_surrogate(char16_t ch)
Checks if UTF-16 character is a surrogate.
auto utf16le_to_utf16(io::Writer< WI > &writer, const SliceConstU16Le &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Converts UTF-16 Little Endian to Native UTF-16.
EndianSlice< const char32_t, std::endian::native > SliceConstU32Native
Slice type representing const native UTF-32 string.
auto str_to_utf16(io::Writer< WI > &writer, const Slice< const char > &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-8 string to UTF-16.
U16Seq rune_to_utf16(Rune rune)
Converts a UTF-32 Rune to a utf-16 sequence.
constexpr auto oppositeEndian
Returns the opposite endianness of a given endian (default is opposite of the native endian)
CharSeq rune_to_str(Rune rune)
Converts a UTF-32 Rune to a sequence of char.
EndianSlice< char32_t, std::endian::native > SliceU32Native
Slice type representing native UTF-32 string *.
EndianSlice< char32_t, std::endian::big > SliceU32Be
Slice type representing big endian UTF-32 string.
std::variant< SliceU16Le, SliceU16Be > endian_from_slice(Slice< char16_t > s)
Gets a UTF-16 endian slice from an input slice Will try to use the first character of the slice as a ...
auto utf16_to_utf8(io::Writer< WI > &writer, const SliceConstU16Be &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-16 string to UTF-8.
SliceU16Native endian_from_native_slice(Slice< char16_t > s)
Gets a UTF-16 endian slice from a slice which is assumed ot be native endian.
auto utf8_to_utf16(io::Writer< WI > &writer, const Slice< const char8_t > &str, bool writeBom=false) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a UTF-8 string to UTF-16.
auto str_to_utf8(io::Writer< WI > &writer, const Slice< const char > &str) -> Result< size_t, typename io::Writer< WI >::ErrType >
Will convert a character sequence to UTF-8 string.
EndianSlice< const char16_t, std::endian::little > SliceConstU16Le
Slice type representing const little endian UTF-16 string *.
Generic iterator defaults built on common contracts Does not guarantee performance of iterators Actua...
Core library for C++ with Zig-related functionality.
Result< Rune, RuneConversionError > utf8_to_rune(const Slice< const char8_t > &rune)
UTF-8 to a Rune.
impl::ShortSeq< char, 4 > CharSeq
Result< Rune, RuneConversionError > utf16_to_rune(const Slice< const char16_t > &rune)
UTF-16 to a Rune.
Result< Rune, RuneConversionError > str_to_rune(const Slice< const char > &rune)
Characters to a Rune.
impl::ShortSeq< char16_t, 2 > U16Seq
impl::ShortSeq< char8_t, 4 > U8Seq
Endian Wrapper for grabbing the endian value By default, will handle converting to and from the nativ...
const EndianSlice & slice
constexpr auto native() const
constexpr T as_endian(std::endian viewAs) const
Gets the value with the specific endian.
Endian Wrapper for grabbing the endian value By default, will handle converting to and from the nativ...
constexpr T native() const
constexpr EndianWrapper & operator=(T val)
Sets the pointed at value using the native endian.
constexpr EndianWrapper & with_endian(T newVal, std::endian setAs)
Sets the target value with the provided endian interpretation.
constexpr T as_endian(std::endian viewAs) const
Gets the value with the specific endian.
A Slice with Endian-aware data which is just a pointer + length + endian direction Accessing elements...
bool operator>=(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
bool operator>(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
constexpr ConstEndianWrapper at(size_t i) const noexcept
Access element at a specific index Const operator, returns a const reference.
EndianWrapper operator[](size_t i) noexcept
Access element at a specific index Non-const operator, returns a mutable reference.
constexpr void init(T *head, size_t len)
Initializes a Slice Using init instead of a constructor so that slices allocated with malloc or an ar...
bool operator<=(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
constexpr EndianSlice sub(size_t start) const noexcept
Gets a sub Slice from start to end.
bool operator<(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
bool operator!=(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
bool operator>=(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
EndianWrapper at(size_t i) noexcept
Access element at a specific index Non-const operator, returns a mutable reference.
constexpr Slice< std::add_const_t< T > > to_const() const noexcept
Converts to a const Slice.
constexpr bool empty() const noexcept
Checks if a Slice is empty.
decltype(auto) ptr_iter() const noexcept
decltype(auto) ptr_iter() noexcept
bool operator!=(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
bool operator<=(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
bool operator==(const EndianSlice< std::remove_const_t< T >, E > &o) const noexcept
std::strong_ordering operator<=>(const EndianSlice< std::remove_const_t< T >, E > &other) const noexcept
Compares against another Slice.
decltype(auto) iter() const noexcept
constexpr ConstEndianWrapper operator[](size_t i) const noexcept
Access element at a specific index Const operator, returns a const reference.
bool operator>(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
constexpr EndianSlice sub(size_t start, size_t len) const noexcept
Gets a sub Slice from start up to a length.
constexpr size_t size() const noexcept
Gets the size of a Slice.
std::strong_ordering operator<=>(const EndianSlice< std::add_const_t< T >, E > &other) const noexcept
Compares against another Slice.
bool operator==(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
bool operator<(const EndianSlice< std::add_const_t< T >, E > &o) const noexcept
Represents a value that may or may not exist (an "Optional" value) Similar concept to std::optional,...
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
Optional< char32_t > next()
Slice< const char16_t > data
Slice< const char32_t > data
Optional< char32_t > next()
Iterates over runes of utf8 sequences (char, char_t)
Optional< Rune > next()
Gets the next Rune, if present.
A Slice which is just a pointer + length Accessing elements through the array operator will do bounds...
constexpr Slice sub(size_t start) const noexcept
Gets a sub Slice from start.
constexpr size_t size() const noexcept
Gets the size of a Slice.
A writer that writes data to some sort of stream or buffer Note: the data elements written should be ...