| //===-- StringExtras.cpp - Implement the StringExtras header --------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the StringExtras.h header |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <cctype> |
| |
| using namespace llvm; |
| |
| /// StrInStrNoCase - Portable version of strcasestr. Locates the first |
| /// occurrence of string 's1' in string 's2', ignoring case. Returns |
| /// the offset of s2 in s1 or npos if s2 cannot be found. |
| StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) { |
| size_t N = s2.size(), M = s1.size(); |
| if (N > M) |
| return StringRef::npos; |
| for (size_t i = 0, e = M - N + 1; i != e; ++i) |
| if (s1.substr(i, N).equals_insensitive(s2)) |
| return i; |
| return StringRef::npos; |
| } |
| |
| /// getToken - This function extracts one token from source, ignoring any |
| /// leading characters that appear in the Delimiters string, and ending the |
| /// token at any of the characters that appear in the Delimiters string. If |
| /// there are no tokens in the source string, an empty string is returned. |
| /// The function returns a pair containing the extracted token and the |
| /// remaining tail string. |
| std::pair<StringRef, StringRef> llvm::getToken(StringRef Source, |
| StringRef Delimiters) { |
| // Figure out where the token starts. |
| StringRef::size_type Start = Source.find_first_not_of(Delimiters); |
| |
| // Find the next occurrence of the delimiter. |
| StringRef::size_type End = Source.find_first_of(Delimiters, Start); |
| |
| return std::make_pair(Source.slice(Start, End), Source.substr(End)); |
| } |
| |
| /// SplitString - Split up the specified string according to the specified |
| /// delimiters, appending the result fragments to the output list. |
| void llvm::SplitString(StringRef Source, |
| SmallVectorImpl<StringRef> &OutFragments, |
| StringRef Delimiters) { |
| std::pair<StringRef, StringRef> S = getToken(Source, Delimiters); |
| while (!S.first.empty()) { |
| OutFragments.push_back(S.first); |
| S = getToken(S.second, Delimiters); |
| } |
| } |
| |
| void llvm::printEscapedString(StringRef Name, raw_ostream &Out) { |
| for (unsigned char C : Name) { |
| if (C == '\\') |
| Out << '\\' << C; |
| else if (isPrint(C) && C != '"') |
| Out << C; |
| else |
| Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); |
| } |
| } |
| |
| void llvm::printHTMLEscaped(StringRef String, raw_ostream &Out) { |
| for (char C : String) { |
| if (C == '&') |
| Out << "&"; |
| else if (C == '<') |
| Out << "<"; |
| else if (C == '>') |
| Out << ">"; |
| else if (C == '\"') |
| Out << """; |
| else if (C == '\'') |
| Out << "'"; |
| else |
| Out << C; |
| } |
| } |
| |
| void llvm::printLowerCase(StringRef String, raw_ostream &Out) { |
| for (const char C : String) |
| Out << toLower(C); |
| } |
| |
| std::string llvm::convertToSnakeFromCamelCase(StringRef input) { |
| if (input.empty()) |
| return ""; |
| |
| std::string snakeCase; |
| snakeCase.reserve(input.size()); |
| for (char c : input) { |
| if (!std::isupper(c)) { |
| snakeCase.push_back(c); |
| continue; |
| } |
| |
| if (!snakeCase.empty() && snakeCase.back() != '_') |
| snakeCase.push_back('_'); |
| snakeCase.push_back(llvm::toLower(c)); |
| } |
| return snakeCase; |
| } |
| |
| std::string llvm::convertToCamelFromSnakeCase(StringRef input, |
| bool capitalizeFirst) { |
| if (input.empty()) |
| return ""; |
| |
| std::string output; |
| output.reserve(input.size()); |
| |
| // Push the first character, capatilizing if necessary. |
| if (capitalizeFirst && std::islower(input.front())) |
| output.push_back(llvm::toUpper(input.front())); |
| else |
| output.push_back(input.front()); |
| |
| // Walk the input converting any `*_[a-z]` snake case into `*[A-Z]` camelCase. |
| for (size_t pos = 1, e = input.size(); pos < e; ++pos) { |
| if (input[pos] == '_' && pos != (e - 1) && std::islower(input[pos + 1])) |
| output.push_back(llvm::toUpper(input[++pos])); |
| else |
| output.push_back(input[pos]); |
| } |
| return output; |
| } |