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 for (char c : input) { 102 if (!std::isupper(c)) { 103 snakeCase.push_back(c); 104 continue; 105 } 106 107 if (!snakeCase.empty() && snakeCase.back() != '_') 108 snakeCase.push_back('_'); 109 snakeCase.push_back(llvm::toLower(c)); 110 } 111 return snakeCase; 112 } 113 114 std::string llvm::convertToCamelFromSnakeCase(StringRef input, 115 bool capitalizeFirst) { 116 if (input.empty()) 117 return ""; 118 119 std::string output; 120 output.reserve(input.size()); 121 122 // Push the first character, capatilizing if necessary. 123 if (capitalizeFirst && std::islower(input.front())) 124 output.push_back(llvm::toUpper(input.front())); 125 else 126 output.push_back(input.front()); 127 128 // Walk the input converting any `*_[a-z]` snake case into `*[A-Z]` camelCase. 129 for (size_t pos = 1, e = input.size(); pos < e; ++pos) { 130 if (input[pos] == '_' && pos != (e - 1) && std::islower(input[pos + 1])) 131 output.push_back(llvm::toUpper(input[++pos])); 132 else 133 output.push_back(input[pos]); 134 } 135 return output; 136 } 137