Line data Source code
1 : #pragma once
2 :
3 : #include <libassert/assert.hpp>
4 :
5 : #include <algorithm>
6 : #include <charconv>
7 : #include <concepts>
8 : #include <iterator>
9 : #include <ranges>
10 : #include <spanstream>
11 : #include <string_view>
12 : #include <vector>
13 :
14 : template <typename... T> void parse(std::string_view const s, T &...values) {
15 : std::ispanstream iss(s);
16 : (iss >> ... >> values);
17 : }
18 :
19 1208 : template <typename T> std::vector<T> parseRange(std::string_view const s) {
20 1208 : std::ispanstream iss(s);
21 1208 : return {std::istream_iterator<T>(iss), std::istream_iterator<T>{}};
22 1208 : }
23 :
24 : template <typename T, std::output_iterator<T const &> OutIt>
25 3 : OutIt parseRange(std::string_view const s, OutIt out) {
26 3 : std::ispanstream iss(s);
27 3 : return std::copy(std::istream_iterator<T>(iss), std::istream_iterator<T>{}, out);
28 3 : }
29 :
30 101963 : template <std::integral T> T parseInt(std::string_view const s) {
31 101963 : T out{};
32 101963 : auto [ptr, ec] = std::from_chars(s.begin(), s.end(), out);
33 101963 : ASSERT(ec == std::errc(), s);
34 101963 : return out;
35 101963 : }
36 :
37 17544 : template <std::integral T> T parseInt(std::ranges::input_range auto &&r) {
38 17544 : std::string_view s(r);
39 17544 : return parseInt<T>(s);
40 17544 : }
41 :
42 624 : template <std::integral T> T parseHexInt(std::string_view const s) {
43 624 : T out{};
44 624 : auto [ptr, ec] = std::from_chars(s.begin(), s.end(), out, 16);
45 624 : ASSERT(ec == std::errc(), s);
46 624 : return out;
47 624 : }
48 :
49 : template <std::integral T, std::output_iterator<T const &> OutIt>
50 11299 : void parseIntegerRange(std::string_view const s, OutIt out, char const delim = ',') {
51 77736 : for (auto it = s.begin(); it < s.end(); ++it, ++out) {
52 66437 : auto startIt = it;
53 66437 : it = std::find(startIt, s.end(), delim);
54 66437 : *out = parseInt<T>({startIt, it});
55 66437 : }
56 11299 : }
57 :
58 : template <std::integral T>
59 8601 : std::vector<T> parseIntegerRange(std::string_view const s, char const delim = ',') {
60 8601 : std::vector<T> result;
61 8601 : parseIntegerRange<T>(s, std::back_inserter(result), delim);
62 8601 : return result;
63 8601 : }
64 :
65 : template <std::integral T, std::ranges::output_range<T const &> R>
66 496 : void parseIntegerRange(std::string_view const s, R &r, char const delim = ',') {
67 496 : auto outIt = std::ranges::begin(r);
68 1488 : for (auto it = s.begin(); it < s.end(); ++it) {
69 992 : ASSERT(outIt != std::ranges::end(r));
70 992 : auto startIt = it;
71 992 : it = std::find(startIt, s.end(), delim);
72 992 : *outIt++ = parseInt<T>({startIt, it});
73 992 : }
74 496 : }
75 :
76 2270 : inline std::vector<std::string_view> split(std::string_view const s, char const delim = ',') {
77 2270 : std::vector<std::string_view> result;
78 16791 : for (auto it = s.begin(); it < s.end(); ++it) {
79 14521 : auto startIt = it;
80 14521 : it = std::find(startIt, s.end(), delim);
81 14521 : result.emplace_back(startIt, it);
82 14521 : }
83 2270 : return result;
84 2270 : }
|