HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
iso_639.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../assert.hpp"
8#include "../strings.hpp"
9#include "../check.hpp"
10#include <cctype>
11
12namespace hi::inline v1 {
13
25class iso_639 {
26public:
27 constexpr iso_639(iso_639 const&) noexcept = default;
28 constexpr iso_639(iso_639&&) noexcept = default;
29 constexpr iso_639& operator=(iso_639 const&) noexcept = default;
30 constexpr iso_639& operator=(iso_639&&) noexcept = default;
31
34 constexpr iso_639() noexcept : _v(0) {}
35
38 constexpr iso_639(std::string_view str) : _v(0)
39 {
40 try {
41 hi_parse_check(str.size() == 2 or str.size() == 3, "ISO-639 incorrect length.");
42
43 set<0>(*this, str[0]);
44 set<1>(*this, str[1]);
45 if (str.size() == 3) {
46 set<2>(*this, str[2]);
47 }
48 } catch (...) {
49 throw parse_error(std::format("A ISO-639 language code must be 2 or 3 letters in length, got '{}'", str));
50 }
51 }
52
57 [[nodiscard]] constexpr std::size_t size() const noexcept
58 {
59 auto tmp = _v & 0x7fff;
60 // clang-format off
61 return
62 tmp == 0 ? 0 :
63 tmp <= 0x1f ? 1 :
64 tmp <= 0x3ff ? 2 :
65 3;
66 // clang-format on
67 }
68
71 [[nodiscard]] constexpr bool empty() const noexcept
72 {
73 return _v == 0;
74 }
75
78 constexpr explicit operator bool() const noexcept
79 {
80 return not empty();
81 }
82
85 [[nodiscard]] size_t hash() const noexcept
86 {
87 return std::hash<uint16_t>{}(_v);
88 }
89
92 [[nodiscard]] constexpr std::string code() const noexcept
93 {
94 auto r = std::string{};
95 if (size() >= 2) {
96 r += get<0>(*this);
97 r += get<1>(*this);
98 }
99 if (size() == 3) {
100 r += get<2>(*this);
101 }
102 return r;
103 }
104
107 [[nodiscard]] constexpr friend bool operator==(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
108
111 [[nodiscard]] constexpr friend auto operator<=>(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
112
119 template<std::size_t I>
120 constexpr friend iso_639& set(iso_639& rhs, char c)
121 {
122 hi_parse_check(
123 c == 0 or (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '1' and c <= '5'),
124 "Must be letters or the digits between '1' and '5', or nul");
125
126 // clang-format off
127 uint16_t x =
128 (c >= 'a' and c <= 'z') ? c - 'a' + 1 :
129 (c >= 'A' and c <= 'Z') ? c - 'A' + 1 :
130 (c >= '1' and c <= '5') ? c - '1' + 27 :
131 0;
132 // clang-format on
133
134 hi_axiom(x <= 0x1f);
135 constexpr auto shift = I * 5;
136 rhs._v &= ~(0x1f << shift);
137 rhs._v |= x << shift;
138 return rhs;
139 }
140
147 template<std::size_t I>
148 [[nodiscard]] constexpr friend char get(iso_639 const& rhs) noexcept
149 {
150 constexpr auto shift = I * 5;
151 auto x = (rhs._v >> shift) & 0x1f;
152 if (x == 0) {
153 return 0;
154 } else if (x <= 26) {
155 return 'a' + static_cast<char>(x - 1);
156 } else {
157 return '1' + static_cast<char>(x - 27);
158 }
159 }
160
161private:
171 uint16_t _v;
172};
173
174} // namespace hi::inline v1
175
176template<>
177struct std::hash<hi::iso_639> {
178 [[nodiscard]] size_t operator()(hi::iso_639 const& rhs) const noexcept
179 {
180 return rhs.hash();
181 }
182};
Exception thrown during parsing on an error.
Definition exception.hpp:25
ISO-639 language code.
Definition iso_639.hpp:25
constexpr std::string code() const noexcept
Get the 2 or 3 letter ISO-639 code.
Definition iso_639.hpp:92
constexpr bool empty() const noexcept
Check if the language is empty.
Definition iso_639.hpp:71
constexpr iso_639() noexcept
Construct empty language.
Definition iso_639.hpp:34
size_t hash() const noexcept
Get the hash value for this language code.
Definition iso_639.hpp:85
constexpr friend char get(iso_639 const &rhs) noexcept
Get the letter at a specific position.
Definition iso_639.hpp:148
constexpr friend iso_639 & set(iso_639 &rhs, char c)
Set the letter at a specific position.
Definition iso_639.hpp:120
constexpr friend auto operator<=>(iso_639 const &lhs, iso_639 const &rhs) noexcept=default
Compare two language codes.
constexpr iso_639(std::string_view str)
Construct a language from the 2 or 3 letter code.
Definition iso_639.hpp:38
constexpr friend bool operator==(iso_639 const &lhs, iso_639 const &rhs) noexcept=default
Compare two language codes.
constexpr std::size_t size() const noexcept
Get the number of character.
Definition iso_639.hpp:57
T operator()(T... args)