1 //===--- StringView.h -------------------------------------------*- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // FIXME: Use std::string_view instead when we support C++17. 10 // There are two copies of this file in the source tree. The one under 11 // libcxxabi is the original and the one under llvm is the copy. Use 12 // cp-to-llvm.sh to update the copy. See README.txt for more details. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef DEMANGLE_STRINGVIEW_H 17 #define DEMANGLE_STRINGVIEW_H 18 19 #include "DemangleConfig.h" 20 #include <cassert> 21 #include <cstring> 22 23 DEMANGLE_NAMESPACE_BEGIN 24 25 class StringView { 26 const char *First; 27 const char *Last; 28 29 public: 30 static const size_t npos = ~size_t(0); 31 32 template <size_t N> 33 StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} 34 StringView(const char *First_, const char *Last_) 35 : First(First_), Last(Last_) {} 36 StringView(const char *First_, size_t Len) 37 : First(First_), Last(First_ + Len) {} 38 StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} 39 StringView() : First(nullptr), Last(nullptr) {} 40 41 StringView substr(size_t Pos, size_t Len = npos) const { 42 assert(Pos <= size()); 43 if (Len > size() - Pos) 44 Len = size() - Pos; 45 return StringView(begin() + Pos, Len); 46 } 47 48 size_t find(char C, size_t From = 0) const { 49 // Avoid calling memchr with nullptr. 50 if (From < size()) { 51 // Just forward to memchr, which is faster than a hand-rolled loop. 52 if (const void *P = ::memchr(First + From, C, size() - From)) 53 return size_t(static_cast<const char *>(P) - First); 54 } 55 return npos; 56 } 57 58 StringView dropFront(size_t N = 1) const { 59 if (N >= size()) 60 N = size(); 61 return StringView(First + N, Last); 62 } 63 64 StringView dropBack(size_t N = 1) const { 65 if (N >= size()) 66 N = size(); 67 return StringView(First, Last - N); 68 } 69 70 char front() const { 71 assert(!empty()); 72 return *begin(); 73 } 74 75 char back() const { 76 assert(!empty()); 77 return *(end() - 1); 78 } 79 80 char popFront() { 81 assert(!empty()); 82 return *First++; 83 } 84 85 bool consumeFront(char C) { 86 if (!startsWith(C)) 87 return false; 88 *this = dropFront(1); 89 return true; 90 } 91 92 bool consumeFront(StringView S) { 93 if (!startsWith(S)) 94 return false; 95 *this = dropFront(S.size()); 96 return true; 97 } 98 99 bool startsWith(char C) const { return !empty() && *begin() == C; } 100 101 bool startsWith(StringView Str) const { 102 if (Str.size() > size()) 103 return false; 104 return std::strncmp(Str.begin(), begin(), Str.size()) == 0; 105 } 106 107 const char &operator[](size_t Idx) const { return *(begin() + Idx); } 108 109 const char *begin() const { return First; } 110 const char *end() const { return Last; } 111 size_t size() const { return static_cast<size_t>(Last - First); } 112 bool empty() const { return First == Last; } 113 }; 114 115 inline bool operator==(const StringView &LHS, const StringView &RHS) { 116 return LHS.size() == RHS.size() && 117 std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0; 118 } 119 120 DEMANGLE_NAMESPACE_END 121 122 #endif 123