diff --git a/include/jwt/impl/.stack_alloc.ipp.swp b/include/jwt/impl/.stack_alloc.ipp.swp deleted file mode 100644 index 1f07458..0000000 Binary files a/include/jwt/impl/.stack_alloc.ipp.swp and /dev/null differ diff --git a/include/jwt/impl/string_view.ipp b/include/jwt/impl/string_view.ipp new file mode 100644 index 0000000..e797776 --- /dev/null +++ b/include/jwt/impl/string_view.ipp @@ -0,0 +1,248 @@ +#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; +} + +} // END namespace jwt + +#endif diff --git a/include/jwt/jwt.hpp b/include/jwt/jwt.hpp new file mode 100644 index 0000000..86e5904 --- /dev/null +++ b/include/jwt/jwt.hpp @@ -0,0 +1,24 @@ +#ifndef JWT_HPP +#define JWT_HPP + +namespace jwt { + +enum class algorithm +{ + NONE = 0, + HS256, + HS384, + HS512, + RS256, + RS384, + RS512, + ES256, + ES384, + ES512, + TERM, +}; + + +} // END namespace jwt + +#endif diff --git a/include/jwt/string_view.hpp b/include/jwt/string_view.hpp new file mode 100644 index 0000000..f7c7500 --- /dev/null +++ b/include/jwt/string_view.hpp @@ -0,0 +1,349 @@ +#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; +}; + + +} // END namespace jwt + +#include "jwt/impl/string_view.ipp" + +#endif diff --git a/include/jwt/test_sv b/include/jwt/test_sv new file mode 100755 index 0000000..4c91707 Binary files /dev/null and b/include/jwt/test_sv differ diff --git a/include/jwt/test_sv.cc b/include/jwt/test_sv.cc new file mode 100644 index 0000000..439726e --- /dev/null +++ b/include/jwt/test_sv.cc @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include "./string_view.hpp" + +using string_view = jwt::basic_string_view; + +void basic_cons() +{ + // Default construction + string_view sv{}; + assert (sv.length() == 0 && "Size must be zero for default constructor"); + + // Construction from string literal + string_view sv2{"Arun Muralidharan"}; + assert (sv2.length() == strlen("Arun Muralidharan") && "Lengths must match"); + + const char* haystack = "some really big data with infinite objects...."; + + // Construct using part of data + string_view sv3{haystack, 4}; + assert (sv3.length() == 4 && "Partial construction is not ok"); + assert (sv3.to_string() == "some" && "Partial strings are not equal"); + + return; +} + +void iterator_test() +{ + string_view sv{"Arun Muralidharan"}; + for (auto c : sv) std::cout << c; + std::cout << std::endl; + return; +} + +void str_operations() +{ + string_view sv{"Arun Muralidharan"}; + string_view tmp = sv; + sv.remove_prefix(5); + assert (sv.to_string() == "Muralidharan" && "Remove prefix failed"); + + sv = tmp; + sv.remove_suffix(strlen("Muralidharan")); + assert (sv.to_string() == "Arun " && "Remove suffix failed"); + + sv=tmp; + { + std::unique_ptr dst{new char[32]}; + sv.copy(dst.get(), 6, 0); + dst[6] = '\0'; + assert (strlen(dst.get()) == 6 && "Copy Failed-1"); + assert (std::string{dst.get()} == "Arun M" && "Copy Failed-2"); + + sv.copy(dst.get(), 8, 4); + dst[8] = '\0'; + assert (strlen(dst.get()) == 8 && "Middle copy failed-1"); + assert (std::string{dst.get()} == " Muralid" && "Middle copy failed-2"); + } + + { + auto ss1 = sv.substr(0, 4); + assert (ss1.to_string() == "Arun" && "Substr failed - 1"); + + auto ss2 = sv.substr(1, 3); + assert (ss2.to_string() == "run" && "Substr failed - 2"); + + auto ss3 = sv.substr(0); + assert (ss3.length() == sv.length() && "Substr failed - 3"); + } + + return; +} + +void find_oper() +{ + string_view sv{"Arun Muralidharan"}; + auto pos = sv.find("Arun", 0, 4); + assert (pos == 0 && "Arun not found in sv"); + + pos = sv.find("arun", 0, 4); + assert (pos == string_view::npos && "arun is not there in sv"); + + sv = "This has a, in it."; + pos = sv.find_first_of(",", 0, 1); + assert (pos != string_view::npos); + assert (pos == 10 && "Comma not found at correct place"); + + pos = sv.find_first_of(",", 10, 1); + assert (pos != string_view::npos); + assert (pos == 10 && "Comma not found at correct place"); + + pos = sv.find_first_of(":", 10, 1); + assert (pos == string_view::npos); + + pos = sv.find_last_of(",", 5, 1); + assert (pos == string_view::npos); + + pos = sv.find_last_of(",", sv.length() - 1, 1); + assert (pos != string_view::npos); + assert (pos == 10 && "Comma not found at correct place"); + + pos = sv.find_first_of(".", 0, 1); + assert (pos == sv.length() - 1 && "Dot not found at correct place"); + + pos = sv.find_last_of(".", sv.length() - 2, 1); + assert (pos == string_view::npos); + + pos = sv.find_last_of(".", sv.length() - 1, 1); + assert (pos == sv.length() - 1); + + sv = "Some string :<> with some ??? pattern --**"; + + pos = sv.rfind("???", sv.length() - 1, 3); + assert (pos != string_view::npos && "??? not found"); + assert (pos == 26 && "??? not found at the correct place"); + + sv = "ATCGTTCACGRRRTCGGGGACGTC"; + + pos = sv.find_first_not_of("ATCG"); + assert (pos != string_view::npos); + assert (pos == 10); + + return; +} + +void conversions() +{ + auto c2sv = [](int num) -> string_view { + switch (num) { + case 1: return "one"; + case 2: return "two"; + case 3: return "three"; + default: return "many"; + }; + }; + + auto res = c2sv(2); + assert (res.to_string() == "two"); + + auto s2sv = [](std::string s) { + return s; + }; + + s2sv(static_cast(res)); +} + +void comparisons() +{ + string_view s1{"Apple"}; + string_view s2{"Orange"}; + + assert (s1 != s2 && "Two string views are not equal"); + assert (s2 > s1 && "Orange is lexicographically bigger than Apple"); + + s2 = "Apples"; + assert (s2 > s1 && "Because Apples is plural"); +} + +int main() { + basic_cons(); + iterator_test(); + str_operations(); + find_oper(); + conversions(); + comparisons(); + return 0; +};