blob: 8cdde3973ae9161b3ef1ac696fc25ce75a6307dd [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_FXL_STRINGS_STRING_VIEW_H_
#define SRC_LIB_FXL_STRINGS_STRING_VIEW_H_
#include <iosfwd>
#include <string>
#include <type_traits>
#include "src/lib/fxl/fxl_export.h"
#include "src/lib/fxl/logging.h"
// MSVC 2015 doesn't support "extended constexpr" from C++14.
#if __cplusplus >= 201402L
// C++14 relaxed the limitation of the content of a constexpr function.
#define CONSTEXPR_IN_CPP14 constexpr
#else
#define CONSTEXPR_IN_CPP14
#endif
namespace fxl {
// A string-like object that points to a sized piece of memory.
class StringView {
public:
// Types.
using const_iterator = const char*;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
constexpr static size_t npos = static_cast<size_t>(-1);
// Constructors.
constexpr StringView() : data_(""), size_(0u) {}
constexpr StringView(const char* str, size_t len) : data_(str), size_(len) {}
explicit constexpr StringView(const char* str) : data_(str), size_(constexpr_strlen(str)) {}
// Implicit constructor for constant C strings.
template <size_t N>
constexpr StringView(const char (&str)[N]) : data_(str), size_(constexpr_strlen(str)) {}
// Implicit constructor.
StringView(const std::string& str) : data_(str.data()), size_(str.size()) {}
// The class is (trivially) copyable.
constexpr StringView(const StringView& string_view) = default;
StringView& operator=(const StringView& other) = default;
// Capacity methods.
constexpr size_t size() const { return size_; }
constexpr size_t length() const { return size(); }
constexpr bool empty() const { return size_ == 0u; }
// Element access methods.
constexpr char operator[](size_t pos) const { return data_[pos]; }
constexpr char at(size_t pos) const { return data_[pos]; }
constexpr char front() const { return data_[0]; }
constexpr char back() const { return data_[size_ - 1]; }
constexpr const char* data() const { return data_; }
// Iterators.
constexpr const_iterator begin() const { return cbegin(); }
constexpr const_iterator end() const { return cend(); }
constexpr const_iterator cbegin() const { return data_; }
constexpr const_iterator cend() const { return data_ + size_; }
const_reverse_iterator rbegin() const { return const_reverse_iterator(cend()); }
const_reverse_iterator rend() const { return const_reverse_iterator(cbegin()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
// Modifier methods.
CONSTEXPR_IN_CPP14 void clear() {
data_ = "";
size_ = 0;
}
CONSTEXPR_IN_CPP14 void remove_prefix(size_t n) {
FX_DCHECK(n <= size_);
data_ += n;
size_ -= n;
}
CONSTEXPR_IN_CPP14 void remove_suffix(size_t n) {
FX_DCHECK(n <= size_);
size_ -= n;
}
CONSTEXPR_IN_CPP14 void swap(StringView& other) {
const char* data = data_;
data_ = other.data_;
other.data_ = data;
size_t size = size_;
size_ = other.size_;
other.size_ = size;
}
// String conversion.
std::string ToString() const { return std::string(data_, size_); }
// String operations.
constexpr StringView substr(size_t pos = 0, size_t n = npos) const {
return StringView(data_ + pos, min(n, size_ - pos));
}
// Returns negative, 0, or positive when |this| is lexigraphically
// less than, equal to, or greater than |other|, a la
// std::basic_string_view::compare.
int compare(StringView other);
size_t find(StringView s, size_t pos = 0) const;
size_t find(char c, size_t pos = 0) const;
size_t rfind(StringView s, size_t pos = npos) const;
size_t rfind(char c, size_t pos = npos) const;
size_t find_first_of(StringView s, size_t pos = 0) const;
size_t find_last_of(StringView s, size_t pos = npos) const;
size_t find_first_not_of(StringView s, size_t pos = 0) const;
size_t find_last_not_of(StringView s, size_t pos = npos) const;
private:
constexpr static size_t min(size_t v1, size_t v2) { return v1 < v2 ? v1 : v2; }
constexpr static size_t constexpr_strlen(const char* str) {
#if defined(_MSC_VER)
return *str ? 1 + constexpr_strlen(str + 1) : 0;
#else
return __builtin_strlen(str);
#endif
}
const char* data_;
size_t size_;
};
// Comparison.
bool operator==(StringView lhs, StringView rhs);
bool operator!=(StringView lhs, StringView rhs);
bool operator<(StringView lhs, StringView rhs);
bool operator>(StringView lhs, StringView rhs);
bool operator<=(StringView lhs, StringView rhs);
bool operator>=(StringView lhs, StringView rhs);
// IO.
std::ostream& operator<<(std::ostream& o, StringView string_view);
} // namespace fxl
#endif // SRC_LIB_FXL_STRINGS_STRING_VIEW_H_