HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
iso_639.hpp
1// Copyright Take Vos 2022.
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 "../utility/module.hpp"
8#include "../strings.hpp"
9#include <cctype>
10
11namespace hi::inline v1 {
12
23class iso_639 {
24public:
31 template<std::size_t I>
32 constexpr friend iso_639& set(iso_639& rhs, char c)
33 {
35 c == 0 or (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '1' and c <= '5'),
36 "Must be letters or the digits between '1' and '5', or nul");
37
38 // clang-format off
39 uint16_t const x =
40 (c >= 'a' and c <= 'z') ? c - 'a' + 1 :
41 (c >= 'A' and c <= 'Z') ? c - 'A' + 1 :
42 (c >= '1' and c <= '5') ? c - '1' + 27 :
43 0;
44 // clang-format on
45
46 hi_assert(x <= 0x1f);
47 constexpr auto shift = I * 5;
48 rhs._v &= ~(0x1f << shift);
49 rhs._v |= x << shift;
50 return rhs;
51 }
52
59 template<std::size_t I>
60 [[nodiscard]] constexpr friend char get(iso_639 const& rhs) noexcept
61 {
62 constexpr auto shift = I * 5;
63 hilet x = (rhs._v >> shift) & 0x1f;
64 if (x == 0) {
65 return 0;
66 } else if (x <= 26) {
67 return 'a' + narrow_cast<char>(x - 1);
68 } else {
69 return '1' + narrow_cast<char>(x - 27);
70 }
71 }
72
73 constexpr iso_639(iso_639 const&) noexcept = default;
74 constexpr iso_639(iso_639&&) noexcept = default;
75 constexpr iso_639& operator=(iso_639 const&) noexcept = default;
76 constexpr iso_639& operator=(iso_639&&) noexcept = default;
77
80 constexpr iso_639() noexcept : _v(0) {}
81
84 constexpr iso_639(std::string_view str) : _v(0)
85 {
86 try {
87 hi_check(str.size() == 2 or str.size() == 3, "ISO-639 incorrect length.");
88
89 set<0>(*this, str[0]);
90 set<1>(*this, str[1]);
91 if (str.size() == 3) {
92 set<2>(*this, str[2]);
93 }
94 } catch (...) {
95 throw parse_error(std::format("A ISO-639 language code must be 2 or 3 letters in length, got '{}'", str));
96 }
97 }
98
99 constexpr iso_639(intrinsic_t, uint16_t v) noexcept : _v(v) {}
100
101 [[nodiscard]] constexpr uint16_t const& intrinsic() const noexcept
102 {
103 return _v;
104 }
105
106 [[nodiscard]] constexpr uint16_t& intrinsic() noexcept
107 {
108 return _v;
109 }
110
115 [[nodiscard]] constexpr std::size_t size() const noexcept
116 {
117 hilet tmp = _v & 0x7fff;
118 // clang-format off
119 return
120 tmp == 0 ? 0 :
121 tmp <= 0x1f ? 1 :
122 tmp <= 0x3ff ? 2 :
123 3;
124 // clang-format on
125 }
126
129 [[nodiscard]] constexpr bool empty() const noexcept
130 {
131 return _v == 0;
132 }
133
136 constexpr explicit operator bool() const noexcept
137 {
138 return not empty();
139 }
140
143 [[nodiscard]] size_t hash() const noexcept
144 {
145 return std::hash<uint16_t>{}(_v);
146 }
147
150 [[nodiscard]] constexpr std::string code() const noexcept
151 {
152 auto r = std::string{};
153 if (size() >= 2) {
154 r += get<0>(*this);
155 r += get<1>(*this);
156 }
157 if (size() == 3) {
158 r += get<2>(*this);
159 }
160 return r;
161 }
162
165 [[nodiscard]] constexpr friend bool operator==(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
166
169 [[nodiscard]] constexpr friend auto operator<=>(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
170
177 [[nodiscard]] constexpr friend bool matches(iso_639 const& lhs, iso_639 const& rhs) noexcept
178 {
179 return lhs.empty() or lhs == rhs;
180 }
181
182private:
192 uint16_t _v;
193};
194
195} // namespace hi::inline v1
196
197template<>
198struct std::hash<hi::iso_639> {
199 [[nodiscard]] size_t operator()(hi::iso_639 const& rhs) const noexcept
200 {
201 return rhs.hash();
202 }
203};
#define hi_check(expression, message,...)
Check if the expression is valid, or throw a parse_error.
Definition assert.hpp:110
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
@ shift
The shift key is being held.
geometry/margins.hpp
Definition cache.hpp:11
ISO-639 language code.
Definition iso_639.hpp:23
constexpr friend bool matches(iso_639 const &lhs, iso_639 const &rhs) noexcept
Check if rhs matches with lhs.
Definition iso_639.hpp:177
constexpr std::string code() const noexcept
Get the 2 or 3 letter ISO-639 code.
Definition iso_639.hpp:150
constexpr bool empty() const noexcept
Check if the language is empty.
Definition iso_639.hpp:129
size_t hash() const noexcept
Get the hash value for this language code.
Definition iso_639.hpp:143
constexpr friend char get(iso_639 const &rhs) noexcept
Get the letter at a specific position.
Definition iso_639.hpp:60
constexpr friend iso_639 & set(iso_639 &rhs, char c)
Set the letter at a specific position.
Definition iso_639.hpp:32
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:84
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:115
T operator()(T... args)