Terminal++ 3.1.0.4
A C++ library for interacting with ANSI terminal windows
All Classes Namespaces Functions Variables Typedefs Friends Pages Concepts
character_set.hpp
1#pragma once
2
3#include "terminalpp/ansi/charset.hpp"
4#include "terminalpp/core.hpp"
5
6#include <boost/container_hash/hash.hpp>
7
8#include <iosfwd>
9#include <ranges>
10#include <string_view>
11
12namespace terminalpp {
13
14//* =========================================================================
16//* =========================================================================
17enum class charset : char
18{
19 dec,
20 dec_supplementary,
21 dec_supplementary_graphics,
22 dec_technical,
23 uk,
24 us_ascii,
25 dutch,
26 finnish,
27 french,
28 french_canadian,
29 german,
30 italian,
31 danish,
32 portuguese,
33 spanish,
34 swedish,
35 swiss,
36 sco,
37 utf8,
38};
39
40//* =========================================================================
42//* =========================================================================
43struct TERMINALPP_EXPORT character_set
44{
45 //* =====================================================================
47 //* =====================================================================
48 constexpr character_set() noexcept : character_set(charset::us_ascii)
49 {
50 }
51
52 //* =====================================================================
54 //* =====================================================================
55 constexpr character_set(charset const &set) noexcept // NOLINT
56 : value_(set)
57 {
58 }
59
60 //* =====================================================================
62 //* =====================================================================
63 [[nodiscard]] constexpr friend auto operator<=>(
64 character_set const &lhs, character_set const &rhs) noexcept = default;
65
66 //* =====================================================================
68 //* =====================================================================
69 [[nodiscard]] friend std::size_t hash_value(
70 character_set const &cs) noexcept
71 {
72 std::size_t seed = 0;
73 boost::hash_combine(seed, cs.value_);
74
75 return seed;
76 }
77
78 terminalpp::charset value_;
79};
80
81namespace detail {
82
83using charset_map_small_entry = std::pair<character_set, byte const (&)[1]>;
84inline constexpr charset_map_small_entry const charset_map[] = {
85 {charset::us_ascii, ansi::charset_us_ascii },
86 {charset::sco, ansi::charset_sco },
87 {charset::dec, ansi::charset_dec },
88 {charset::dec_supplementary, ansi::charset_dec_supplementary },
89 {charset::dec_technical, ansi::charset_dec_technical },
90 {charset::uk, ansi::charset_uk },
91 {charset::dutch, ansi::charset_dutch },
92 {charset::finnish, ansi::charset_finnish },
93 {charset::finnish, ansi::charset_finnish_alt },
94 {charset::french, ansi::charset_french },
95 {charset::french, ansi::charset_french_alt },
96 {charset::french_canadian, ansi::charset_french_canadian },
97 {charset::french_canadian, ansi::charset_french_canadian_alt},
98 {charset::german, ansi::charset_german },
99 {charset::italian, ansi::charset_italian },
100 {charset::danish, ansi::charset_danish },
101 {charset::danish, ansi::charset_danish_alt_1 },
102 {charset::danish, ansi::charset_danish_alt_2 },
103 {charset::spanish, ansi::charset_spanish },
104 {charset::swedish, ansi::charset_swedish },
105 {charset::swedish, ansi::charset_swedish_alt },
106 {charset::swiss, ansi::charset_swiss },
107};
108
109using charset_map_extended_entry = std::pair<character_set, byte const (&)[2]>;
110inline constexpr charset_map_extended_entry const extended_charset_map[] = {
111 {charset::dec_supplementary_graphics, ansi::charset_dec_supplementary_gr},
112 {charset::portuguese, ansi::charset_portuguese },
113};
114
115} // namespace detail
116
117//* =========================================================================
120//* =========================================================================
121TERMINALPP_EXPORT
122[[nodiscard]] constexpr std::optional<character_set> lookup_character_set(
123 bytes code) noexcept
124{
125 auto const len = code.size();
126
127 if (len == 0)
128 {
129 return {};
130 }
131
132 if (code[0] == ansi::charset_extender)
133 {
134 if (len > 1)
135 {
136 for (auto &&mapping : detail::extended_charset_map)
137 {
138 if (code[1] == mapping.second[1])
139 {
140 return mapping.first;
141 }
142 }
143 }
144 }
145 else
146 {
147 for (auto &&mapping : detail::charset_map)
148 {
149 if (code[0] == mapping.second[0])
150 {
151 return mapping.first;
152 }
153 }
154 }
155
156 return std::nullopt;
157}
158
159//* =========================================================================
161//* =========================================================================
162TERMINALPP_EXPORT
163[[nodiscard]] constexpr std::basic_string_view<byte> encode_character_set(
164 character_set const &set) noexcept
165{
166 constexpr auto project_first = [](auto const &entry) {
167 return entry.first;
168 };
169
170 if (auto const *entry =
171 std::ranges::find(detail::charset_map, set, project_first);
172 entry != std::cend(detail::charset_map))
173 {
174 return {entry->second, 1};
175 }
176
177 if (auto const *entry =
178 std::ranges::find(detail::extended_charset_map, set, project_first);
179 entry != std::cend(detail::extended_charset_map))
180 {
181 return {entry->second, 2};
182 }
183
184 return encode_character_set(character_set(charset::us_ascii));
185}
186
187//* =========================================================================
190//* =========================================================================
191TERMINALPP_EXPORT
192std::ostream &operator<<(std::ostream &out, character_set const &set);
193
194} // namespace terminalpp
195
196namespace std {
197
198template <>
199struct hash<terminalpp::character_set>
200{
202 using result_type = std::size_t;
203
204 [[nodiscard]] result_type operator()(argument_type const &cs) const noexcept
205 {
206 return hash_value(cs);
207 }
208};
209
210} // namespace std
A structure that represents a character set.
Definition character_set.hpp:44
constexpr character_set(charset const &set) noexcept
Initialises the character set the given value.
Definition character_set.hpp:55
constexpr friend auto operator<=>(character_set const &lhs, character_set const &rhs) noexcept=default
Relational operators for character sets.
constexpr character_set() noexcept
Initialises the character set to its default value.
Definition character_set.hpp:48
friend std::size_t hash_value(character_set const &cs) noexcept
Hash function.
Definition character_set.hpp:69