1 //===-- StringExtras.cpp - Implement the StringExtras header --------------===// 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 // This file implements the StringExtras.h header 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/StringExtras.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/Support/raw_ostream.h" 16 #include <cctype> 17 18 using namespace llvm; 19 20 /// StrInStrNoCase - Portable version of strcasestr. Locates the first 21 /// occurrence of string 's1' in string 's2', ignoring case. Returns 22 /// the offset of s2 in s1 or npos if s2 cannot be found. 23 StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) { 24 size_t N = s2.size(), M = s1.size(); 25 if (N > M) 26 return StringRef::npos; 27 for (size_t i = 0, e = M - N + 1; i != e; ++i) 28 if (s1.substr(i, N).equals_insensitive(s2)) 29 return i; 30 return StringRef::npos; 31 } 32 33 /// getToken - This function extracts one token from source, ignoring any 34 /// leading characters that appear in the Delimiters string, and ending the 35 /// token at any of the characters that appear in the Delimiters string. If 36 /// there are no tokens in the source string, an empty string is returned. 37 /// The function returns a pair containing the extracted token and the 38 /// remaining tail string. 39 std::pair<StringRef, StringRef> llvm::getToken(StringRef Source, 40 StringRef Delimiters) { 41 // Figure out where the token starts. 42 StringRef::size_type Start = Source.find_first_not_of(Delimiters); 43 44 // Find the next occurrence of the delimiter. 45 StringRef::size_type End = Source.find_first_of(Delimiters, Start); 46 47 return std::make_pair(Source.slice(Start, End), Source.substr(End)); 48 } 49 50 /// SplitString - Split up the specified string according to the specified 51 /// delimiters, appending the result fragments to the output list. 52 void llvm::SplitString(StringRef Source, 53 SmallVectorImpl<StringRef> &OutFragments, 54 StringRef Delimiters) { 55 std::pair<StringRef, StringRef> S = getToken(Source, Delimiters); 56 while (!S.first.empty()) { 57 OutFragments.push_back(S.first); 58 S = getToken(S.second, Delimiters); 59 } 60 } 61 62 void llvm::printEscapedString(StringRef Name, raw_ostream &Out) { 63 for (unsigned char C : Name) { 64 if (C == '\\') 65 Out << '\\' << C; 66 else if (isPrint(C) && C != '"') 67 Out << C; 68 else 69 Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); 70 } 71 } 72 73 void llvm::printHTMLEscaped(StringRef String, raw_ostream &Out) { 74 for (char C : String) { 75 if (C == '&') 76 Out << "&"; 77 else if (C == '<') 78 Out << "<"; 79 else if (C == '>') 80 Out << ">"; 81 else if (C == '\"') 82 Out << """; 83 else if (C == '\'') 84 Out << "'"; 85 else 86 Out << C; 87 } 88 } 89 90 void llvm::printLowerCase(StringRef String, raw_ostream &Out) { 91 for (const char C : String) 92 Out << toLower(C); 93 } 94 95 std::string llvm::convertToSnakeFromCamelCase(StringRef input) { 96 if (input.empty()) 97 return ""; 98 99 std::string snakeCase; 100 snakeCase.reserve(input.size()); 101 auto check = [&input](size_t j, function_ref<bool(int)> predicate) { 102 return j < input.size() && predicate(input[j]); 103 }; 104 for (size_t i = 0; i < input.size(); ++i) { 105 snakeCase.push_back(tolower(input[i])); 106 // Handles "runs" of capitals, such as in OPName -> op_name. 107 if (check(i, isupper) && check(i + 1, isupper) && check(i + 2, islower)) 108 snakeCase.push_back('_'); 109 if ((check(i, islower) || check(i, isdigit)) && check(i + 1, isupper)) 110 snakeCase.push_back('_'); 111 } 112 return snakeCase; 113 } 114 115 std::string llvm::convertToCamelFromSnakeCase(StringRef input, 116 bool capitalizeFirst) { 117 if (input.empty()) 118 return ""; 119 120 std::string output; 121 output.reserve(input.size()); 122 123 // Push the first character, capatilizing if necessary. 124 if (capitalizeFirst && std::islower(input.front())) 125 output.push_back(llvm::toUpper(input.front())); 126 else 127 output.push_back(input.front()); 128 129 // Walk the input converting any `*_[a-z]` snake case into `*[A-Z]` camelCase. 130 for (size_t pos = 1, e = input.size(); pos < e; ++pos) { 131 if (input[pos] == '_' && pos != (e - 1) && std::islower(input[pos + 1])) 132 output.push_back(llvm::toUpper(input[++pos])); 133 else 134 output.push_back(input[pos]); 135 } 136 return output; 137 } 138