#ifndef JWT_STRING_VIEW_IPP #define JWT_STRING_VIEW_IPP namespace jwt { template auto basic_string_view::find( const CharT* str, size_type pos, size_type n) const noexcept -> size_type { assert (str); assert (n < (len_ - pos) && "Comparison size out of bounds"); if (n == 0) { return pos <= len_ ? pos : npos; } if (n <= len_) { for (; pos <= (len_ - n); ++pos) { if (traits_type::eq(data_[pos], str[0]) && traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) { return pos; } } } return npos; } template auto basic_string_view::rfind( const CharT* str, size_type pos, size_type n) const noexcept -> size_type { assert (str); assert (pos < len_ && "Position out of bounds"); if (n <= len_) { pos = std::min(len_ - n, pos); do { if (traits_type::eq(data_[pos], str[0]) && traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) { return pos; } } while (pos-- != 0); } return npos; } template auto basic_string_view::find( const CharT ch, size_type pos) const noexcept -> size_type { if (pos < len_) { for (size_type i = pos; i < len_; ++i) { if (traits_type::eq(data_[i], ch)) return i; } } return npos; } template auto basic_string_view::rfind( const CharT ch, size_type pos) const noexcept -> size_type { if (pos < len_) { do { if (traits_type::eq(data_[pos], ch)) { return pos; } } while (pos-- != 0); } return npos; } template auto basic_string_view::find_first_of( const CharT* str, size_type pos, size_type count) const noexcept -> size_type { assert (str); for (size_type i = pos; i < len_; ++i) { auto p = traits_type::find(str, count, data_[i]); if (p) { return i; } } return npos; } template auto basic_string_view::find_last_of( const CharT* str, size_type pos, size_type count) const noexcept -> size_type { assert (str); assert (pos < len_ && "Position must be within the bounds of the view"); size_type siz = len_; if (siz && count) { siz = std::min(pos, siz); do { auto p = traits_type::find(str, count, data_[siz]); if (p) { return siz; } } while (siz-- != 0); } return npos; } template auto basic_string_view::find_first_not_of( const CharT* str, size_type pos, size_type n) const noexcept -> size_type { assert (str); assert (pos < len_&& "Position must be within the bounds of the view"); for (size_type i = pos; i < len_; ++i) { auto p = traits_type::find(str, n, data_[i]); if (not p) return i; } return npos; } template auto basic_string_view::find_last_not_of( const CharT* str, size_type pos, size_type n) const noexcept -> size_type { assert (str); assert (pos < len_ && "Position must be within the bounds of the view"); do { for (size_type i = 0; i < n; ++i) { if (not traits_type::eq(data_[pos], str[i])) return pos; } } while (pos-- != 0); return npos; } template auto basic_string_view::find_first_not_of( CharT ch, size_type pos) const noexcept -> size_type { assert (pos < len_&& "Position must be within the bounds of the view"); for (size_type i = pos; i < len_; ++i) { if (not traits_type::eq(data_[i], ch)) return i; } return npos; } template auto basic_string_view::find_last_not_of( CharT ch, size_type pos) const noexcept -> size_type { assert (pos < len_ && "Position must be within the bounds of the view"); do { if (not traits_type::eq(data_[pos], ch)) return pos; } while (pos-- != 0); return npos; } // Comparison Operators template bool operator== (basic_string_view a, basic_string_view b) noexcept { if (a.length() != b.length()) return false; using traits_type = typename basic_string_view::traits_type; using size_type = typename basic_string_view::size_type; for (size_type i = 0; i < a.length(); ++i) { if (not traits_type::eq(a[i], b[i])) return false; } return true; } template bool operator!= (basic_string_view a, basic_string_view b) noexcept { return not ( a == b ); } template bool operator< (basic_string_view a, basic_string_view b) noexcept { return a.compare(b) < 0; } template bool operator> (basic_string_view a, basic_string_view b) noexcept { return a.compare(b) > 0; } template bool operator<= (basic_string_view a, basic_string_view b) noexcept { return a.compare(b) <= 0; } template bool operator>= (basic_string_view a, basic_string_view b) noexcept { return a.compare(b) >= 0; } template std::ostream& operator<< (std::ostream& os, basic_string_view sv) { os.write(sv.data(), sv.length()); return os; } namespace { /* * Copy of gcc implementation of murmurhash * hash_bytes.cc */ inline size_t unaligned_load(const char* p) { std::size_t result; std::memcpy(&result, p, sizeof(result)); return result; } inline size_t hash_bytes(const void* ptr, size_t len, size_t seed) { const size_t m = 0x5bd1e995; size_t hash = seed ^ len; const char* buf = static_cast(ptr); // Mix 4 bytes at a time into the hash. while(len >= 4) { size_t k = unaligned_load(buf); k *= m; k ^= k >> 24; k *= m; hash *= m; hash ^= k; buf += 4; len -= 4; } // Handle the last few bytes of the input array. switch(len) { case 3: hash ^= static_cast(buf[2]) << 16; //FALLTHROUGH case 2: hash ^= static_cast(buf[1]) << 8; //FALLTHROUGH case 1: hash ^= static_cast(buf[0]); hash *= m; }; // Do a few final mixes of the hash. hash ^= hash >> 13; hash *= m; hash ^= hash >> 15; return hash; } } } // END namespace jwt /// Provide a hash specialization namespace std { template <> struct hash { size_t operator()(const jwt::string_view& sv) const { return jwt::hash_bytes((void*)sv.data(), sv.length(), static_cast(0xc70f6907UL)); } }; } #endif