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/utility.hpp"
8#include "../macros.hpp"
9#include <cctype>
10#include <compare>
11#include <string_view>
12#include <string>
13#include <format>
14
15hi_export_module(hikogui.i18n.iso_639);
16
17hi_export namespace hi::inline v1 {
18
29hi_export class iso_639 {
30public:
37 template<std::size_t I>
38 constexpr friend bool set(iso_639& rhs, char c) noexcept
39 {
40 if (not (c == 0 or (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '1' and c <= '5'))) {
41 // Must be letters or the digits between '1' and '5', or nul.
42 return false;
43 }
44
45 // clang-format off
46 uint16_t const x =
47 (c >= 'a' and c <= 'z') ? c - 'a' + 1 :
48 (c >= 'A' and c <= 'Z') ? c - 'A' + 1 :
49 (c >= '1' and c <= '5') ? c - '1' + 27 :
50 0;
51 // clang-format on
52
53 hi_axiom(x <= 0x1f);
54 constexpr auto shift = I * 5;
55 rhs._v &= ~(0x1f << shift);
56 rhs._v |= x << shift;
57 return true;
58 }
59
66 template<std::size_t I>
67 [[nodiscard]] constexpr friend char get(iso_639 const& rhs) noexcept
68 {
69 constexpr auto shift = I * 5;
70 auto const x = (rhs._v >> shift) & 0x1f;
71 if (x == 0) {
72 return 0;
73 } else if (x <= 26) {
74 return 'a' + narrow_cast<char>(x - 1);
75 } else {
76 return '1' + narrow_cast<char>(x - 27);
77 }
78 }
79
80 constexpr iso_639(iso_639 const&) noexcept = default;
81 constexpr iso_639(iso_639&&) noexcept = default;
82 constexpr iso_639& operator=(iso_639 const&) noexcept = default;
83 constexpr iso_639& operator=(iso_639&&) noexcept = default;
84
87 constexpr iso_639() noexcept : _v(0) {}
88
91 constexpr iso_639(std::string_view str) : _v(0)
92 {
93 if (str.size() != 2 and str.size() != 3) {
94 throw parse_error("ISO-639 incorrect length.");
95 }
96
97 if (not set<0>(*this, str[0])) {
98 throw parse_error("Must be letters or the digits between '1' and '5', or nul.");
99 }
100
101 if (not set<1>(*this, str[1])) {
102 throw parse_error("Must be letters or the digits between '1' and '5', or nul.");
103 }
104
105 if (str.size() == 3) {
106 if (not set<2>(*this, str[2])) {
107 throw parse_error("Must be letters or the digits between '1' and '5', or nul.");
108 }
109 }
110 }
111
112 constexpr iso_639(std::in_place_t, uint16_t v) noexcept : _v(v) {}
113
114 [[nodiscard]] constexpr uint16_t const& intrinsic() const noexcept
115 {
116 return _v;
117 }
118
119 [[nodiscard]] constexpr uint16_t& intrinsic() noexcept
120 {
121 return _v;
122 }
123
128 [[nodiscard]] constexpr std::size_t size() const noexcept
129 {
130 auto const tmp = _v & 0x7fff;
131 // clang-format off
132 return
133 tmp == 0 ? 0 :
134 tmp <= 0x1f ? 1 :
135 tmp <= 0x3ff ? 2 :
136 3;
137 // clang-format on
138 }
139
142 [[nodiscard]] constexpr bool empty() const noexcept
143 {
144 return _v == 0;
145 }
146
149 constexpr explicit operator bool() const noexcept
150 {
151 return not empty();
152 }
153
156 [[nodiscard]] size_t hash() const noexcept
157 {
158 return std::hash<uint16_t>{}(_v);
159 }
160
163 [[nodiscard]] constexpr std::string code() const noexcept
164 {
165 auto r = std::string{};
166 if (size() >= 2) {
167 r += get<0>(*this);
168 r += get<1>(*this);
169 }
170 if (size() == 3) {
171 r += get<2>(*this);
172 }
173 return r;
174 }
175
176 [[nodiscard]] constexpr friend std::string to_string(iso_639 const &rhs) noexcept
177 {
178 return rhs.code();
179 }
180
183 [[nodiscard]] constexpr friend bool operator==(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
184
187 [[nodiscard]] constexpr friend auto operator<=>(iso_639 const& lhs, iso_639 const& rhs) noexcept = default;
188
195 [[nodiscard]] constexpr friend bool matches(iso_639 const& lhs, iso_639 const& rhs) noexcept
196 {
197 return lhs.empty() or lhs == rhs;
198 }
199
200private:
210 uint16_t _v;
211};
212
213} // namespace hi::inline v1
214
215hi_export template<>
216struct std::hash<hi::iso_639> {
217 [[nodiscard]] size_t operator()(hi::iso_639 const& rhs) const noexcept
218 {
219 return rhs.hash();
220 }
221};
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
@ shift
The shift key is being held.
ISO-639 language code.
Definition iso_639.hpp:29
constexpr friend bool matches(iso_639 const &lhs, iso_639 const &rhs) noexcept
Check if rhs matches with lhs.
Definition iso_639.hpp:195
constexpr std::string code() const noexcept
Get the 2 or 3 letter ISO-639 code.
Definition iso_639.hpp:163
constexpr bool empty() const noexcept
Check if the language is empty.
Definition iso_639.hpp:142
constexpr friend bool set(iso_639 &rhs, char c) noexcept
Set the letter at a specific position.
Definition iso_639.hpp:38
size_t hash() const noexcept
Get the hash value for this language code.
Definition iso_639.hpp:156
constexpr friend char get(iso_639 const &rhs) noexcept
Get the letter at a specific position.
Definition iso_639.hpp:67
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:91
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:128
T operator()(T... args)