-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetlines.hpp
More file actions
132 lines (104 loc) · 3.49 KB
/
getlines.hpp
File metadata and controls
132 lines (104 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <fstream>
#include <ranges>
#include <string>
namespace utils {
class getlines_view : public std::ranges::view_interface<getlines_view> {
std::istream* in_;
std::string str_{};
char delim_;
struct cursor {
getlines_view* rng_ = nullptr;
public:
cursor() = default;
explicit cursor(getlines_view* rng)
: rng_(rng) {}
void next() {
rng_->next();
}
std::string& read() const noexcept {
return rng_->str_;
}
bool equal(std::default_sentinel_t) const {
return !rng_->in_;
}
bool equal(cursor that) const {
return !rng_->in_ == !that.rng_->in_;
}
};
public:
class iterator {
using Base = const std::string;
cursor cursor_;
public:
using iterator_category = std::input_iterator_tag;
using reference = Base&;
using value_type = Base;
using difference_type = std::ranges::range_difference_t<Base>;
iterator() = default;
iterator(cursor cursor)
: cursor_{ cursor } {}
decltype(auto) operator*() {
return cursor_.read();
}
decltype(auto) operator*() const {
return cursor_.read();
}
iterator& operator++() {
cursor_.next();
return *this;
}
void operator++(int) {
(void)operator++();
}
friend bool operator==(const iterator& x,
const iterator& y) {
return x.cursor_.equal(y.cursor_);
}
friend bool operator!=(const iterator& x,
const iterator& y) {
return !(x == y);
}
friend bool operator==(const iterator& x,
const std::default_sentinel_t sentinel) {
return x.cursor_.equal(sentinel);
}
friend bool operator!=(const iterator& x,
const std::default_sentinel_t sentinel) {
return !(x == sentinel);
}
};
public:
using iterator_t = iterator;
using sentinel_t = std::default_sentinel_t;
getlines_view() = default;
getlines_view(std::istream& in, char delim = '\n')
: in_(&in), delim_(delim) {
this->next();
}
void next() {
if (!std::getline(*in_, str_, delim_)) {
in_ = nullptr;
}
}
auto begin() {
return iterator{ cursor{ this } };
}
auto end() const noexcept {
return std::default_sentinel;
}
};
namespace views {
namespace detail {
struct getlines_fn {
getlines_view operator()(std::istream& in, char delim = '\n') const {
return getlines_view{ in, delim };
}
template <typename T>
friend constexpr auto operator|(T&& v, getlines_fn fn) {
return fn(std::forward<T>(v));
}
};
} // namespace detail
inline constexpr auto getlines = detail::getlines_fn{};
} // namespace views
} // namespace utils