179c2e3e6Spatrick //===--- StringView.h -------------------------------------------*- C++ -*-===// 279c2e3e6Spatrick // 379c2e3e6Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 479c2e3e6Spatrick // See https://llvm.org/LICENSE.txt for license information. 579c2e3e6Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 679c2e3e6Spatrick // 779c2e3e6Spatrick //===----------------------------------------------------------------------===// 879c2e3e6Spatrick // 979c2e3e6Spatrick // FIXME: Use std::string_view instead when we support C++17. 10*8f1d5724Srobert // There are two copies of this file in the source tree. The one under 11*8f1d5724Srobert // libcxxabi is the original and the one under llvm is the copy. Use 12*8f1d5724Srobert // cp-to-llvm.sh to update the copy. See README.txt for more details. 1379c2e3e6Spatrick // 1479c2e3e6Spatrick //===----------------------------------------------------------------------===// 1579c2e3e6Spatrick 1679c2e3e6Spatrick #ifndef DEMANGLE_STRINGVIEW_H 1779c2e3e6Spatrick #define DEMANGLE_STRINGVIEW_H 1879c2e3e6Spatrick 1979c2e3e6Spatrick #include "DemangleConfig.h" 2079c2e3e6Spatrick #include <cassert> 2179c2e3e6Spatrick #include <cstring> 2279c2e3e6Spatrick 2379c2e3e6Spatrick DEMANGLE_NAMESPACE_BEGIN 2479c2e3e6Spatrick 2579c2e3e6Spatrick class StringView { 2679c2e3e6Spatrick const char *First; 2779c2e3e6Spatrick const char *Last; 2879c2e3e6Spatrick 2979c2e3e6Spatrick public: 3079c2e3e6Spatrick static const size_t npos = ~size_t(0); 3179c2e3e6Spatrick 3279c2e3e6Spatrick template <size_t N> StringView(const char (& Str)[N])3379c2e3e6Spatrick StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} StringView(const char * First_,const char * Last_)3479c2e3e6Spatrick StringView(const char *First_, const char *Last_) 3579c2e3e6Spatrick : First(First_), Last(Last_) {} StringView(const char * First_,size_t Len)3679c2e3e6Spatrick StringView(const char *First_, size_t Len) 3779c2e3e6Spatrick : First(First_), Last(First_ + Len) {} StringView(const char * Str)3879c2e3e6Spatrick StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} StringView()3979c2e3e6Spatrick StringView() : First(nullptr), Last(nullptr) {} 4079c2e3e6Spatrick 414e0cc08cSpatrick StringView substr(size_t Pos, size_t Len = npos) const { 424e0cc08cSpatrick assert(Pos <= size()); 43*8f1d5724Srobert if (Len > size() - Pos) 44*8f1d5724Srobert Len = size() - Pos; 45*8f1d5724Srobert return StringView(begin() + Pos, Len); 4679c2e3e6Spatrick } 4779c2e3e6Spatrick 4879c2e3e6Spatrick size_t find(char C, size_t From = 0) const { 4979c2e3e6Spatrick // Avoid calling memchr with nullptr. 50*8f1d5724Srobert if (From < size()) { 5179c2e3e6Spatrick // Just forward to memchr, which is faster than a hand-rolled loop. 52*8f1d5724Srobert if (const void *P = ::memchr(First + From, C, size() - From)) 5379c2e3e6Spatrick return size_t(static_cast<const char *>(P) - First); 5479c2e3e6Spatrick } 5579c2e3e6Spatrick return npos; 5679c2e3e6Spatrick } 5779c2e3e6Spatrick 5879c2e3e6Spatrick StringView dropFront(size_t N = 1) const { 5979c2e3e6Spatrick if (N >= size()) 6079c2e3e6Spatrick N = size(); 6179c2e3e6Spatrick return StringView(First + N, Last); 6279c2e3e6Spatrick } 6379c2e3e6Spatrick 6479c2e3e6Spatrick StringView dropBack(size_t N = 1) const { 6579c2e3e6Spatrick if (N >= size()) 6679c2e3e6Spatrick N = size(); 6779c2e3e6Spatrick return StringView(First, Last - N); 6879c2e3e6Spatrick } 6979c2e3e6Spatrick front()7079c2e3e6Spatrick char front() const { 7179c2e3e6Spatrick assert(!empty()); 7279c2e3e6Spatrick return *begin(); 7379c2e3e6Spatrick } 7479c2e3e6Spatrick back()7579c2e3e6Spatrick char back() const { 7679c2e3e6Spatrick assert(!empty()); 7779c2e3e6Spatrick return *(end() - 1); 7879c2e3e6Spatrick } 7979c2e3e6Spatrick popFront()8079c2e3e6Spatrick char popFront() { 8179c2e3e6Spatrick assert(!empty()); 8279c2e3e6Spatrick return *First++; 8379c2e3e6Spatrick } 8479c2e3e6Spatrick consumeFront(char C)8579c2e3e6Spatrick bool consumeFront(char C) { 8679c2e3e6Spatrick if (!startsWith(C)) 8779c2e3e6Spatrick return false; 8879c2e3e6Spatrick *this = dropFront(1); 8979c2e3e6Spatrick return true; 9079c2e3e6Spatrick } 9179c2e3e6Spatrick consumeFront(StringView S)9279c2e3e6Spatrick bool consumeFront(StringView S) { 9379c2e3e6Spatrick if (!startsWith(S)) 9479c2e3e6Spatrick return false; 9579c2e3e6Spatrick *this = dropFront(S.size()); 9679c2e3e6Spatrick return true; 9779c2e3e6Spatrick } 9879c2e3e6Spatrick startsWith(char C)9979c2e3e6Spatrick bool startsWith(char C) const { return !empty() && *begin() == C; } 10079c2e3e6Spatrick startsWith(StringView Str)10179c2e3e6Spatrick bool startsWith(StringView Str) const { 10279c2e3e6Spatrick if (Str.size() > size()) 10379c2e3e6Spatrick return false; 104*8f1d5724Srobert return std::strncmp(Str.begin(), begin(), Str.size()) == 0; 10579c2e3e6Spatrick } 10679c2e3e6Spatrick 10779c2e3e6Spatrick const char &operator[](size_t Idx) const { return *(begin() + Idx); } 10879c2e3e6Spatrick begin()10979c2e3e6Spatrick const char *begin() const { return First; } end()11079c2e3e6Spatrick const char *end() const { return Last; } size()11179c2e3e6Spatrick size_t size() const { return static_cast<size_t>(Last - First); } empty()11279c2e3e6Spatrick bool empty() const { return First == Last; } 11379c2e3e6Spatrick }; 11479c2e3e6Spatrick 11579c2e3e6Spatrick inline bool operator==(const StringView &LHS, const StringView &RHS) { 11679c2e3e6Spatrick return LHS.size() == RHS.size() && 117*8f1d5724Srobert std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0; 11879c2e3e6Spatrick } 11979c2e3e6Spatrick 12079c2e3e6Spatrick DEMANGLE_NAMESPACE_END 12179c2e3e6Spatrick 12279c2e3e6Spatrick #endif 123