Skip to content

Commit e66263a

Browse files
committed
Implement search functionality
1 parent cc27bf0 commit e66263a

9 files changed

Lines changed: 673 additions & 57 deletions

File tree

‎include/iris/format.hpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef IRIS_FORMAT_HPP
22
#define IRIS_FORMAT_HPP
33

4+
// SPDX-License-Identifier: MIT
5+
46
#include <iris/format_traits.hpp>
57

68
#include <format>

‎include/iris/format_traits.hpp‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#ifndef IRIS_ZZ_FORMAT_TRAITS_HPP
1+
#ifndef IRIS_ZZ_FORMAT_TRAITS_HPP
22
#define IRIS_ZZ_FORMAT_TRAITS_HPP
33

44
// SPDX-License-Identifier: MIT
@@ -16,8 +16,11 @@ template<>
1616
struct format_traits<char>
1717
{
1818
using char_type = char;
19+
static constexpr char_type square_brace_open = '[';
20+
static constexpr char_type paren_close = ')';
1921
static constexpr char_type brace_open = '{';
2022
static constexpr char_type brace_close = '}';
23+
static constexpr char_type comma = ',';
2124

2225
template<class T>
2326
static constexpr std::basic_format_string<char_type, std::type_identity_t<T>>
@@ -28,8 +31,11 @@ template<>
2831
struct format_traits<wchar_t>
2932
{
3033
using char_type = wchar_t;
34+
static constexpr char_type square_brace_open = L'[';
35+
static constexpr char_type paren_close = L')';
3136
static constexpr char_type brace_open = L'{';
3237
static constexpr char_type brace_close = L'}';
38+
static constexpr char_type comma = L',';
3339

3440
template<class T>
3541
static constexpr std::basic_format_string<char_type, std::type_identity_t<T>>

‎include/iris/interval.hpp‎

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#ifndef IRIS_INTERVAL_HPP
2+
#define IRIS_INTERVAL_HPP
3+
4+
// SPDX-License-Identifier: MIT
5+
6+
#include <iris/config.hpp>
7+
#include <iris/format_traits.hpp>
8+
9+
#include <iterator>
10+
#include <format>
11+
#include <concepts>
12+
#include <compare>
13+
#include <type_traits>
14+
#include <utility>
15+
16+
namespace iris {
17+
18+
template<std::signed_integral T>
19+
struct interval
20+
{
21+
using value_type = T;
22+
T left, right;
23+
24+
[[nodiscard]]
25+
constexpr bool operator==(interval const&) const noexcept = default;
26+
27+
[[nodiscard]]
28+
constexpr std::strong_ordering operator<=>(interval const&) const noexcept = default;
29+
};
30+
31+
template<std::size_t I, class T>
32+
[[nodiscard]] constexpr T& get(interval<T>& iv) noexcept
33+
{
34+
static_assert(I == 0 || I == 1);
35+
if constexpr (I == 0) { return iv.left; } else { return iv.right; }
36+
}
37+
template<std::size_t I, class T>
38+
[[nodiscard]] constexpr T const& get(interval<T> const& iv) noexcept
39+
{
40+
static_assert(I == 0 || I == 1);
41+
if constexpr (I == 0) { return iv.left; } else { return iv.right; }
42+
}
43+
template<std::size_t I, class T>
44+
[[nodiscard]] constexpr T&& get(interval<T>&& iv) noexcept
45+
{
46+
static_assert(I == 0 || I == 1);
47+
if constexpr (I == 0) { return std::move(iv).left; } else { return std::move(iv).right; }
48+
}
49+
template<std::size_t I, class T>
50+
[[nodiscard]] constexpr T const&& get(interval<T> const&& iv) noexcept
51+
{
52+
static_assert(I == 0 || I == 1);
53+
if constexpr (I == 0) { return std::move(iv).left; } else { return std::move(iv).right; }
54+
}
55+
56+
} // iris
57+
58+
template<class T>
59+
struct std::tuple_size<iris::interval<T>>
60+
: std::integral_constant<std::size_t, 2>
61+
{};
62+
63+
template<std::size_t I, class T>
64+
struct std::tuple_element<I, iris::interval<T>>
65+
{
66+
using type = T;
67+
};
68+
69+
template<class T, class CharT>
70+
struct std::formatter<iris::interval<T>, CharT>
71+
{
72+
[[nodiscard]] constexpr std::basic_format_parse_context<CharT>::const_iterator
73+
parse(std::basic_format_parse_context<CharT>& ctx)
74+
{
75+
auto const first = ctx.begin();
76+
if (first == ctx.end()) return first;
77+
if (*first == iris::format_traits<CharT>::brace_close) return first;
78+
79+
// Bound the search to this replacement field
80+
auto const close_it = std::find(
81+
first, ctx.end(),
82+
iris::format_traits<CharT>::brace_close
83+
);
84+
if (close_it == ctx.end()) {
85+
throw std::format_error("unterminated format specifier");
86+
}
87+
88+
auto const comma_it = std::find(
89+
first, close_it,
90+
iris::format_traits<CharT>::comma
91+
);
92+
if (comma_it == close_it) {
93+
throw std::format_error("expected ',' in format specifier");
94+
}
95+
96+
{
97+
std::basic_format_parse_context<CharT> left_ctx{
98+
std::basic_string_view<CharT>{first, comma_it}, 1
99+
};
100+
if (left_fmt_.parse(left_ctx) != left_ctx.end()) {
101+
throw std::format_error("trailing characters in left format specifier");
102+
}
103+
}
104+
{
105+
std::basic_format_parse_context<CharT> right_ctx{
106+
std::basic_string_view<CharT>{std::next(comma_it), close_it}, 1
107+
};
108+
if (right_fmt_.parse(right_ctx) != right_ctx.end()) {
109+
throw std::format_error("trailing characters in right format specifier");
110+
}
111+
}
112+
return close_it;
113+
}
114+
115+
template<class Ctx>
116+
Ctx::iterator format(iris::interval<T> const& iv, Ctx& ctx) const
117+
{
118+
ctx.advance_to(std::format_to(ctx.out(), "{}", iris::format_traits<CharT>::square_brace_open));
119+
left_fmt_.format(iv.left, ctx);
120+
ctx.advance_to(std::format_to(ctx.out(), "{}", iris::format_traits<CharT>::comma));
121+
right_fmt_.format(iv.right, ctx);
122+
return std::format_to(ctx.out(), "{}", iris::format_traits<CharT>::paren_close);
123+
}
124+
125+
private:
126+
std::formatter<T, CharT> left_fmt_, right_fmt_;
127+
};
128+
129+
#endif

0 commit comments

Comments
 (0)