From 68f26b42f6c43c751781970d901c6c4fae778400 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 16 Jun 2017 15:23:18 -0700 Subject: [PATCH] add util::string_view --- src/util/CMakeLists.txt | 1 + src/util/string_view.cpp | 23 ++ src/util/string_view.h | 606 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 630 insertions(+) create mode 100644 src/util/string_view.cpp create mode 100644 src/util/string_view.h diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 42d814d..3f0fea9 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -28,6 +28,7 @@ set(sources bit_intrinsics.cpp is_swappable.cpp optional.cpp soft_float.cpp + string_view.cpp variant.cpp void_t.cpp) add_library(util STATIC ${sources}) diff --git a/src/util/string_view.cpp b/src/util/string_view.cpp new file mode 100644 index 0000000..143f3e5 --- /dev/null +++ b/src/util/string_view.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#include "string_view.h" diff --git a/src/util/string_view.h b/src/util/string_view.h new file mode 100644 index 0000000..577f379 --- /dev/null +++ b/src/util/string_view.h @@ -0,0 +1,606 @@ +/* +* Copyright 2017 Jacob Lifshay +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +*/ +// derived and relicensed from +// https://github.com/programmerjake/quick-shell/blob/d963cb5057e7013b8ff64db1cc42f464e3195644/util/string_view.h +#ifndef UTIL_STRING_VIEW_H_ +#define UTIL_STRING_VIEW_H_ + +#include +#include +#include +#include +#include +#include + +namespace vulkan_cpu +{ +namespace util +{ +template > +class basic_string_view +{ +public: + typedef Traits_type traits_type; + typedef Char_type value_type; + typedef Char_type *pointer; + typedef const Char_type *const_pointer; + typedef Char_type &reference; + typedef const Char_type &const_reference; + typedef const Char_type *const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + static constexpr std::size_t npos = static_cast(-1); + +private: + const Char_type *string_pointer; + std::size_t string_size; + +private: + static constexpr std::size_t constexpr_min(std::size_t a, std::size_t b) noexcept + { + return a < b ? a : b; + } + +public: + constexpr basic_string_view() noexcept : string_pointer(nullptr), string_size(0) + { + } + constexpr basic_string_view(const basic_string_view &) noexcept = default; + template + constexpr basic_string_view( + const std::basic_string &str) noexcept + : string_pointer(str.data()), + string_size(str.size()) + { + } + constexpr basic_string_view(const Char_type *str, std::size_t count) noexcept + : string_pointer(str), + string_size(count) + { + } + basic_string_view(const Char_type *str) + : string_pointer(str), string_size(traits_type::length(str)) + { + } + basic_string_view &operator=(const basic_string_view &) noexcept = default; + constexpr const_iterator begin() const noexcept + { + return string_pointer; + } + constexpr const_iterator cbegin() const noexcept + { + return string_pointer; + } + constexpr const_iterator end() const noexcept + { + return string_pointer + string_size; + } + constexpr const_iterator cend() const noexcept + { + return string_pointer + string_size; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator(end()); + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(end()); + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator(begin()); + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(begin()); + } + constexpr const Char_type &at(std::size_t index) const + { + return index >= string_size ? + throw std::out_of_range("out of range in util::basic_string_view::at") : + string_pointer[index]; + } + constexpr const Char_type &operator[](std::size_t index) const noexcept + { + return string_pointer[index]; + } + constexpr const Char_type &front() const noexcept + { + return string_pointer[0]; + } + constexpr const Char_type &back() const noexcept + { + return string_pointer[string_size - 1]; + } + constexpr const Char_type *data() const noexcept + { + return string_pointer; + } + constexpr std::size_t size() const noexcept + { + return string_size; + } + constexpr std::size_t length() const noexcept + { + return string_size; + } + constexpr std::size_t max_size() const noexcept + { + return static_cast(-1) / sizeof(Char_type); + } + constexpr bool empty() const noexcept + { + return string_size == 0; + } + void remove_prefix(std::size_t n) noexcept + { + string_pointer += n; + string_size -= n; + } + void remove_suffix(std::size_t n) noexcept + { + string_size -= n; + } + void swap(basic_string_view &rt) noexcept + { + basic_string_view temp = *this; + *this = rt; + rt = temp; + } + std::size_t copy(Char_type *dest, std::size_t count, std::size_t pos = 0) const + { + if(pos > count) + throw std::out_of_range("out of range in util::basic_string_view::copy"); + count = constexpr_min(count, string_size - pos); + for(std::size_t i = 0; i < count; i++) + traits_type::assign(dest[i], string_pointer[i + pos]); + return count; + } + constexpr basic_string_view substr(std::size_t pos = 0, std::size_t count = npos) const + { + return pos > string_size ? + throw std::out_of_range("out of range in util::basic_string_view::substr") : + basic_string_view(string_pointer + pos, constexpr_min(count, string_size - pos)); + } + +private: + constexpr int compareHelper(int compare_result, basic_string_view rt) const noexcept + { + return compare_result != 0 ? compare_result : string_size > rt.string_size ? + 1 : + string_size < rt.string_size ? -1 : 0; + } + +public: + constexpr int compare(basic_string_view rt) const noexcept + { + return compareHelper( + traits_type::compare( + string_pointer, rt.string_pointer, constexpr_min(string_size, rt.string_size)), + rt); + } + constexpr int compare(std::size_t pos1, std::size_t count1, basic_string_view rt) const + { + return substr(pos1, count1).compare(rt); + } + constexpr int compare(std::size_t pos1, + std::size_t count1, + basic_string_view rt, + std::size_t pos2, + std::size_t count2) const + { + return substr(pos1, count1).compare(rt.substr(pos2, count2)); + } + constexpr int compare(const Char_type *rt) const + { + return compare(basic_string_view(rt)); + } + constexpr int compare(std::size_t pos1, std::size_t count1, const Char_type *rt) const + { + return substr(pos1, count1).compare(rt); + } + constexpr int compare(std::size_t pos1, + std::size_t count1, + basic_string_view rt, + std::size_t count2) const + { + return substr(pos1, count1).compare(basic_string_view(rt, count2)); + } + std::size_t find(basic_string_view v, std::size_t pos = 0) const noexcept + { + if(pos > string_size) + return npos; + for(; string_size - pos < v.string_size; pos++) + { + bool found = true; + for(std::size_t i = 0; i < v.string_size; i++) + { + if(!traits_type::eq(string_pointer[i + pos], v.string_pointer[i])) + { + found = false; + break; + } + } + if(found) + return pos; + } + return npos; + } + std::size_t find(Char_type c, std::size_t pos = 0) const noexcept + { + return find(basic_string_view(std::addressof(c), 1), pos); + } + std::size_t find(const Char_type *s, std::size_t pos, std::size_t count) const noexcept + { + return find(basic_string_view(s, count), pos); + } + std::size_t find(const Char_type *s, std::size_t pos = 0) const + { + return find(basic_string_view(s), pos); + } + std::size_t rfind(basic_string_view v, std::size_t pos = npos) const noexcept + { + if(v.string_size > string_size) + return npos; + pos = constexpr_min(pos, string_size - v.string_size); + for(std::size_t i = 0, count = pos; i < count; i++, pos--) + { + bool found = true; + for(std::size_t i = 0; i < v.string_size; i++) + { + if(!traits_type::eq(string_pointer[i + pos], v.string_pointer[i])) + { + found = false; + break; + } + } + if(found) + return pos; + } + return npos; + } + std::size_t rfind(Char_type c, std::size_t pos = npos) const noexcept + { + return rfind(basic_string_view(std::addressof(c), 1), pos); + } + std::size_t rfind(const Char_type *s, std::size_t pos, std::size_t count) const noexcept + { + return rfind(basic_string_view(s, count), pos); + } + std::size_t rfind(const Char_type *s, std::size_t pos = npos) const + { + return rfind(basic_string_view(s), pos); + } + std::size_t find_first_of(basic_string_view v, std::size_t pos = 0) const noexcept + { + for(; pos < string_size; pos++) + { + if(v.find(string_pointer[pos]) != npos) + return pos; + } + return npos; + } + std::size_t find_first_of(Char_type v, std::size_t pos = 0) const noexcept + { + return find(v, pos); + } + std::size_t find_first_of(const Char_type *s, std::size_t pos, std::size_t count) const noexcept + { + return find_first_of(basic_string_view(s, count), pos); + } + std::size_t find_first_of(const Char_type *s, std::size_t pos = 0) const + { + return find_first_of(basic_string_view(s), pos); + } + std::size_t find_first_not_of(basic_string_view v, std::size_t pos = 0) const noexcept + { + for(; pos < string_size; pos++) + { + if(v.find(string_pointer[pos]) == npos) + return pos; + } + return npos; + } + std::size_t find_first_not_of(Char_type v, std::size_t pos = 0) const noexcept + { + return find_first_not_of(basic_string_view(std::addressof(v), 1), pos); + } + std::size_t find_first_not_of(const Char_type *s, std::size_t pos, std::size_t count) const + noexcept + { + return find_first_not_of(basic_string_view(s, count), pos); + } + std::size_t find_first_not_of(const Char_type *s, std::size_t pos = 0) const + { + return find_first_not_of(basic_string_view(s), pos); + } + std::size_t find_last_of(basic_string_view v, std::size_t pos = npos) const noexcept + { + if(empty()) + return npos; + pos = constexpr_min(pos, string_size - 1); + for(std::size_t i = 0, count = pos; i < count; i++, pos--) + { + if(v.find(string_pointer[pos]) != npos) + return pos; + } + return npos; + } + std::size_t find_last_of(Char_type v, std::size_t pos = npos) const noexcept + { + return rfind(v, pos); + } + std::size_t find_last_of(const Char_type *s, std::size_t pos, std::size_t count) const noexcept + { + return find_last_of(basic_string_view(s, count), pos); + } + std::size_t find_last_of(const Char_type *s, std::size_t pos = npos) const + { + return find_last_of(basic_string_view(s), pos); + } + std::size_t find_last_not_of(basic_string_view v, std::size_t pos = npos) const noexcept + { + if(empty()) + return npos; + pos = constexpr_min(pos, string_size - 1); + for(std::size_t i = 0, count = pos; i < count; i++, pos--) + { + if(v.find(string_pointer[pos]) == npos) + return pos; + } + return npos; + } + std::size_t find_last_not_of(Char_type v, std::size_t pos = npos) const noexcept + { + return find_last_not_of(basic_string_view(std::addressof(v), 1), pos); + } + std::size_t find_last_not_of(const Char_type *s, std::size_t pos, std::size_t count) const + noexcept + { + return find_last_not_of(basic_string_view(s, count), pos); + } + std::size_t find_last_not_of(const Char_type *s, std::size_t pos = npos) const + { + return find_last_not_of(basic_string_view(s), pos); + } + template + explicit operator std::basic_string() const + { + return std::basic_string(string_pointer, string_size); + } + template + friend std::basic_string &operator+=( + std::basic_string &l, basic_string_view r) + { + l.append(r.data(), r.size()); + return l; + } + template + friend std::basic_string &operator+=( + std::basic_string &&l, basic_string_view r) + { + l.append(r.data(), r.size()); + return l; + } +}; + +template +constexpr std::size_t basic_string_view::npos; + +template +constexpr bool operator==(basic_string_view a, + basic_string_view b) noexcept +{ + return a.size() == b.size() && Traits_type::compare(a.data(), b.data(), a.size()) == 0; +} + +template +constexpr bool operator!=(basic_string_view a, + basic_string_view b) noexcept +{ + return !operator==(a, b); +} + +template +constexpr bool operator<=(basic_string_view a, + basic_string_view b) noexcept +{ + return a.compare(b) <= 0; +} + +template +constexpr bool operator>=(basic_string_view a, + basic_string_view b) noexcept +{ + return a.compare(b) >= 0; +} + +template +constexpr bool operator<(basic_string_view a, + basic_string_view b) noexcept +{ + return a.compare(b) < 0; +} + +template +constexpr bool operator>(basic_string_view a, + basic_string_view b) noexcept +{ + return a.compare(b) > 0; +} + +#define QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_NO_ALLOCATOR(...) \ + template \ + bool operator==(__VA_ARGS__) noexcept \ + { \ + return operator==(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator!=(__VA_ARGS__) noexcept \ + { \ + return operator!=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator<=(__VA_ARGS__) noexcept \ + { \ + return operator<=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator>=(__VA_ARGS__) noexcept \ + { \ + return operator>=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator<(__VA_ARGS__) noexcept \ + { \ + return operator<(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator>(__VA_ARGS__) noexcept \ + { \ + return operator>(static_cast>(a), \ + static_cast>(b)); \ + } + +#define QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_WITH_ALLOCATOR(...) \ + template \ + bool operator==(__VA_ARGS__) noexcept \ + { \ + return operator==(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator!=(__VA_ARGS__) noexcept \ + { \ + return operator!=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator<=(__VA_ARGS__) noexcept \ + { \ + return operator<=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator>=(__VA_ARGS__) noexcept \ + { \ + return operator>=(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator<(__VA_ARGS__) noexcept \ + { \ + return operator<(static_cast>(a), \ + static_cast>(b)); \ + } \ + \ + template \ + bool operator>(__VA_ARGS__) noexcept \ + { \ + return operator>(static_cast>(a), \ + static_cast>(b)); \ + } + +QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_NO_ALLOCATOR( + const Char_type *a, basic_string_view b) +QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_NO_ALLOCATOR( + basic_string_view a, const Char_type *b) +QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_WITH_ALLOCATOR( + basic_string_view a, + std::basic_string b) +QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_WITH_ALLOCATOR( + std::basic_string a, + basic_string_view b) +#undef QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_NO_ALLOCATOR +#undef QUICK_SHELL_UTIL_STRING_VIEW_GENERATE_EXTRA_COMPARE_OPERATORS_WITH_ALLOCATOR + +template +std::basic_ostream &operator<<( + std::basic_ostream &os, basic_string_view v) +{ + os << static_cast>(v); + return os; +} + +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; + +inline namespace literals +{ +inline namespace string_view_literals +{ +constexpr string_view operator"" _sv(const char *str, std::size_t length) noexcept +{ + return string_view(str, length); +} +constexpr wstring_view operator"" _sv(const wchar_t *str, std::size_t length) noexcept +{ + return wstring_view(str, length); +} +constexpr u16string_view operator"" _sv(const char16_t *str, std::size_t length) noexcept +{ + return u16string_view(str, length); +} +constexpr u32string_view operator"" _sv(const char32_t *str, std::size_t length) noexcept +{ + return u32string_view(str, length); +} +} +} +} +} + +namespace std +{ +template +struct hash> +{ + std::size_t operator()(vulkan_cpu::util::basic_string_view v) const + { + typedef std::basic_string stringType; + return std::hash(static_cast(v)); + } +}; +} + +#endif /* UTIL_STRING_VIEW_H_ */ \ No newline at end of file -- 2.30.2