#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include <stddef.h>
namespace LIBC_NAMESPACE_DECL {
namespace cpp {
class string_view {
private:
const char *Data;
size_t Len;
LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; }
LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,
size_t Length) {
for (size_t I = 0; I < Length; ++I)
if (int Diff = (int)Lhs[I] - (int)Rhs[I])
return Diff;
return 0;
}
LIBC_INLINE static constexpr size_t length(const char *Str) {
for (const char *End = Str;; ++End)
if (*End == '\0')
return End - Str;
}
LIBC_INLINE bool equals(string_view Other) const {
return (Len == Other.Len &&
compareMemory(Data, Other.Data, Other.Len) == 0);
}
public:
using value_type = char;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = char *;
using const_pointer = const char *;
using reference = char &;
using const_reference = const char &;
using const_iterator = char *;
using iterator = const_iterator;
LIBC_INLINE_VAR static constexpr size_t npos = -1;
LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
LIBC_INLINE constexpr string_view(const char *Str)
: Data(Str), Len(length(Str)) {}
LIBC_INLINE constexpr string_view(const char *Str, size_t N)
: Data(Str), Len(N) {}
LIBC_INLINE constexpr const char *data() const { return Data; }
LIBC_INLINE constexpr size_t size() const { return Len; }
LIBC_INLINE constexpr bool empty() const { return Len == 0; }
LIBC_INLINE const char *begin() const { return Data; }
LIBC_INLINE const char *end() const { return Data + Len; }
LIBC_INLINE constexpr const char &operator[](size_t Index) const {
return Data[Index];
}
LIBC_INLINE int compare(string_view Other) const {
if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len)))
return Res < 0 ? -1 : 1;
if (Len == Other.Len)
return 0;
return Len < Other.Len ? -1 : 1;
}
LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); }
LIBC_INLINE bool operator!=(string_view Other) const {
return !(*this == Other);
}
LIBC_INLINE bool operator<(string_view Other) const {
return compare(Other) == -1;
}
LIBC_INLINE bool operator<=(string_view Other) const {
return compare(Other) != 1;
}
LIBC_INLINE bool operator>(string_view Other) const {
return compare(Other) == 1;
}
LIBC_INLINE bool operator>=(string_view Other) const {
return compare(Other) != -1;
}
LIBC_INLINE void remove_prefix(size_t N) {
Len -= N;
Data += N;
}
LIBC_INLINE void remove_suffix(size_t N) { Len -= N; }
LIBC_INLINE bool starts_with(string_view Prefix) const {
return Len >= Prefix.Len &&
compareMemory(Data, Prefix.Data, Prefix.Len) == 0;
}
LIBC_INLINE bool starts_with(const char Prefix) const {
return !empty() && front() == Prefix;
}
LIBC_INLINE bool ends_with(const char Suffix) const {
return !empty() && back() == Suffix;
}
LIBC_INLINE bool ends_with(string_view Suffix) const {
return Len >= Suffix.Len &&
compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;
}
LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const {
Start = min(Start, Len);
return string_view(Data + Start, min(N, Len - Start));
}
LIBC_INLINE char front() const { return Data[0]; }
LIBC_INLINE char back() const { return Data[Len - 1]; }
LIBC_INLINE constexpr size_t find_first_of(const char c,
size_t From = 0) const {
for (size_t Pos = From; Pos < size(); ++Pos)
if ((*this)[Pos] == c)
return Pos;
return npos;
}
LIBC_INLINE constexpr size_t find_last_of(const char c,
size_t End = npos) const {
End = End >= size() ? size() : End + 1;
for (; End > 0; --End)
if ((*this)[End - 1] == c)
return End - 1;
return npos;
}
LIBC_INLINE constexpr size_t find_first_not_of(const char c,
size_t From = 0) const {
for (size_t Pos = From; Pos < size(); ++Pos)
if ((*this)[Pos] != c)
return Pos;
return npos;
}
LIBC_INLINE constexpr bool contains(char c) const {
return find_first_of(c) != npos;
}
};
}
}
#endif