brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · aa15814 Raw
223 lines · c
1//===-- Standalone implementation std::string_view --------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H10#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H11 12#include "limits.h"13#include "src/__support/common.h"14#include "src/__support/macros/config.h"15 16#include <stddef.h>17 18namespace LIBC_NAMESPACE_DECL {19namespace cpp {20 21// This is very simple alternate of the std::string_view class. There is no22// bounds check performed in any of the methods. The callers are expected to23// do the checks before invoking the methods.24//25// This class will be extended as needed in future.26class string_view {27private:28  const char *Data;29  size_t Len;30 31  LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; }32 33  LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,34                                       size_t Length) {35    for (size_t i = 0; i < Length; ++i)36      if (int Diff = (int)Lhs[i] - (int)Rhs[i])37        return Diff;38    return 0;39  }40 41  LIBC_INLINE static constexpr size_t length(const char *Str) {42    for (const char *End = Str;; ++End)43      if (*End == '\0')44        return static_cast<size_t>(End - Str);45  }46 47  LIBC_INLINE bool equals(string_view Other) const {48    return (Len == Other.Len &&49            compareMemory(Data, Other.Data, Other.Len) == 0);50  }51 52public:53  using value_type = char;54  using size_type = size_t;55  using difference_type = ptrdiff_t;56  using pointer = char *;57  using const_pointer = const char *;58  using reference = char &;59  using const_reference = const char &;60  using const_iterator = char *;61  using iterator = const_iterator;62 63  // special value equal to the maximum value representable by the type64  // size_type.65  LIBC_INLINE_VAR static constexpr size_t npos =66      cpp::numeric_limits<size_t>::max();67 68  LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}69 70  // Assumes Str is a null-terminated string. The length of the string does71  // not include the terminating null character.72  // Preconditions: [Str, Str + ​length(Str)) is a valid range.73  LIBC_INLINE constexpr string_view(const char *Str)74      : Data(Str), Len(length(Str)) {}75 76  // Preconditions: [Str, Str + N) is a valid range.77  LIBC_INLINE constexpr string_view(const char *Str, size_t N)78      : Data(Str), Len(N) {}79 80  LIBC_INLINE constexpr const char *data() const { return Data; }81 82  // Returns the size of the string_view.83  LIBC_INLINE constexpr size_t size() const { return Len; }84 85  // Returns whether the string_view is empty.86  LIBC_INLINE constexpr bool empty() const { return Len == 0; }87 88  // Returns an iterator to the first character of the view.89  LIBC_INLINE const char *begin() const { return Data; }90 91  // Returns an iterator to the character following the last character of the92  // view.93  LIBC_INLINE const char *end() const { return Data + Len; }94 95  // Returns a const reference to the character at specified location pos.96  // No bounds checking is performed: the behavior is undefined if pos >=97  // size().98  LIBC_INLINE constexpr const char &operator[](size_t Index) const {99    return Data[Index];100  }101 102  /// compare - Compare two strings; the result is -1, 0, or 1 if this string103  /// is lexicographically less than, equal to, or greater than the \p Other.104  LIBC_INLINE int compare(string_view Other) const {105    // Check the prefix for a mismatch.106    if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len)))107      return Res < 0 ? -1 : 1;108    // Otherwise the prefixes match, so we only need to check the lengths.109    if (Len == Other.Len)110      return 0;111    return Len < Other.Len ? -1 : 1;112  }113 114  LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); }115  LIBC_INLINE bool operator!=(string_view Other) const {116    return !(*this == Other);117  }118  LIBC_INLINE bool operator<(string_view Other) const {119    return compare(Other) == -1;120  }121  LIBC_INLINE bool operator<=(string_view Other) const {122    return compare(Other) != 1;123  }124  LIBC_INLINE bool operator>(string_view Other) const {125    return compare(Other) == 1;126  }127  LIBC_INLINE bool operator>=(string_view Other) const {128    return compare(Other) != -1;129  }130 131  // Moves the start of the view forward by n characters.132  // The behavior is undefined if n > size().133  LIBC_INLINE void remove_prefix(size_t N) {134    Len -= N;135    Data += N;136  }137 138  // Moves the end of the view back by n characters.139  // The behavior is undefined if n > size().140  LIBC_INLINE void remove_suffix(size_t N) { Len -= N; }141 142  // Check if this string starts with the given Prefix.143  LIBC_INLINE bool starts_with(string_view Prefix) const {144    return Len >= Prefix.Len &&145           compareMemory(Data, Prefix.Data, Prefix.Len) == 0;146  }147 148  // Check if this string starts with the given Prefix.149  LIBC_INLINE bool starts_with(const char Prefix) const {150    return !empty() && front() == Prefix;151  }152 153  // Check if this string ends with the given Prefix.154  LIBC_INLINE bool ends_with(const char Suffix) const {155    return !empty() && back() == Suffix;156  }157 158  // Check if this string ends with the given Suffix.159  LIBC_INLINE bool ends_with(string_view Suffix) const {160    return Len >= Suffix.Len &&161           compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;162  }163 164  // Return a reference to the substring from [Start, Start + N).165  //166  // Start The index of the starting character in the substring; if the index is167  // npos or greater than the length of the string then the empty substring will168  // be returned.169  //170  // N The number of characters to included in the substring. If N exceeds the171  // number of characters remaining in the string, the string suffix (starting172  // with Start) will be returned.173  LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const {174    Start = min(Start, Len);175    return string_view(Data + Start, min(N, Len - Start));176  }177 178  // front - Get the first character in the string.179  LIBC_INLINE char front() const { return Data[0]; }180 181  // back - Get the last character in the string.182  LIBC_INLINE char back() const { return Data[Len - 1]; }183 184  // Finds the first occurence of c in this view, starting at position From.185  LIBC_INLINE constexpr size_t find_first_of(const char c,186                                             size_t From = 0) const {187    for (size_t Pos = From; Pos < size(); ++Pos)188      if ((*this)[Pos] == c)189        return Pos;190    return npos;191  }192 193  // Finds the last occurence of c in this view, ending at position End.194  LIBC_INLINE constexpr size_t find_last_of(const char c,195                                            size_t End = npos) const {196    End = End >= size() ? size() : End + 1;197    for (; End > 0; --End)198      if ((*this)[End - 1] == c)199        return End - 1;200    return npos;201  }202 203  // Finds the first character not equal to c in this view, starting at position204  // From.205  LIBC_INLINE constexpr size_t find_first_not_of(const char c,206                                                 size_t From = 0) const {207    for (size_t Pos = From; Pos < size(); ++Pos)208      if ((*this)[Pos] != c)209        return Pos;210    return npos;211  }212 213  // Check if this view contains the given character.214  LIBC_INLINE constexpr bool contains(char c) const {215    return find_first_of(c) != npos;216  }217};218 219} // namespace cpp220} // namespace LIBC_NAMESPACE_DECL221 222#endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H223