src/io/fastin/lib.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "../../util/alias/others/lib.hpp" | ||
| 4 | #include "../../util/traits/math/lib.hpp" | ||
| 5 | #ifdef __linux__ | ||
| 6 | #include <sys/mman.h> | ||
| 7 | #include <sys/stat.h> | ||
| 8 | #endif | ||
| 9 | |||
| 10 | namespace tifa_libs { | ||
| 11 | |||
| 12 | struct fastin_data { | ||
| 13 | CEXP static u32 BUF = 0x200005; | ||
| 14 | FILE* f_ = nullptr; | ||
| 15 | #ifdef __linux__ | ||
| 16 | chr *bg, *ed, *p; | ||
| 17 | struct stat Fl; | ||
| 18 | |||
| 19 | 32104 | void rebind(FILE* f = nullptr) NE { | |
| 20 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" | ||
| 21 |
2/2✓ Branch 0 taken 16036 times.
✓ Branch 1 taken 16068 times.
|
32104 | if (!f_) munmap(bg, Fl.st_size + 1); |
| 22 | #pragma GCC diagnostic warning "-Wmaybe-uninitialized" | ||
| 23 |
2/2✓ Branch 0 taken 16036 times.
✓ Branch 1 taken 16068 times.
|
32104 | if (!f) return; |
| 24 | 16068 | auto fd = fileno(f_ = f); | |
| 25 | 16068 | fstat(fd, &Fl); | |
| 26 | 16068 | p = (bg = (chr*)mmap(nullptr, Fl.st_size + 4, PROT_READ, MAP_PRIVATE, fd, 0)); | |
| 27 | 16068 | ed = bg + Fl.st_size; | |
| 28 | 16068 | madvise(bg, Fl.st_size + 4, MADV_SEQUENTIAL); | |
| 29 | } | ||
| 30 | |||
| 31 | 20139493677 | ND bool iseof() CNE { return p == ed; } | |
| 32 | 16036 | ~fastin_data() NE { rebind(); } | |
| 33 | #else | ||
| 34 | // NOLINTNEXTLINE(modernize-avoid-c-arrays) | ||
| 35 | chr buf[BUF], *ed, *p; | ||
| 36 | |||
| 37 | void rebind(FILE* f) NE { f_ = f, p = ed = buf; } | ||
| 38 | ND bool iseof() NE { | ||
| 39 | if (p == ed) [[unlikely]] | ||
| 40 | ed = (p = buf) + fread(buf, 1, BUF, f_); | ||
| 41 | return p == ed; | ||
| 42 | } | ||
| 43 | #endif | ||
| 44 | |||
| 45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16036 times.
|
16036 | fastin_data(FILE* f = stdin) NE { assert(f), rebind(f); } |
| 46 | fastin_data(fastin_data CR) = delete; | ||
| 47 | fastin_data& operator=(fastin_data CR) = delete; | ||
| 48 | }; | ||
| 49 | // clang-format off | ||
| 50 | enum FIN_SET : u8 { FS_NEWLINE = 1, FS_SPACE = 2, FS_NEG = 4, FS_NUM = 8, FS_ALPHA = 16, FS_OTHERS = 32 }; | ||
| 51 | // clang-format on | ||
| 52 | template <u32 charset> | ||
| 53 | class fastin { | ||
| 54 | fastin_data& data; | ||
| 55 | |||
| 56 | static CEXP bool is_cntrl(chr c) NE { | ||
| 57 | if CEXP (charset & FS_OTHERS) return iscntrl(c); | ||
| 58 | else if CEXP (charset & FS_NEWLINE) return c < 32; | ||
| 59 | else return false; | ||
| 60 | } | ||
| 61 | 878672468 | static CEXP bool is_cntrls(chr c) NE { | |
| 62 | 263738826 | if CEXP (charset & FS_OTHERS) return !isgraph(c); | |
| 63 | 614933642 | else if CEXP (charset & (FS_NEWLINE | FS_SPACE)) return c <= 32; | |
| 64 | else return false; | ||
| 65 | } | ||
| 66 | 20005062064 | static CEXP bool is_digit(chr c) NE { | |
| 67 | 9228493 | if CEXP (charset & (FS_ALPHA | FS_OTHERS)) return isdigit(c); | |
| 68 | else if CEXP (!(charset & FS_NUM)) return false; | ||
| 69 | 19958245442 | else if CEXP (!(charset & FS_NEG)) return c > 32; | |
| 70 | 37588129 | else return c >= 48; | |
| 71 | } | ||
| 72 | 67778592 | static CEXP bool is_neg_digit(chr c) NE { | |
| 73 | if CEXP (!(charset & FS_NEG)) return is_digit(c); | ||
| 74 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | else if CEXP (charset & (FS_ALPHA | FS_OTHERS)) return c == '-' || isdigit(c); |
| 75 | 67778584 | else return c > 32; | |
| 76 | } | ||
| 77 | #ifdef __linux__ | ||
| 78 | template <bool ignore_space = true> | ||
| 79 | 16770785 | void read_str(strn& n) NE { | |
| 80 | chr* l; | ||
| 81 | if CEXP (ignore_space) { | ||
| 82 | 16770785 | skip_cntrls(), l = data.p; | |
| 83 |
6/6void tifa_libs::fastin<11u>::read_str<true>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 1 taken 339952855 times.
✓ Branch 2 taken 3748017 times.
void tifa_libs::fastin<15u>::read_str<true>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 1 taken 246325651 times.
✓ Branch 2 taken 8705728 times.
void tifa_libs::fastin<63u>::read_str<true>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 1 taken 245502225 times.
✓ Branch 2 taken 4317040 times.
|
848551516 | while (!is_cntrls(*data.p)) ++data.p; |
| 84 | } else { | ||
| 85 | skip_cntrl(), l = data.p; | ||
| 86 | while (!is_cntrl(*data.p)) ++data.p; | ||
| 87 | } | ||
| 88 | 16770785 | n.assign(l, data.p); | |
| 89 | 16770785 | } | |
| 90 | #else | ||
| 91 | template <bool ignore_space> | ||
| 92 | void read_str(strn& n) NE { | ||
| 93 | if CEXP (n.clear(); ignore_space) { | ||
| 94 | n.push_back(skip_cntrls().get()); | ||
| 95 | while (!is_cntrls(peek())) n.push_back(get()); | ||
| 96 | } else { | ||
| 97 | n.push_back(skip_cntrl().get()); | ||
| 98 | while (!is_cntrl(peek())) n.push_back(get()); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | #endif | ||
| 102 | public: | ||
| 103 | 48108 | fastin(fastin_data& data) NE : data(data) {} | |
| 104 | fastin(fastin CR) = delete; | ||
| 105 | fastin& operator=(fastin CR) = delete; | ||
| 106 | |||
| 107 | 20136850908 | chr peek() NE { | |
| 108 |
4/6tifa_libs::fastin<11u>::peek():
✗ Branch 1 not taken.
✓ Branch 2 taken 19965741105 times.
tifa_libs::fastin<15u>::peek():
✗ Branch 1 not taken.
✓ Branch 2 taken 147961733 times.
tifa_libs::fastin<63u>::peek():
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 23148065 times.
|
20136850908 | if (data.iseof()) [[unlikely]] |
| 109 | 5 | return EOF; | |
| 110 | 20136850903 | return *data.p; | |
| 111 | } | ||
| 112 | 12120165701 | chr get_unchk() NE { return *data.p++; } | |
| 113 | 2642769 | chr get() NE { | |
| 114 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2642769 times.
|
2642769 | if (data.iseof()) [[unlikely]] |
| 115 | ✗ | return EOF; | |
| 116 | 2642769 | return get_unchk(); | |
| 117 | } | ||
| 118 | #define SKIP(name, pred) \ | ||
| 119 | fastin& skip_##name() NE { \ | ||
| 120 | while (pred(peek())) get_unchk(); \ | ||
| 121 | return *this; \ | ||
| 122 | } | ||
| 123 | SKIP(cntrl, is_cntrl) | ||
| 124 |
5/6tifa_libs::fastin<11u>::skip_cntrls():
✓ Branch 3 taken 3747646 times.
✓ Branch 4 taken 3748017 times.
tifa_libs::fastin<15u>::skip_cntrls():
✗ Branch 3 not taken.
✓ Branch 4 taken 8705728 times.
tifa_libs::fastin<63u>::skip_cntrls():
✓ Branch 3 taken 6959752 times.
✓ Branch 4 taken 6959809 times.
|
30120952 | SKIP(cntrls, is_cntrls) |
| 125 |
4/4tifa_libs::fastin<11u>::skip_ndigit():
✓ Branch 3 taken 6014223198 times.
✓ Branch 4 taken 6014238713 times.
tifa_libs::fastin<63u>::skip_ndigit():
✓ Branch 3 taken 2642769 times.
✓ Branch 4 taken 2642777 times.
|
12033747457 | SKIP(ndigit, !is_digit) |
| 126 |
3/4tifa_libs::fastin<15u>::skip_nnegdigit():
✓ Branch 3 taken 33889292 times.
✓ Branch 4 taken 33889292 times.
tifa_libs::fastin<63u>::skip_nnegdigit():
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
67778592 | SKIP(nnegdigit, !is_neg_digit) |
| 127 | #undef SKIP | ||
| 128 | template <class T> | ||
| 129 | requires(imost64_c<T> && !char_c<T>) | ||
| 130 | 6042065058 | fastin& operator>>(T& n) NE { | |
| 131 | if CEXP (std::same_as<T, bool>) n = skip_ndigit().get() != '0'; | ||
| 132 | else { | ||
| 133 | 6042065058 | n = 0; | |
| 134 | 6042065058 | bool is_neg = false; | |
| 135 |
9/12tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><int>(int&):
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><long>(long&):
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><short>(short&):
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
|
25183570 | if CEXP ((charset & FS_NEG) && std::signed_integral<T>) is_neg = (skip_nnegdigit().peek() == '-' && get_unchk()); |
| 136 | 6016881488 | else skip_ndigit(); | |
| 137 | 6042065058 | std::conditional_t<sizeof(T) < sizeof(u32), u32, to_uint_t<T>> n_ = 0; | |
| 138 | #ifdef __linux__ | ||
| 139 | // clang-format off | ||
| 140 | #define _ {while (~STR2U16[*(u16*)data.p]) (n_ *= 100) += STR2U16[*(u16*)data.p], data.p += 2; if (is_digit(peek())) (n_ *= 10) += get_unchk() & 15;} | ||
| 141 |
74/108tifa_libs::fastin<11u>& tifa_libs::fastin<11u>::operator>><int>(int&):
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 18 taken 37 times.
✓ Branch 19 taken 18 times.
✓ Branch 22 taken 11 times.
✓ Branch 23 taken 7 times.
tifa_libs::fastin<11u>& tifa_libs::fastin<11u>::operator>><unsigned int>(unsigned int&):
✓ Branch 0 taken 135976809 times.
✓ Branch 1 taken 129617340 times.
✓ Branch 4 taken 135976809 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 225880473 times.
✓ Branch 10 taken 135976809 times.
✓ Branch 13 taken 44228892 times.
✓ Branch 14 taken 91747917 times.
✓ Branch 18 taken 318210979 times.
✓ Branch 19 taken 129617340 times.
✓ Branch 22 taken 85387396 times.
✓ Branch 23 taken 44229944 times.
tifa_libs::fastin<11u>& tifa_libs::fastin<11u>::operator>><unsigned long>(unsigned long&):
✓ Branch 0 taken 1453247 times.
✓ Branch 1 taken 1653279 times.
✓ Branch 4 taken 1453247 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 2903329 times.
✓ Branch 10 taken 1453247 times.
✓ Branch 13 taken 503069 times.
✓ Branch 14 taken 950178 times.
✓ Branch 18 taken 4046060 times.
✓ Branch 19 taken 1653279 times.
✓ Branch 22 taken 1148978 times.
✓ Branch 23 taken 504301 times.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><int>(int&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 1 time.
✓ Branch 13 taken 1 time.
✗ Branch 14 not taken.
✓ Branch 18 taken 5 times.
✓ Branch 19 taken 1 time.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 time.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><long>(long&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 1 time.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 time.
✓ Branch 18 taken 9 times.
✓ Branch 19 taken 1 time.
✓ Branch 22 taken 1 time.
✗ Branch 23 not taken.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><short>(short&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 1 time.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 time.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 1 time.
✓ Branch 22 taken 1 time.
✗ Branch 23 not taken.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><unsigned int>(unsigned int&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 18 taken 5 times.
✓ Branch 19 taken 2 times.
✓ Branch 22 taken 1 time.
✓ Branch 23 taken 1 time.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><unsigned long>(unsigned long&):
✓ Branch 0 taken 1300163 times.
✓ Branch 1 taken 1342608 times.
✓ Branch 4 taken 1300163 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 71431 times.
✓ Branch 10 taken 1300163 times.
✓ Branch 13 taken 133732 times.
✓ Branch 14 taken 1166431 times.
✓ Branch 18 taken 222668 times.
✓ Branch 19 taken 1342608 times.
✓ Branch 22 taken 1210541 times.
✓ Branch 23 taken 132067 times.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><unsigned short>(unsigned short&):
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
|
27113868374 | if ((usz)data.p & 1) { if (is_digit(peek())) [[likely]] { (n_ *= 10) += get_unchk() & 15; _ } } else _; |
| 142 | #undef _ | ||
| 143 | // clang-format on | ||
| 144 | #else | ||
| 145 | while (is_digit(peek())) (n_ *= 10) += get_unchk() & 15; | ||
| 146 | #endif | ||
| 147 | if CEXP (sint_c<T>) | ||
| 148 |
7/8tifa_libs::fastin<11u>& tifa_libs::fastin<11u>::operator>><int>(int&):
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><int>(int&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><long>(long&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
tifa_libs::fastin<63u>& tifa_libs::fastin<63u>::operator>><short>(short&):
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
5488103648 | if (is_neg) n_ = -n_; |
| 149 | 6042065058 | n = (T)n_; | |
| 150 | } | ||
| 151 | 6042065058 | return *this; | |
| 152 | } | ||
| 153 | fastin& operator>>(std::floating_point auto& n) NE { | ||
| 154 | static strn s; | ||
| 155 | (*this >> s), std::from_chars(begin(s).base(), end(s).base(), n); | ||
| 156 | return *this; | ||
| 157 | } | ||
| 158 | //! ignore cntrl and space | ||
| 159 | 2642769 | fastin& operator>>(char_c auto& n) NE { | |
| 160 | 2642769 | n = skip_cntrls().get(); | |
| 161 | 2642769 | return *this; | |
| 162 | } | ||
| 163 | 16770785 | fastin& operator>>(strn& n) NE { | |
| 164 | 16770785 | read_str<true>(n); | |
| 165 | 16770785 | return *this; | |
| 166 | } | ||
| 167 | fastin& getline(strn& n) NE { | ||
| 168 | read_str<false>(n); | ||
| 169 | return *this; | ||
| 170 | } | ||
| 171 | //! NOT ignore cntrl and space | ||
| 172 | fastin& strict_read(char_c auto& n) NE { | ||
| 173 | n = get(); | ||
| 174 | return *this; | ||
| 175 | } | ||
| 176 | fastin& operator>>(fastin& (*func)(fastin&)) NE { return func(*this); } | ||
| 177 | }; | ||
| 178 | inline fastin_data fid_stdin; | ||
| 179 | inline fastin<FS_NEWLINE | FS_SPACE | FS_NEG | FS_NUM | FS_ALPHA | FS_OTHERS> fin(fid_stdin); | ||
| 180 | inline fastin<FS_NEWLINE | FS_SPACE | FS_NEG | FS_NUM> fin_int(fid_stdin); | ||
| 181 | inline fastin<FS_NEWLINE | FS_SPACE | FS_NUM> fin_uint(fid_stdin); | ||
| 182 | template <u32 w> | ||
| 183 | inline fastin<w>& ws(fastin<w>& f) NE { return f.skip_cntrls(); } | ||
| 184 | |||
| 185 | } // namespace tifa_libs | ||
| 186 |