Home | History | Annotate | Line # | Download | only in Demangle
      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 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_DEMANGLE_STRINGVIEW_H
     14 #define LLVM_DEMANGLE_STRINGVIEW_H
     15 
     16 #include "DemangleConfig.h"
     17 #include <algorithm>
     18 #include <cassert>
     19 #include <cstring>
     20 
     21 DEMANGLE_NAMESPACE_BEGIN
     22 
     23 class StringView {
     24   const char *First;
     25   const char *Last;
     26 
     27 public:
     28   static const size_t npos = ~size_t(0);
     29 
     30   template <size_t N>
     31   StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
     32   StringView(const char *First_, const char *Last_)
     33       : First(First_), Last(Last_) {}
     34   StringView(const char *First_, size_t Len)
     35       : First(First_), Last(First_ + Len) {}
     36   StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
     37   StringView() : First(nullptr), Last(nullptr) {}
     38 
     39   StringView substr(size_t Pos, size_t Len = npos) const {
     40     assert(Pos <= size());
     41     return StringView(begin() + Pos, std::min(Len, size() - Pos));
     42   }
     43 
     44   size_t find(char C, size_t From = 0) const {
     45     size_t FindBegin = std::min(From, size());
     46     // Avoid calling memchr with nullptr.
     47     if (FindBegin < size()) {
     48       // Just forward to memchr, which is faster than a hand-rolled loop.
     49       if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
     50         return size_t(static_cast<const char *>(P) - First);
     51     }
     52     return npos;
     53   }
     54 
     55   StringView dropFront(size_t N = 1) const {
     56     if (N >= size())
     57       N = size();
     58     return StringView(First + N, Last);
     59   }
     60 
     61   StringView dropBack(size_t N = 1) const {
     62     if (N >= size())
     63       N = size();
     64     return StringView(First, Last - N);
     65   }
     66 
     67   char front() const {
     68     assert(!empty());
     69     return *begin();
     70   }
     71 
     72   char back() const {
     73     assert(!empty());
     74     return *(end() - 1);
     75   }
     76 
     77   char popFront() {
     78     assert(!empty());
     79     return *First++;
     80   }
     81 
     82   bool consumeFront(char C) {
     83     if (!startsWith(C))
     84       return false;
     85     *this = dropFront(1);
     86     return true;
     87   }
     88 
     89   bool consumeFront(StringView S) {
     90     if (!startsWith(S))
     91       return false;
     92     *this = dropFront(S.size());
     93     return true;
     94   }
     95 
     96   bool startsWith(char C) const { return !empty() && *begin() == C; }
     97 
     98   bool startsWith(StringView Str) const {
     99     if (Str.size() > size())
    100       return false;
    101     return std::equal(Str.begin(), Str.end(), begin());
    102   }
    103 
    104   const char &operator[](size_t Idx) const { return *(begin() + Idx); }
    105 
    106   const char *begin() const { return First; }
    107   const char *end() const { return Last; }
    108   size_t size() const { return static_cast<size_t>(Last - First); }
    109   bool empty() const { return First == Last; }
    110 };
    111 
    112 inline bool operator==(const StringView &LHS, const StringView &RHS) {
    113   return LHS.size() == RHS.size() &&
    114          std::equal(LHS.begin(), LHS.end(), RHS.begin());
    115 }
    116 
    117 DEMANGLE_NAMESPACE_END
    118 
    119 #endif
    120