message: [crispy] move strntoul here
diff: namespace crispy {
  +constexpr unsigned long strntoul(char const* _data, size_t _count, char const** _eptr, unsigned _base = 10)
  +{
  + constexpr auto values = std::string_view{"0123456789ABCDEF"};
  + constexpr auto lowerLetters = std::string_view{"abcdef"};
  +
  + unsigned long result = 0;
  + while (_count != 0)
  + {
  + if (auto const i = values.find(*_data); i != values.npos && i < _base)
  + {
  + result *= _base;
  + result += i;
  + ++_data;
  + --_count;
  + }
  + else if (auto const i = lowerLetters.find(*_data); i != lowerLetters.npos && _base == 16)
  + {
  + result *= _base;
  + result += i;
  + ++_data;
  + --_count;
  + }
  + else
  + return 0;
  + }
  +
  + if (_eptr)
  + *_eptr = _data;
  +
  + return result;
  +}
  +
  inline std::vector<std::string_view> split(std::string_view const& _text, char _delimiter)
  {
  auto res = std::vector<std::string_view>{};
  @@ -25,7 +57,7 @@ inline std::vector<std::string_view> split(std::string_view const& _text, char
  return res;
  }
  -std::unordered_map<std::string_view, std::string_view> splitKeyValuePairs(std::string_view const& _text, char _delimiter)
  +inline std::unordered_map<std::string_view, std::string_view> splitKeyValuePairs(std::string_view const& _text, char _delimiter)
  {
  // params := pair (':' pair)*
  // pair := TEXT '=' TEXT
  