diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:17:04 +0000 | 
| commit | b915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch) | |
| tree | 98b8f811c7aff2547cab8642daf372d6c59502fb /lib/Support/StringRef.cpp | |
| parent | 6421cca32f69ac849537a3cff78c352195e99f1b (diff) | |
Notes
Diffstat (limited to 'lib/Support/StringRef.cpp')
| -rw-r--r-- | lib/Support/StringRef.cpp | 140 | 
1 files changed, 109 insertions, 31 deletions
| diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index 8a9da5edca84..d81250e48dde 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -69,6 +69,11 @@ bool StringRef::endswith_lower(StringRef Suffix) const {        ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;  } +size_t StringRef::find_lower(char C, size_t From) const { +  char L = ascii_tolower(C); +  return find_if([L](char D) { return ascii_tolower(D) == L; }, From); +} +  /// compare_numeric - Compare strings, handle embedded numbers.  int StringRef::compare_numeric(StringRef RHS) const {    for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { @@ -143,16 +148,20 @@ size_t StringRef::find(StringRef Str, size_t From) const {    if (From > Length)      return npos; +  const char *Start = Data + From; +  size_t Size = Length - From; +    const char *Needle = Str.data();    size_t N = Str.size();    if (N == 0)      return From; - -  size_t Size = Length - From;    if (Size < N)      return npos; +  if (N == 1) { +    const char *Ptr = (const char *)::memchr(Start, Needle[0], Size); +    return Ptr == nullptr ? npos : Ptr - Data; +  } -  const char *Start = Data + From;    const char *Stop = Start + (Size - N + 1);    // For short haystacks or unsupported needles fall back to the naive algorithm @@ -172,16 +181,40 @@ size_t StringRef::find(StringRef Str, size_t From) const {      BadCharSkip[(uint8_t)Str[i]] = N-1-i;    do { -    if (std::memcmp(Start, Needle, N) == 0) -      return Start - Data; +    uint8_t Last = Start[N - 1]; +    if (LLVM_UNLIKELY(Last == (uint8_t)Needle[N - 1])) +      if (std::memcmp(Start, Needle, N - 1) == 0) +        return Start - Data;      // Otherwise skip the appropriate number of bytes. -    Start += BadCharSkip[(uint8_t)Start[N-1]]; +    Start += BadCharSkip[Last];    } while (Start < Stop);    return npos;  } +size_t StringRef::find_lower(StringRef Str, size_t From) const { +  StringRef This = substr(From); +  while (This.size() >= Str.size()) { +    if (This.startswith_lower(Str)) +      return From; +    This = This.drop_front(); +    ++From; +  } +  return npos; +} + +size_t StringRef::rfind_lower(char C, size_t From) const { +  From = std::min(From, Length); +  size_t i = From; +  while (i != 0) { +    --i; +    if (ascii_tolower(Data[i]) == ascii_tolower(C)) +      return i; +  } +  return npos; +} +  /// rfind - Search for the last string \arg Str in the string.  ///  /// \return - The index of the last occurrence of \arg Str, or npos if not @@ -198,6 +231,18 @@ size_t StringRef::rfind(StringRef Str) const {    return npos;  } +size_t StringRef::rfind_lower(StringRef Str) const { +  size_t N = Str.size(); +  if (N > Length) +    return npos; +  for (size_t i = Length - N + 1, e = 0; i != e;) { +    --i; +    if (substr(i, N).equals_lower(Str)) +      return i; +  } +  return npos; +} +  /// find_first_of - Find the first character in the string that is in \arg  /// Chars, or npos if not found.  /// @@ -351,6 +396,9 @@ size_t StringRef::count(StringRef Str) const {  }  static unsigned GetAutoSenseRadix(StringRef &Str) { +  if (Str.empty()) +    return 10; +    if (Str.startswith("0x") || Str.startswith("0X")) {      Str = Str.substr(2);      return 16; @@ -366,17 +414,16 @@ static unsigned GetAutoSenseRadix(StringRef &Str) {      return 8;    } -  if (Str.startswith("0")) +  if (Str[0] == '0' && Str.size() > 1 && ascii_isdigit(Str[1])) { +    Str = Str.substr(1);      return 8; -   +  } +    return 10;  } - -/// GetAsUnsignedInteger - Workhorse method that converts a integer character -/// sequence of radix up to 36 to an unsigned long long value. -bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, -                                unsigned long long &Result) { +bool llvm::consumeUnsignedInteger(StringRef &Str, unsigned Radix, +                                  unsigned long long &Result) {    // Autosense radix if not specified.    if (Radix == 0)      Radix = GetAutoSenseRadix(Str); @@ -385,44 +432,51 @@ bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix,    if (Str.empty()) return true;    // Parse all the bytes of the string given this radix.  Watch for overflow. +  StringRef Str2 = Str;    Result = 0; -  while (!Str.empty()) { +  while (!Str2.empty()) {      unsigned CharVal; -    if (Str[0] >= '0' && Str[0] <= '9') -      CharVal = Str[0]-'0'; -    else if (Str[0] >= 'a' && Str[0] <= 'z') -      CharVal = Str[0]-'a'+10; -    else if (Str[0] >= 'A' && Str[0] <= 'Z') -      CharVal = Str[0]-'A'+10; +    if (Str2[0] >= '0' && Str2[0] <= '9') +      CharVal = Str2[0] - '0'; +    else if (Str2[0] >= 'a' && Str2[0] <= 'z') +      CharVal = Str2[0] - 'a' + 10; +    else if (Str2[0] >= 'A' && Str2[0] <= 'Z') +      CharVal = Str2[0] - 'A' + 10;      else -      return true; +      break; -    // If the parsed value is larger than the integer radix, the string is -    // invalid. +    // If the parsed value is larger than the integer radix, we cannot +    // consume any more characters.      if (CharVal >= Radix) -      return true; +      break;      // Add in this character.      unsigned long long PrevResult = Result; -    Result = Result*Radix+CharVal; +    Result = Result * Radix + CharVal;      // Check for overflow by shifting back and seeing if bits were lost. -    if (Result/Radix < PrevResult) +    if (Result / Radix < PrevResult)        return true; -    Str = Str.substr(1); +    Str2 = Str2.substr(1);    } +  // We consider the operation a failure if no characters were consumed +  // successfully. +  if (Str.size() == Str2.size()) +    return true; + +  Str = Str2;    return false;  } -bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, -                              long long &Result) { +bool llvm::consumeSignedInteger(StringRef &Str, unsigned Radix, +                                long long &Result) {    unsigned long long ULLVal;    // Handle positive strings first.    if (Str.empty() || Str.front() != '-') { -    if (getAsUnsignedInteger(Str, Radix, ULLVal) || +    if (consumeUnsignedInteger(Str, Radix, ULLVal) ||          // Check for value so large it overflows a signed value.          (long long)ULLVal < 0)        return true; @@ -431,17 +485,41 @@ bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix,    }    // Get the positive part of the value. -  if (getAsUnsignedInteger(Str.substr(1), Radix, ULLVal) || +  StringRef Str2 = Str.drop_front(1); +  if (consumeUnsignedInteger(Str2, Radix, ULLVal) ||        // Reject values so large they'd overflow as negative signed, but allow        // "-0".  This negates the unsigned so that the negative isn't undefined        // on signed overflow.        (long long)-ULLVal > 0)      return true; +  Str = Str2;    Result = -ULLVal;    return false;  } +/// GetAsUnsignedInteger - Workhorse method that converts a integer character +/// sequence of radix up to 36 to an unsigned long long value. +bool llvm::getAsUnsignedInteger(StringRef Str, unsigned Radix, +                                unsigned long long &Result) { +  if (consumeUnsignedInteger(Str, Radix, Result)) +    return true; + +  // For getAsUnsignedInteger, we require the whole string to be consumed or +  // else we consider it a failure. +  return !Str.empty(); +} + +bool llvm::getAsSignedInteger(StringRef Str, unsigned Radix, +                              long long &Result) { +  if (consumeSignedInteger(Str, Radix, Result)) +    return true; + +  // For getAsSignedInteger, we require the whole string to be consumed or else +  // we consider it a failure. +  return !Str.empty(); +} +  bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const {    StringRef Str = *this; | 
