Пытаюсь сделать простенький парсер входных данных из string_view, разбирая токены через хеш-функцию:
#include <string_view>
#include <format>
#include <iostream>
#include <ranges>
/******************************************************************************/
inline constexpr size_t _hash (const char *str, size_t n=0) {
// FNV-1a
size_t res{0xcbf29ce484222325}, prime{0x00000100000001b3};
// vvvvvvvvvvvvvvv здесь была ошибка
// for (size_t i{0}; i < n or str[i]; ++i) {
for (size_t i{0}; (i < n) or (n == 0 and str[i]); ++i) { // *fixed* FTGJ
res = res ^ str[i];
res = res * prime;
}
return res;
}
inline constexpr size_t operator ""_hash (const char *str, size_t n) {
return _hash (str, n);
};
inline constexpr size_t _hash (const std::string_view &strv) {
return _hash (strv.data(), strv.size());
};
auto to_string_view = [] (auto &&r) -> std::string_view {
return std::string_view(&*r.begin(), std::ranges::distance(r));
};
auto not_empty = [](auto x) -> bool {
return not x.empty();
};
void parse_key_flags(std::string_view input) {
std::cout<<std::format("\"TOKEN\"_hash = {}\n", "TOKEN"_hash);
for (auto entry : input
| std::views::split(' ')
| std::views::filter(not_empty)
) {
auto row = entry | std::views::split(':')
| std::views::filter(not_empty)
| std::views::transform(to_string_view);
auto key = row.front();
std::cout<<std::format("key = \"{}\", tokens:\n", key);
for (auto flag : row
| std::views::drop(1)
| std::views::transform(to_string_view)
) {
std::cout<<std::format("\t\"{}\" (hash = {})",flag, _hash(flag));
switch (_hash(flag)) {
default:
std::cout<<" -> [FAIL]\n";
continue;
case "TOKEN"_hash:
std::cout<<" -> [TOKEN]\n";
}
}
}
}
Пытаюсь парсить строку
int main() {
std::string_view input = "KEY1:TOKEN KEY2:TOKEN:FAIL";
parse_key_flags(input);
}
"TOKEN"_hash = 15101299456084321266 // ok
key = "KEY1", tokens:
"TOKEN" (hash = 10353157926286166668) -> [FAIL] // WAT?
key = "KEY2", tokens:
"TOKEN" (hash = 5196937941191725884) -> [FAIL] // WUT!?
"FAIL" (hash = 3215402482899151853) -> [FAIL]