#ifndef JWT_STRING_VIEW_HPP #define JWT_STRING_VIEW_HPP #include #include #include namespace jwt { /* * Implements c++17 string_view. * Could have used boost::string_ref, but wanted to * keep boost dependency off from this library. */ template < typename CharT, typename Traits = std::char_traits > class basic_string_view { public: // Member Types using traits_type = std::char_traits; using value_type = CharT; using pointer = const CharT*; using const_pointer = const CharT*; using reference = const CharT&; using const_reference = const CharT&; using iterator = const CharT*; using const_iterator = const CharT*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using size_type = size_t; using difference_type = std::ptrdiff_t; static constexpr size_type npos = size_type(-1); public: // 'tors /// The default constructor; basic_string_view() = default; /// Construct from string literal basic_string_view(const CharT* str) noexcept : data_(str) , len_(str ? traits_type::length(str) : 0) { } /// Construct from CharT pointer and provided length basic_string_view(const CharT* p, size_type len) noexcept : data_(p) , len_(len) { } /// Construct from std::string template basic_string_view( const std::basic_string& str) noexcept : data_(str.data()) , len_(str.length()) { } /// Copy constructor basic_string_view(const basic_string_view&) = default; /// Assignment operator basic_string_view& operator=(const basic_string_view&) = default; /// Destructor ~basic_string_view() { data_ = nullptr; len_ = 0; } public: // Exposed APIs /// Iterator Member Functions iterator begin() const noexcept { return data_; } iterator end() const noexcept { return data_ + len_; } iterator rbegin() const noexcept { return reverse_iterator(end()); } iterator rend() const noexcept { return reverse_iterator(begin()); } const_iterator cbegin() const noexcept { return begin(); } const_iterator cend() const noexcept { return end(); } const_iterator crbegin() const noexcept { return rbegin(); } const_iterator crend() const noexcept { return rend(); } /// Capacity Member Functions size_type length() const noexcept { return len_; } size_type size() const noexcept { return len_; } size_type max_size() const noexcept { return (npos - sizeof(size_type) - sizeof(void*)) / sizeof(value_type) / 4; } bool empty() const noexcept { return len_ == 0; } /// Element Access Member Functions const_reference operator[](size_type idx) const noexcept { return data_[idx]; } // NOTE: 'at' not supported //CharT at(size_type idx) const; const_reference front() const noexcept { return data_[0]; } const_reference back() const noexcept { return data_[len_ - 1]; } const_pointer data() const noexcept { return data_; } /// Modifier Member Functions void remove_prefix(size_type n) noexcept { assert (n < len_ && "Data would point out of bounds"); data_ += n; len_ -= n; } void remove_suffix(size_type n) noexcept { assert (n < len_ && "Suffix length more than data length"); len_ -= n; } void swap(basic_string_view& other) { std::swap(data_, other.data_); std::swap(len_, other.len_); } /// String Operation Member Functions template explicit operator std::basic_string() const { return {data_, len_}; } template > std::basic_string to_string(const Allocator& alloc = Allocator()) const { return {data_, len_, alloc}; } // NOTE: Does not throw size_type copy(CharT* dest, size_type n, size_type pos = 0) const noexcept { assert (pos < len_ && n < len_); size_type to_copy = std::min(n, len_ - pos); for (size_type i = 0; i < to_copy; i++) { dest[i] = data_[i + pos]; } return to_copy; } // NOTE: Does not throw basic_string_view substr(size_type pos, size_type n = npos) const noexcept { assert (pos < len_ && "Start position should be less than length of the view"); assert (n == npos ? 1 : (n - pos) < len_ && "Substring length asked for is more than the view length"); if (n == npos) n = len_; return basic_string_view{data_ + pos, n}; } /// Comparison Member Functions int compare(const basic_string_view& other) const noexcept { int ret = traits_type::compare(data_, other.data_, std::min(len_, other.len_)); if (ret == 0) { ret = compare_length(len_, other.len_); } return ret; } int compare(size_type pos, size_type n, basic_string_view other) const noexcept { return substr(pos, n).compare(other); } int compare(const CharT* str) const noexcept { return compare(basic_string_view{str}); } int compare(size_type pos, size_type n, const CharT* str) const noexcept { return compare(pos, n, basic_string_view{str}); } int compare(size_type pos, size_type n1, const CharT* str, size_type n2) const noexcept { return compare(pos, n1, basic_string_view{str, n2}); } /// Find operations size_type find(const CharT* str, size_type pos, size_type n) const noexcept; size_type find(const CharT ch, size_type pos) const noexcept; size_type find(basic_string_view sv, size_type pos = 0) const noexcept { return find(sv.data(), pos, sv.length()); } size_type find(const CharT* str, size_type pos = 0) const noexcept { return find(str, pos, traits_type::length(str)); } size_type rfind(const CharT* str, size_type pos, size_type n) const noexcept; size_type rfind(const CharT ch, size_type pos) const noexcept; size_type rfind(basic_string_view sv, size_type pos = 0) const noexcept { return rfind(sv.data(), pos, sv.length()); } size_type rfind(const CharT* str, size_type pos = 0) const noexcept { return rfind(str, pos, traits_type::length(str)); } size_type find_first_of(const CharT* str, size_type pos, size_type count) const noexcept; size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept { return find_first_of(str.data(), pos, str.length()); } size_type find_first_of(CharT ch, size_type pos = 0) const noexcept { return find(ch, pos); } size_type find_first_of(const CharT* str, size_type pos = 0) const noexcept { return find_first_of(str, pos, traits_type::length(str)); } size_type find_last_of(const CharT* str, size_type pos, size_type count) const noexcept; size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept { return find_last_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length()); } size_type find_last_of(CharT ch, size_type pos = npos) const noexcept { return rfind(ch, pos == npos ? len_ - 1 : pos); } size_type find_last_of(const CharT* str, size_type pos = npos) const noexcept { return find_last_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str)); } size_type find_first_not_of(const CharT* str, size_type pos, size_type n) const noexcept; size_type find_first_not_of(CharT ch, size_type pos) const noexcept; size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept { return find_first_not_of(str.data(), pos, str.length()); } size_type find_first_not_of(const CharT* str, size_type pos = 0) const noexcept { return find_first_not_of(str, pos, traits_type::length(str)); } size_type find_last_not_of(const CharT* str, size_type pos, size_type n) const noexcept; size_type find_last_not_of(CharT ch, size_type pos) const noexcept; size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept { return find_last_not_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length()); } size_type find_last_not_of(const CharT* str, size_type pos = npos) const noexcept { return find_last_not_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str)); } /// Comparison operators Member Functions /* friend bool operator== (basic_string_view a, basic_string_view b) noexcept; friend bool operator!= (basic_string_view a, basic_string_view b) noexcept; friend bool operator< (basic_string_view a, basic_string_view b) noexcept; friend bool operator> (basic_string_view a, basic_string_view b) noexcept; friend bool operator<= (basic_string_view a, basic_string_view b) noexcept; friend bool operator>= (basic_string_view a, basic_string_view b) noexcept; */ private: // private implementations static constexpr int compare_length(size_type n1, size_type n2) noexcept { return static_cast(n1 - n2) > std::numeric_limits::max() ? std::numeric_limits::max() : static_cast(n1 - n2) < std::numeric_limits::min() ? std::numeric_limits::min() : static_cast(n1 - n2) ; } private: // This is what view is basically... const char* data_ = nullptr; size_type len_ = 0; }; /// Helper typedef using string_view = basic_string_view; } // END namespace jwt #include "jwt/impl/string_view.ipp" #endif