commons 0.1.5
Header-only C++23 library of common/shared types for the C++ libraries
Loading...
Searching...
No Matches
icon.hpp
Go to the documentation of this file.
1#pragma once
2
24
26#include <commons/types.hpp>
27
28#include <format>
29#include <optional>
30#include <ostream>
31#include <stdexcept>
32#include <string>
33#include <string_view>
34
35namespace comms {
36
43struct Icon {
46 static constexpr usize capacity = 64;
47
48 // -- construction -------------------------------------------------------
49
50 constexpr Icon() = default;
51
56 [[nodiscard]] static constexpr Icon from(const std::string_view value) {
57 if (value.size() > capacity) {
58 throw std::length_error{"commons: Icon value exceeds capacity"};
59 }
60 const auto parsed = parse(value);
61 if (!parsed) {
62 throw std::invalid_argument{"commons: invalid Icon value (expected 'set:name')"};
63 }
64 return *parsed;
65 }
66
69 [[nodiscard]] static constexpr Icon from(const std::string_view set,
70 const std::string_view name) {
71 const usize total = set.size() + 1U + name.size();
72 if (total > capacity) {
73 throw std::length_error{"commons: Icon 'set:name' exceeds capacity"};
74 }
75 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
76 char tmp[capacity]{};
77 usize k = 0;
78 for (const char c : set) {
79 tmp[k++] = c;
80 }
81 tmp[k++] = ':';
82 for (const char c : name) {
83 tmp[k++] = c;
84 }
85 const auto parsed = parse(std::string_view{static_cast<const char*>(tmp), total});
86 if (!parsed) {
87 throw std::invalid_argument{
88 "commons: invalid Icon set/name (expected non-empty parts)"};
89 }
90 return *parsed;
91 }
92
96 [[nodiscard]] static constexpr std::optional<Icon> parse(const std::string_view value) {
97 if (value.size() > capacity) {
98 return std::nullopt;
99 }
100 usize colon = std::string_view::npos;
101 usize colons = 0;
102 for (usize i = 0; i < value.size(); ++i) {
103 if (value[i] == ':') {
104 colon = i;
105 ++colons;
106 }
107 }
108 if (colons != 1 || colon == 0 || colon + 1 == value.size()) {
109 return std::nullopt;
110 }
111 Icon icon;
112 for (usize i = 0; i < value.size(); ++i) {
113 icon.buf_[i] = value[i];
114 }
115 icon.len_ = static_cast<u8>(value.size());
116 return icon;
117 }
118
119 // -- accessors ----------------------------------------------------------
120
122 [[nodiscard]] constexpr std::string_view value() const noexcept {
123 return std::string_view{static_cast<const char*>(buf_), len_};
124 }
125
127 [[nodiscard]] constexpr std::string_view set() const noexcept {
128 const auto v = value();
129 return v.substr(0, colon_index(v));
130 }
131
133 [[nodiscard]] constexpr std::string_view name() const noexcept {
134 const auto v = value();
135 const auto pos = colon_index(v);
136 return pos == std::string_view::npos ? std::string_view{} : v.substr(pos + 1);
137 }
138
139 [[nodiscard]] constexpr bool empty() const noexcept {
140 return len_ == 0;
141 }
142
144 [[nodiscard]] std::string to_string() const {
145 return std::string{value()};
146 }
147
148 bool operator==(const Icon&) const = default;
149
150private:
154 [[nodiscard]] static constexpr usize colon_index(std::string_view v) noexcept {
155 for (usize i = 0; i < v.size(); ++i) {
156 if (v[i] == ':') {
157 return i;
158 }
159 }
160 return std::string_view::npos;
161 }
162
163 // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
164 char buf_[capacity]{};
165 u8 len_ = 0;
166};
167
170template <FixedString Set>
172 static constexpr std::string_view set = Set.view();
173};
174
175// ---------------------------------------------------------------------------
176// Text output: to_string + std::ostream insertion. (std::format support is the
177// std::formatter specialization below, outside namespace comms.)
178// ---------------------------------------------------------------------------
179
181[[nodiscard]] inline std::string to_string(const Icon& i) {
182 return i.to_string();
183}
184
185inline std::ostream& operator<<(std::ostream& os, const Icon& i) {
186 return os << i.value();
187}
188
189} // namespace comms
190
191// ---------------------------------------------------------------------------
192// std::format support. The specialization lives in namespace std (the primary
193// template is visible), like nlohmann's adl_serializer route in json.hpp.
194// ---------------------------------------------------------------------------
195
196// This spec-less formatter reads no member state, but `std::formatter` requires
197// `parse`/`format` to be non-static members — so silence the convert-to-static
198// suggestion here.
199// NOLINTBEGIN(readability-convert-member-functions-to-static)
200
202template <>
203struct std::formatter<comms::Icon> {
204 constexpr auto parse(const std::format_parse_context& ctx) {
205 const auto* it = ctx.begin();
206 if (it != ctx.end() && *it != '}') {
207 throw std::format_error("commons: Icon takes no format spec");
208 }
209 return it;
210 }
211
212 auto format(const comms::Icon& i, std::format_context& ctx) const {
213 return std::format_to(ctx.out(), "{}", i.value());
214 }
215};
216
217// NOLINTEND(readability-convert-member-functions-to-static)
std::string to_string(const Color &c)
Color as its canonical hex string (#RRGGBB, or #RRGGBBAA when not opaque).
Definition color.hpp:1388
NTTP-friendly fixed-size string usable as a non-type template parameter.
An Iconify icon identifier — a set:name pair such as mdi:abacus.
Definition icon.hpp:43
constexpr std::string_view value() const noexcept
The whole set:name string.
Definition icon.hpp:122
static constexpr Icon from(const std::string_view set, const std::string_view name)
Build by joining set and name with a :.
Definition icon.hpp:69
constexpr std::string_view name() const noexcept
The icon name (after the :), e.g. abacus.
Definition icon.hpp:133
static constexpr Icon from(const std::string_view value)
Build from a whole set:name value, e.g.
Definition icon.hpp:56
constexpr std::string_view set() const noexcept
The set prefix (before the :), e.g. mdi.
Definition icon.hpp:127
std::string to_string() const
The canonical set:name string as a std::string.
Definition icon.hpp:144
static constexpr usize capacity
Inline buffer capacity.
Definition icon.hpp:46
static constexpr std::optional< Icon > parse(const std::string_view value)
Non-throwing validation: returns the Icon for a well-formed value (exactly one :, non-empty set and n...
Definition icon.hpp:96
Base for a predefined Iconify set: carries the set name as a string_view.
Definition icon.hpp:171
Fixed-width numeric aliases shared across the C++ libraries.
std::uint8_t u8
Unsigned 8-bit integer.
Definition types.hpp:22
std::size_t usize
Unsigned size type (std::size_t).
Definition types.hpp:43