diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hash-util.cc | 38 | ||||
-rw-r--r-- | src/hash-util.h | 47 | ||||
-rw-r--r-- | src/string-view.cc | 196 | ||||
-rw-r--r-- | src/string-view.h | 288 | ||||
-rw-r--r-- | src/test-string-view.cc | 412 |
5 files changed, 981 insertions, 0 deletions
diff --git a/src/hash-util.cc b/src/hash-util.cc new file mode 100644 index 00000000..c0c55a21 --- /dev/null +++ b/src/hash-util.cc @@ -0,0 +1,38 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hash-util.h" + +#include "config.h" + +namespace wabt { + +// Hash combiner from: +// http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine + +hash_code hash_combine(hash_code seed, hash_code y) { +#if SIZEOF_SIZE_T == 4 + constexpr hash_code magic = 0x9e3779b9; +#elif SIZEOF_SIZE_T == 8 + constexpr hash_code magic = 0x9e3779b97f4a7c16; +#else +#error "weird sizeof size_t" +#endif + seed ^= y + magic + (seed << 6) + (seed >> 2); + return seed; +} + +} // namespace wabt diff --git a/src/hash-util.h b/src/hash-util.h new file mode 100644 index 00000000..0cf68758 --- /dev/null +++ b/src/hash-util.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WABT_HASH_UTIL_H_ +#define WABT_HASH_UTIL_H_ + +#include <cstdlib> +#include <functional> + +namespace wabt { + +typedef std::size_t hash_code; + +inline hash_code hash_combine() { return 0; } +inline hash_code hash_combine(hash_code seed) { return seed; } +hash_code hash_combine(hash_code x, hash_code y); + +template <typename T, typename... U> +inline hash_code hash_combine(const T& first, const U&... rest) { + return hash_combine(hash_combine(rest...), std::hash<T>()(first)); +} + +template <typename It> +inline hash_code hash_range(It first, It last) { + hash_code result = 0; + for (auto iter = first; iter != last; ++iter) { + result = hash_combine(result, *iter); + } + return result; +} + +} // namespace wabt + +#endif // WABT_HASH_UTIL_H_ diff --git a/src/string-view.cc b/src/string-view.cc new file mode 100644 index 00000000..dc72f7dd --- /dev/null +++ b/src/string-view.cc @@ -0,0 +1,196 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string-view.h" + +#include <algorithm> +#include <limits> + +namespace wabt { + +void string_view::remove_prefix(size_type n) { + assert(n <= size_); + data_ += n; + size_ -= n; +} + +void string_view::remove_suffix(size_type n) { + assert(n <= size_); + size_ -= n; +} + +void string_view::swap(string_view& s) noexcept { + std::swap(data_, s.data_); + std::swap(size_, s.size_); +} + +string_view::operator std::string() const { + return std::string(data_, size_); +} + +std::string string_view::to_string() const { + return std::string(data_, size_); +} + +constexpr string_view::size_type string_view::max_size() const noexcept { + return std::numeric_limits<size_type>::max(); +} + +string_view::size_type string_view::copy(char* s, + size_type n, + size_type pos) const { + assert(pos <= size_); + size_t count = std::min(n, size_ - pos); + traits_type::copy(s, data_ + pos, count); + return count; +} + +string_view string_view::substr(size_type pos, size_type n) const { + assert(pos <= size_); + size_t count = std::min(n, size_ - pos); + return string_view(data_ + pos, count); +} + +int string_view::compare(string_view s) const noexcept { + size_type rlen = std::min(size_, s.size_); + int result = traits_type::compare(data_, s.data_, rlen); + if (result != 0 || size_ == s.size_) { + return result; + } + return size_ < s.size_ ? -1 : 1; +} + +int string_view::compare(size_type pos1, size_type n1, string_view s) const { + return substr(pos1, n1).compare(s); +} + +int string_view::compare(size_type pos1, + size_type n1, + string_view s, + size_type pos2, + size_type n2) const { + return substr(pos1, n1).compare(s.substr(pos2, n2)); +} + +int string_view::compare(const char* s) const { + return compare(string_view(s)); +} + +int string_view::compare(size_type pos1, size_type n1, const char* s) const { + return substr(pos1, n1).compare(string_view(s)); +} + +int string_view::compare(size_type pos1, + size_type n1, + const char* s, + size_type n2) const { + return substr(pos1, n1).compare(string_view(s, n2)); +} + +string_view::size_type string_view::find(string_view s, size_type pos) const + noexcept { + pos = std::min(pos, size_); + const_iterator iter = std::search(begin() + pos, end(), s.begin(), s.end()); + return iter == end() ? npos : iter - begin(); +} + +string_view::size_type string_view::find(char c, size_type pos) const noexcept { + return find(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find(const char* s, + size_type pos, + size_type n) const { + return find(string_view(s, n), pos); +} + +string_view::size_type string_view::find(const char* s, size_type pos) const { + return find(string_view(s), pos); +} + +string_view::size_type string_view::rfind(string_view s, size_type pos) const + noexcept { + pos = std::min(pos, size_ - s.size_); + reverse_iterator iter = std::search(reverse_iterator(begin() + pos + s.size_), + rend(), s.rbegin(), s.rend()); + return iter == rend() ? npos : (rend() - iter - s.size_); +} + +string_view::size_type string_view::rfind(char c, size_type pos) const + noexcept { + return rfind(string_view(&c, 1), pos); +} + +string_view::size_type string_view::rfind(const char* s, + size_type pos, + size_type n) const { + return rfind(string_view(s, n), pos); +} + +string_view::size_type string_view::rfind(const char* s, size_type pos) const { + return rfind(string_view(s), pos); +} + +string_view::size_type string_view::find_first_of(string_view s, + size_type pos) const + noexcept { + pos = std::min(pos, size_); + const_iterator iter = + std::find_first_of(begin() + pos, end(), s.begin(), s.end()); + return iter == end() ? npos : iter - begin(); +} + +string_view::size_type string_view::find_first_of(char c, size_type pos) const + noexcept { + return find_first_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_first_of(const char* s, + size_type pos, + size_type n) const { + return find_first_of(string_view(s, n), pos); +} + +string_view::size_type string_view::find_first_of(const char* s, + size_type pos) const { + return find_first_of(string_view(s), pos); +} + +string_view::size_type string_view::find_last_of(string_view s, + size_type pos) const noexcept { + pos = std::min(pos, size_ - 1); + reverse_iterator iter = std::find_first_of( + reverse_iterator(begin() + pos + 1), rend(), s.begin(), s.end()); + return iter == rend() ? npos : (rend() - iter - 1); +} + +string_view::size_type string_view::find_last_of(char c, size_type pos) const + noexcept { + return find_last_of(string_view(&c, 1), pos); +} + +string_view::size_type string_view::find_last_of(const char* s, + size_type pos, + size_type n) const { + return find_last_of(string_view(s, n), pos); +} + +string_view::size_type string_view::find_last_of(const char* s, + size_type pos) const { + return find_last_of(string_view(s), pos); +} + +} // namespace wabt diff --git a/src/string-view.h b/src/string-view.h new file mode 100644 index 00000000..bc90130f --- /dev/null +++ b/src/string-view.h @@ -0,0 +1,288 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WABT_STRING_VIEW_H_ +#define WABT_STRING_VIEW_H_ + +#include <cassert> +#include <functional> +#include <iterator> +#include <string> + +#include "hash-util.h" + +namespace wabt { + +// This is a simplified implemention of C++17's basic_string_view template. +// +// Missing features: +// * Not a template +// * No allocator support +// * Some functions are not implemented +// * Asserts instead of exceptions +// * Some functions are not constexpr because we don't compile in C++17 mode + +class string_view { + public: + typedef std::char_traits<char> traits_type; + typedef char value_type; + typedef char* pointer; + typedef const char* const_pointer; + typedef char& reference; + typedef const char& const_reference; + typedef const char* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + static const size_type npos = size_type(-1); + + // construction and assignment + constexpr string_view() noexcept; + constexpr string_view(const string_view&) noexcept = default; + string_view& operator=(const string_view&) noexcept = default; + string_view(const std::string& str) noexcept; + /*constexpr*/ string_view(const char* str); + constexpr string_view(const char* str, size_type len); + + // iterator support + constexpr const_iterator begin() const noexcept; + constexpr const_iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + const_reverse_iterator rbegin() const noexcept; + const_reverse_iterator rend() const noexcept; + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + + // capacity + constexpr size_type size() const noexcept; + constexpr size_type length() const noexcept; + constexpr size_type max_size() const noexcept; + constexpr bool empty() const noexcept; + + // element access + constexpr const_reference operator[](size_type pos) const; + /*constexpr*/ const_reference at(size_type pos) const; + /*constexpr*/ const_reference front() const; + /*constexpr*/ const_reference back() const; + constexpr const_pointer data() const noexcept; + + // modifiers + /*constexpr*/ void remove_prefix(size_type n); + /*constexpr*/ void remove_suffix(size_type n); + /*constexpr*/ void swap(string_view& s) noexcept; + + // string operations + explicit operator std::string() const; + std::string to_string() const; + size_type copy(char* s, size_type n, size_type pos = 0) const; + /*constexpr*/ string_view substr(size_type pos = 0, size_type n = npos) const; + /*constexpr*/ int compare(string_view s) const noexcept; + /*constexpr*/ int compare(size_type pos1, size_type n1, string_view s) const; + /*constexpr*/ int compare(size_type pos1, + size_type n1, + string_view s, + size_type pos2, + size_type n2) const; + /*constexpr*/ int compare(const char* s) const; + /*constexpr*/ int compare(size_type pos1, size_type n1, const char* s) const; + /*constexpr*/ int compare(size_type pos1, + size_type n1, + const char* s, + size_type n2) const; + /*constexpr*/ size_type find(string_view s, size_type pos = 0) const noexcept; + /*constexpr*/ size_type find(char c, size_type pos = 0) const noexcept; + /*constexpr*/ size_type find(const char* s, size_type pos, size_type n) const; + /*constexpr*/ size_type find(const char* s, size_type pos = 0) const; + /*constexpr*/ size_type rfind(string_view s, size_type pos = npos) const + noexcept; + /*constexpr*/ size_type rfind(char c, size_type pos = npos) const noexcept; + /*constexpr*/ size_type rfind(const char* s, + size_type pos, + size_type n) const; + /*constexpr*/ size_type rfind(const char* s, size_type pos = npos) const; + /*constexpr*/ size_type find_first_of(string_view s, size_type pos = 0) const + noexcept; + /*constexpr*/ size_type find_first_of(char c, size_type pos = 0) const + noexcept; + /*constexpr*/ size_type find_first_of(const char* s, + size_type pos, + size_type n) const; + /*constexpr*/ size_type find_first_of(const char* s, size_type pos = 0) const; + /*constexpr*/ size_type find_last_of(string_view s, + size_type pos = npos) const noexcept; + /*constexpr*/ size_type find_last_of(char c, size_type pos = npos) const + noexcept; + /*constexpr*/ size_type find_last_of(const char* s, + size_type pos, + size_type n) const; + /*constexpr*/ size_type find_last_of(const char* s, + size_type pos = npos) const; + + // TODO(binji): These are defined by C++17 basic_string_view but not + // implemented here. +#if 0 + constexpr size_type find_first_not_of(string_view s, size_type pos = 0) const + noexcept; + constexpr size_type find_first_not_of(char c, size_type pos = 0) const + noexcept; + constexpr size_type find_first_not_of(const char* s, + size_type pos, + size_type n) const; + constexpr size_type find_first_not_of(const char* s, size_type pos = 0) const; + constexpr size_type find_last_not_of(string_view s, + size_type pos = npos) const noexcept; + constexpr size_type find_last_not_of(char c, size_type pos = npos) const + noexcept; + constexpr size_type find_last_not_of(const char* s, + size_type pos, + size_type n) const; + constexpr size_type find_last_not_of(const char* s, + size_type pos = npos) const; +#endif + + private: + const char* data_; + size_type size_; +}; + +// non-member comparison functions +inline bool operator==(string_view x, string_view y) noexcept { + return x.compare(y) == 0; +} + +inline bool operator!=(string_view x, string_view y) noexcept { + return x.compare(y) != 0; +} + +inline bool operator<(string_view x, string_view y) noexcept { + return x.compare(y) < 0; +} + +inline bool operator>(string_view x, string_view y) noexcept { + return x.compare(y) > 0; +} + +inline bool operator<=(string_view x, string_view y) noexcept { + return x.compare(y) <= 0; +} + +inline bool operator>=(string_view x, string_view y) noexcept { + return x.compare(y) >= 0; +} + +inline constexpr string_view::string_view() noexcept + : data_(nullptr), size_(0) {} + +inline string_view::string_view(const std::string& str) noexcept + : data_(str.data()), size_(str.size()) {} + +inline string_view::string_view(const char* str) + : data_(str), size_(traits_type::length(str)) {} + +inline constexpr string_view::string_view(const char* str, size_type len) + : data_(str), size_(len) {} + +inline constexpr string_view::const_iterator string_view::begin() const + noexcept { + return data_; +} + +inline constexpr string_view::const_iterator string_view::end() const noexcept { + return data_ + size_; +} + +inline constexpr string_view::const_iterator string_view::cbegin() const + noexcept { + return data_; +} + +inline constexpr string_view::const_iterator string_view::cend() const + noexcept { + return data_ + size_; +} + +inline string_view::const_reverse_iterator string_view::rbegin() const + noexcept { + return const_reverse_iterator(end()); +} + +inline string_view::const_reverse_iterator string_view::rend() const noexcept { + return const_reverse_iterator(begin()); +} + +inline string_view::const_reverse_iterator string_view::crbegin() const + noexcept { + return const_reverse_iterator(cend()); +} + +inline string_view::const_reverse_iterator string_view::crend() const noexcept { + return const_reverse_iterator(cbegin()); +} + +constexpr inline string_view::size_type string_view::size() const noexcept { + return size_; +} + +constexpr inline string_view::size_type string_view::length() const noexcept { + return size_; +} + +constexpr inline bool string_view::empty() const noexcept { + return size_ == 0; +} + +constexpr inline string_view::const_reference string_view::operator[]( + size_type pos) const { + return data_[pos]; +} + +inline string_view::const_reference string_view::at(size_type pos) const { + assert(pos < size_); + return data_[pos]; +} + +inline string_view::const_reference string_view::front() const { + assert(!empty()); + return *data_; +} + +inline string_view::const_reference string_view::back() const { + assert(!empty()); + return data_[size_ - 1]; +} + +constexpr inline string_view::const_pointer string_view::data() const noexcept { + return data_; +} + +} // namespace wabt + +namespace std { + +// hash support +template <> +struct hash<::wabt::string_view> { + ::wabt::hash_code operator()(const ::wabt::string_view& sv) { + return ::wabt::hash_range(sv.begin(), sv.end()); + } +}; + +} + +#endif // WABT_STRING_VIEW_H_ diff --git a/src/test-string-view.cc b/src/test-string-view.cc new file mode 100644 index 00000000..9a7636f7 --- /dev/null +++ b/src/test-string-view.cc @@ -0,0 +1,412 @@ +/* + * Copyright 2017 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" + +#include "string-view.h" + +#include <cstring> +#include <functional> + +using namespace wabt; + +namespace { + +void assert_string_view_eq(const char* s, const string_view& sv) { + size_t len = std::strlen(s); + ASSERT_EQ(len, sv.size()); + for (size_t i = 0; i < len; ++i) { + ASSERT_EQ(s[i], sv[i]); + } +} + +constexpr string_view::size_type npos = string_view::npos; + +} // namespace + +TEST(string_view, default_constructor) { + assert_string_view_eq("", string_view()); +} + +TEST(string_view, copy_constructor) { + string_view sv1("copy"); + assert_string_view_eq("copy", string_view(sv1)); + + string_view sv2; + assert_string_view_eq("", string_view(sv2)); +} + +TEST(string_view, assignment_operator) { + string_view sv1; + sv1 = string_view("assign"); + assert_string_view_eq("assign", sv1); + + string_view sv2; + sv2 = string_view(); + assert_string_view_eq("", sv2); +} + +TEST(string_view, string_constructor) { + assert_string_view_eq("", string_view(std::string())); + assert_string_view_eq("string", string_view(std::string("string"))); +} + +TEST(string_view, cstr_constructor) { + assert_string_view_eq("", string_view("")); + assert_string_view_eq("cstr", string_view("cstr")); +} + +TEST(string_view, cstr_len_constructor) { + assert_string_view_eq("", string_view("foo-bar-baz", 0)); + assert_string_view_eq("foo", string_view("foo-bar-baz", 3)); + assert_string_view_eq("foo-bar", string_view("foo-bar-baz", 7)); +} + +TEST(string_view, begin_end) { + string_view sv("012345"); + + char count = 0; + for (auto iter = sv.begin(), end = sv.end(); iter != end; ++iter) { + ASSERT_EQ('0' + count, *iter); + ++count; + } + ASSERT_EQ(6, count); +} + +TEST(string_view, cbegin_cend) { + const string_view sv("012345"); + + char count = 0; + for (auto iter = sv.cbegin(), end = sv.cend(); iter != end; ++iter) { + ASSERT_EQ('0' + count, *iter); + ++count; + } + ASSERT_EQ(6, count); +} + +TEST(string_view, rbegin_rend) { + string_view sv("012345"); + + char count = 0; + for (auto iter = sv.rbegin(), end = sv.rend(); iter != end; ++iter) { + ASSERT_EQ('5' - count, *iter); + ++count; + } + ASSERT_EQ(6, count); +} + +TEST(string_view, crbegin_crend) { + const string_view sv("012345"); + + char count = 0; + for (auto iter = sv.crbegin(), end = sv.crend(); iter != end; ++iter) { + ASSERT_EQ('5' - count, *iter); + ++count; + } + ASSERT_EQ(6, count); +} + +TEST(string_view, size) { + string_view sv1; + ASSERT_EQ(0U, sv1.size()); + + string_view sv2(""); + ASSERT_EQ(0U, sv2.size()); + + string_view sv3("hello"); + ASSERT_EQ(5U, sv3.size()); +} + +TEST(string_view, length) { + string_view sv1; + ASSERT_EQ(0U, sv1.length()); + + string_view sv2("hello"); + ASSERT_EQ(5U, sv2.length()); +} + +TEST(string_view, empty) { + string_view sv1; + ASSERT_TRUE(sv1.empty()); + + string_view sv2("bye"); + ASSERT_FALSE(sv2.empty()); +} + +TEST(string_view, operator_bracket) { + string_view sv("words"); + ASSERT_EQ('w', sv[0]); + ASSERT_EQ('o', sv[1]); + ASSERT_EQ('r', sv[2]); + ASSERT_EQ('d', sv[3]); + ASSERT_EQ('s', sv[4]); +} + +TEST(string_view, at) { + string_view sv("words"); + ASSERT_EQ('w', sv.at(0)); + ASSERT_EQ('o', sv.at(1)); + ASSERT_EQ('r', sv.at(2)); + ASSERT_EQ('d', sv.at(3)); + ASSERT_EQ('s', sv.at(4)); +} + +TEST(string_view, front) { + string_view sv("words"); + ASSERT_EQ('w', sv.front()); +} + +TEST(string_view, back) { + string_view sv("words"); + ASSERT_EQ('s', sv.back()); +} + +TEST(string_view, data) { + const char* cstr = "words"; + string_view sv(cstr); + ASSERT_EQ(cstr, sv.data()); +} + +TEST(string_view, remove_prefix) { + string_view sv("words"); + sv.remove_prefix(2); + assert_string_view_eq("rds", sv); +} + +TEST(string_view, remove_suffix) { + string_view sv("words"); + sv.remove_suffix(2); + assert_string_view_eq("wor", sv); +} + +TEST(string_view, swap) { + string_view sv1("hello"); + string_view sv2("bye"); + + sv1.swap(sv2); + + assert_string_view_eq("bye", sv1); + assert_string_view_eq("hello", sv2); +} + +TEST(string_view, operator_std_string) { + string_view sv1("hi"); + std::string s(sv1); + + ASSERT_EQ(2U, s.size()); + ASSERT_EQ('h', s[0]); + ASSERT_EQ('i', s[1]); +} + +TEST(string_view, copy) { + string_view sv("words"); + char buffer[10] = {0}; + + sv.copy(buffer, 10, 2); + ASSERT_EQ('r', buffer[0]); + ASSERT_EQ('d', buffer[1]); + ASSERT_EQ('s', buffer[2]); + for (int i = 3; i < 10; ++i) { + ASSERT_EQ(0, buffer[i]); + } +} + +TEST(string_view, substr) { + string_view sv1("abcdefghij"); + string_view sv2 = sv1.substr(2, 3); + assert_string_view_eq("cde", sv2); +} + +TEST(string_view, compare0) { + ASSERT_TRUE(string_view("meat").compare(string_view("meet")) < 0); + ASSERT_TRUE(string_view("rest").compare(string_view("rate")) > 0); + ASSERT_TRUE(string_view("equal").compare(string_view("equal")) == 0); + ASSERT_TRUE(string_view("star").compare(string_view("start")) < 0); + ASSERT_TRUE(string_view("finished").compare(string_view("fin")) > 0); +} + +TEST(string_view, compare1) { + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("ca")) > 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("cd")) == 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("cz")) < 0); +} + +TEST(string_view, compare2) { + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("_ca__"), 1, 2) > + 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("_cd__"), 1, 2) == + 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, string_view("_cz__"), 1, 2) < + 0); +} + +TEST(string_view, compare3) { + ASSERT_TRUE(string_view("abcdef").compare("aaaa") > 0); + ASSERT_TRUE(string_view("abcdef").compare("abcdef") == 0); + ASSERT_TRUE(string_view("abcdef").compare("zzzz") < 0); +} + +TEST(string_view, compare4) { + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "ca") > 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "cd") == 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "cz") < 0); +} + +TEST(string_view, compare5) { + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "ca____", 2) > 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "cd___", 2) == 0); + ASSERT_TRUE(string_view("abcdef").compare(2, 2, "cz__", 2) < 0); +} + +TEST(string_view, find0) { + ASSERT_EQ(0U, string_view("find fins").find(string_view("fin"))); + ASSERT_EQ(5U, string_view("find fins").find(string_view("fin"), 1)); + ASSERT_EQ(npos, string_view("find fins").find(string_view("fin"), 6)); +} + +TEST(string_view, find1) { + ASSERT_EQ(0U, string_view("012340123").find('0')); + ASSERT_EQ(5U, string_view("012340123").find('0', 2)); + ASSERT_EQ(npos, string_view("012340123").find('0', 6)); +} + +TEST(string_view, find2) { + ASSERT_EQ(1U, string_view("012340123").find("12345", 0, 2)); + ASSERT_EQ(6U, string_view("012340123").find("12345", 3, 2)); + ASSERT_EQ(npos, string_view("012340123").find("12345", 10, 2)); +} + +TEST(string_view, find3) { + ASSERT_EQ(1U, string_view("012340123").find("12")); + ASSERT_EQ(6U, string_view("012340123").find("12", 2)); + ASSERT_EQ(npos, string_view("012340123").find("12", 10)); +} + +TEST(string_view, rfind0) { + ASSERT_EQ(5U, string_view("find fins").rfind(string_view("fin"))); + ASSERT_EQ(0U, string_view("find fins").rfind(string_view("fin"), 4)); + ASSERT_EQ(npos, string_view("find fins").rfind(string_view("no"))); +} + +TEST(string_view, rfind1) { + ASSERT_EQ(5U, string_view("012340123").rfind('0')); + ASSERT_EQ(0U, string_view("012340123").rfind('0', 2)); + ASSERT_EQ(npos, string_view("012340123").rfind('9')); +} + +TEST(string_view, rfind2) { + ASSERT_EQ(6U, string_view("012340123").rfind("12345", npos, 2)); + ASSERT_EQ(1U, string_view("012340123").rfind("12345", 4, 2)); + ASSERT_EQ(npos, string_view("012340123").rfind("12345", npos, 5)); +} + +TEST(string_view, rfind3) { + ASSERT_EQ(6U, string_view("012340123").rfind("12")); + ASSERT_EQ(1U, string_view("012340123").rfind("12", 2)); + ASSERT_EQ(npos, string_view("012340123").rfind("12", 0)); +} + +TEST(string_view, find_first_of0) { + ASSERT_EQ(0U, string_view("0123abc").find_first_of(string_view("0a"))); + ASSERT_EQ(4U, string_view("0123abc").find_first_of(string_view("0a"), 1)); + ASSERT_EQ(npos, string_view("0123abc").find_first_of(string_view("xyz"))); +} + +TEST(string_view, find_first_of1) { + ASSERT_EQ(1U, string_view("ahellohi").find_first_of('h')); + ASSERT_EQ(6U, string_view("ahellohi").find_first_of('h', 2)); + ASSERT_EQ(npos, string_view("ahellohi").find_first_of('z', 2)); +} + +TEST(string_view, find_first_of2) { + ASSERT_EQ(0U, string_view("0123abc").find_first_of("0a1b", 0, 2)); + ASSERT_EQ(4U, string_view("0123abc").find_first_of("0a1b", 1, 2)); + ASSERT_EQ(npos, string_view("0123abc").find_first_of("0a1b", 5, 2)); +} + +TEST(string_view, find_first_of3) { + ASSERT_EQ(0U, string_view("0123abc").find_first_of("0a")); + ASSERT_EQ(0U, string_view("0123abc").find_first_of("0a", 0)); + ASSERT_EQ(4U, string_view("0123abc").find_first_of("0a", 1)); + ASSERT_EQ(npos, string_view("0123abc").find_first_of("0a", 5)); +} + +TEST(string_view, find_last_of0) { + ASSERT_EQ(4U, string_view("0123abc").find_last_of(string_view("0a"))); + ASSERT_EQ(0U, string_view("0123abc").find_last_of(string_view("0a"), 1)); + ASSERT_EQ(npos, string_view("0123abc").find_last_of(string_view("xyz"))); +} + +TEST(string_view, find_last_of1) { + ASSERT_EQ(6U, string_view("ahellohi").find_last_of('h')); + ASSERT_EQ(1U, string_view("ahellohi").find_last_of('h', 2)); + ASSERT_EQ(npos, string_view("ahellohi").find_last_of('z', 2)); +} + +TEST(string_view, find_last_of2) { + ASSERT_EQ(4U, string_view("0123abc").find_last_of("0a1b", npos, 2)); + ASSERT_EQ(0U, string_view("0123abc").find_last_of("0a1b", 1, 2)); + ASSERT_EQ(npos, string_view("0123abc").find_last_of("a1b", 0, 2)); + ASSERT_EQ(npos, string_view("0123abc").find_last_of("xyz", npos, 0)); +} + +TEST(string_view, find_last_of3) { + ASSERT_EQ(4U, string_view("0123abc").find_last_of("0a")); + ASSERT_EQ(4U, string_view("0123abc").find_last_of("0a", npos)); + ASSERT_EQ(0U, string_view("0123abc").find_last_of("0a", 1)); + ASSERT_EQ(npos, string_view("0123abc").find_last_of("a1", 0)); +} + +TEST(string_view, operator_equal) { + ASSERT_TRUE(string_view("this") == string_view("this")); + ASSERT_FALSE(string_view("this") == string_view("that")); +} + +TEST(string_view, operator_not_equal) { + ASSERT_FALSE(string_view("here") != string_view("here")); + ASSERT_TRUE(string_view("here") != string_view("there")); +} + +TEST(string_view, operator_less_than) { + ASSERT_TRUE(string_view("abc") < string_view("xyz")); + ASSERT_FALSE(string_view("later") < string_view("earlier")); + ASSERT_FALSE(string_view("one") < string_view("one")); +} + +TEST(string_view, operator_greater_than) { + ASSERT_TRUE(string_view("much") > string_view("little")); + ASSERT_FALSE(string_view("future") > string_view("past")); + ASSERT_FALSE(string_view("now") > string_view("now")); +} + +TEST(string_view, operator_less_than_or_equal) { + ASSERT_TRUE(string_view("abc") <= string_view("xyz")); + ASSERT_FALSE(string_view("later") <= string_view("earlier")); + ASSERT_TRUE(string_view("one") <= string_view("one")); +} + +TEST(string_view, operator_greater_than_or_equal) { + ASSERT_TRUE(string_view("much") >= string_view("little")); + ASSERT_FALSE(string_view("future") >= string_view("past")); + ASSERT_TRUE(string_view("now") >= string_view("now")); +} + +TEST(string_view, hash) { + std::hash<string_view> hasher; + + ASSERT_NE(hasher(string_view("hello")), hasher(string_view("goodbye"))); + ASSERT_EQ(hasher(string_view("same")), hasher(string_view("same"))); +} |