//===-- 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 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 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 &OutFragments, StringRef Delimiters) { std::pair 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 i = 0, e = Name.size(); i != e; ++i) { unsigned char C = Name[i]; 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; }