blob: 534e675c73473b7bf477d057a0c899c15b726d99 [file] [log] [blame] [edit]
/*
* 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 <ostream>
#include <string>
#include "src/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;
}
// non-member append.
inline std::string& operator+=(std::string& x, string_view y) {
x.append(y.data(), y.size());
return x;
}
inline std::string operator+(string_view x, string_view y) {
std::string s;
s.reserve(x.size() + y.size());
s.append(x.data(), x.size());
s.append(y.data(), y.size());
return s;
}
inline std::string operator+(const std::string& x, string_view y) {
return string_view(x) + y;
}
inline std::string operator+(string_view x, const std::string& y) {
return x + string_view(y);
}
inline std::string operator+(const char* x, string_view y) {
return string_view(x) + y;
}
inline std::string operator+(string_view x, const char* y) {
return x + string_view(y);
}
inline void cat_concatenate(std::string&) {}
template<typename T, typename ...Ts>
void cat_concatenate(std::string& s, const T& t, const Ts&... args) {
s += t;
cat_concatenate(s, args...);
}
inline size_t cat_compute_size() { return 0; }
template<typename T, typename ...Ts>
size_t cat_compute_size(const T& t, const Ts&... args) {
return string_view(t).size() + cat_compute_size(args...);
}
// Is able to concatenate any combination of string/string_view/char*
template<typename ...Ts> std::string cat(const Ts&... args) {
std::string s;
s.reserve(cat_compute_size(args...));
cat_concatenate(s, args...);
return s;
}
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_;
}
inline std::ostream& operator<<(std::ostream& os, string_view sv) {
os.write(sv.data(), sv.size());
return os;
}
} // namespace wabt
namespace std {
// hash support
template <>
struct hash<::wabt::string_view> {
::wabt::hash_code operator()(const ::wabt::string_view& sv) {
return ::wabt::HashRange(sv.begin(), sv.end());
}
};
} // namespace std
#endif // WABT_STRING_VIEW_H_