xref: /src/contrib/llvm-project/llvm/lib/Support/StringExtras.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1009b1c42SEd Schouten //===-- StringExtras.cpp - Implement the StringExtras header --------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This file implements the StringExtras.h header
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten 
13829000e0SRoman Divacky #include "llvm/ADT/StringExtras.h"
147ab83427SDimitry Andric #include "llvm/ADT/SmallVector.h"
15044eb2f6SDimitry Andric #include "llvm/Support/raw_ostream.h"
16cfca06d7SDimitry Andric #include <cctype>
17cfca06d7SDimitry Andric 
18009b1c42SEd Schouten using namespace llvm;
19009b1c42SEd Schouten 
20829000e0SRoman Divacky /// StrInStrNoCase - Portable version of strcasestr.  Locates the first
21829000e0SRoman Divacky /// occurrence of string 's1' in string 's2', ignoring case.  Returns
22829000e0SRoman Divacky /// the offset of s2 in s1 or npos if s2 cannot be found.
StrInStrNoCase(StringRef s1,StringRef s2)23829000e0SRoman Divacky StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) {
24829000e0SRoman Divacky   size_t N = s2.size(), M = s1.size();
25829000e0SRoman Divacky   if (N > M)
26829000e0SRoman Divacky     return StringRef::npos;
27829000e0SRoman Divacky   for (size_t i = 0, e = M - N + 1; i != e; ++i)
28344a3780SDimitry Andric     if (s1.substr(i, N).equals_insensitive(s2))
29829000e0SRoman Divacky       return i;
30829000e0SRoman Divacky   return StringRef::npos;
31829000e0SRoman Divacky }
32829000e0SRoman Divacky 
33009b1c42SEd Schouten /// getToken - This function extracts one token from source, ignoring any
34009b1c42SEd Schouten /// leading characters that appear in the Delimiters string, and ending the
35009b1c42SEd Schouten /// token at any of the characters that appear in the Delimiters string.  If
36009b1c42SEd Schouten /// there are no tokens in the source string, an empty string is returned.
37829000e0SRoman Divacky /// The function returns a pair containing the extracted token and the
38829000e0SRoman Divacky /// remaining tail string.
getToken(StringRef Source,StringRef Delimiters)39829000e0SRoman Divacky std::pair<StringRef, StringRef> llvm::getToken(StringRef Source,
40829000e0SRoman Divacky                                                StringRef Delimiters) {
41009b1c42SEd Schouten   // Figure out where the token starts.
42829000e0SRoman Divacky   StringRef::size_type Start = Source.find_first_not_of(Delimiters);
43009b1c42SEd Schouten 
44829000e0SRoman Divacky   // Find the next occurrence of the delimiter.
45829000e0SRoman Divacky   StringRef::size_type End = Source.find_first_of(Delimiters, Start);
46009b1c42SEd Schouten 
47989df958SRoman Divacky   return std::make_pair(Source.slice(Start, End), Source.substr(End));
48009b1c42SEd Schouten }
49009b1c42SEd Schouten 
50009b1c42SEd Schouten /// SplitString - Split up the specified string according to the specified
51009b1c42SEd Schouten /// delimiters, appending the result fragments to the output list.
SplitString(StringRef Source,SmallVectorImpl<StringRef> & OutFragments,StringRef Delimiters)52829000e0SRoman Divacky void llvm::SplitString(StringRef Source,
53829000e0SRoman Divacky                        SmallVectorImpl<StringRef> &OutFragments,
54829000e0SRoman Divacky                        StringRef Delimiters) {
5530815c53SDimitry Andric   std::pair<StringRef, StringRef> S = getToken(Source, Delimiters);
5630815c53SDimitry Andric   while (!S.first.empty()) {
5730815c53SDimitry Andric     OutFragments.push_back(S.first);
5830815c53SDimitry Andric     S = getToken(S.second, Delimiters);
59009b1c42SEd Schouten   }
60009b1c42SEd Schouten }
61044eb2f6SDimitry Andric 
printEscapedString(StringRef Name,raw_ostream & Out)62eb11fae6SDimitry Andric void llvm::printEscapedString(StringRef Name, raw_ostream &Out) {
63f65dcba8SDimitry Andric   for (unsigned char C : Name) {
641d5ae102SDimitry Andric     if (C == '\\')
651d5ae102SDimitry Andric       Out << '\\' << C;
661d5ae102SDimitry Andric     else if (isPrint(C) && C != '"')
67eb11fae6SDimitry Andric       Out << C;
68eb11fae6SDimitry Andric     else
69eb11fae6SDimitry Andric       Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
70eb11fae6SDimitry Andric   }
71eb11fae6SDimitry Andric }
72eb11fae6SDimitry Andric 
printHTMLEscaped(StringRef String,raw_ostream & Out)73eb11fae6SDimitry Andric void llvm::printHTMLEscaped(StringRef String, raw_ostream &Out) {
74eb11fae6SDimitry Andric   for (char C : String) {
75eb11fae6SDimitry Andric     if (C == '&')
76eb11fae6SDimitry Andric       Out << "&amp;";
77eb11fae6SDimitry Andric     else if (C == '<')
78eb11fae6SDimitry Andric       Out << "&lt;";
79eb11fae6SDimitry Andric     else if (C == '>')
80eb11fae6SDimitry Andric       Out << "&gt;";
81eb11fae6SDimitry Andric     else if (C == '\"')
82eb11fae6SDimitry Andric       Out << "&quot;";
83eb11fae6SDimitry Andric     else if (C == '\'')
84eb11fae6SDimitry Andric       Out << "&apos;";
85eb11fae6SDimitry Andric     else
86eb11fae6SDimitry Andric       Out << C;
87eb11fae6SDimitry Andric   }
88eb11fae6SDimitry Andric }
89eb11fae6SDimitry Andric 
printLowerCase(StringRef String,raw_ostream & Out)90044eb2f6SDimitry Andric void llvm::printLowerCase(StringRef String, raw_ostream &Out) {
91044eb2f6SDimitry Andric   for (const char C : String)
92044eb2f6SDimitry Andric     Out << toLower(C);
93044eb2f6SDimitry Andric }
94cfca06d7SDimitry Andric 
convertToSnakeFromCamelCase(StringRef input)95cfca06d7SDimitry Andric std::string llvm::convertToSnakeFromCamelCase(StringRef input) {
96cfca06d7SDimitry Andric   if (input.empty())
97cfca06d7SDimitry Andric     return "";
98cfca06d7SDimitry Andric 
99cfca06d7SDimitry Andric   std::string snakeCase;
100cfca06d7SDimitry Andric   snakeCase.reserve(input.size());
101b1c73532SDimitry Andric   auto check = [&input](size_t j, function_ref<bool(int)> predicate) {
102b1c73532SDimitry Andric     return j < input.size() && predicate(input[j]);
103b1c73532SDimitry Andric   };
104b1c73532SDimitry Andric   for (size_t i = 0; i < input.size(); ++i) {
105b1c73532SDimitry Andric     snakeCase.push_back(tolower(input[i]));
106b1c73532SDimitry Andric     // Handles "runs" of capitals, such as in OPName -> op_name.
107b1c73532SDimitry Andric     if (check(i, isupper) && check(i + 1, isupper) && check(i + 2, islower))
108cfca06d7SDimitry Andric       snakeCase.push_back('_');
109b1c73532SDimitry Andric     if ((check(i, islower) || check(i, isdigit)) && check(i + 1, isupper))
110b1c73532SDimitry Andric       snakeCase.push_back('_');
111cfca06d7SDimitry Andric   }
112cfca06d7SDimitry Andric   return snakeCase;
113cfca06d7SDimitry Andric }
114cfca06d7SDimitry Andric 
convertToCamelFromSnakeCase(StringRef input,bool capitalizeFirst)115cfca06d7SDimitry Andric std::string llvm::convertToCamelFromSnakeCase(StringRef input,
116cfca06d7SDimitry Andric                                               bool capitalizeFirst) {
117cfca06d7SDimitry Andric   if (input.empty())
118cfca06d7SDimitry Andric     return "";
119cfca06d7SDimitry Andric 
120cfca06d7SDimitry Andric   std::string output;
121cfca06d7SDimitry Andric   output.reserve(input.size());
122cfca06d7SDimitry Andric 
123cfca06d7SDimitry Andric   // Push the first character, capatilizing if necessary.
124cfca06d7SDimitry Andric   if (capitalizeFirst && std::islower(input.front()))
125cfca06d7SDimitry Andric     output.push_back(llvm::toUpper(input.front()));
126cfca06d7SDimitry Andric   else
127cfca06d7SDimitry Andric     output.push_back(input.front());
128cfca06d7SDimitry Andric 
129cfca06d7SDimitry Andric   // Walk the input converting any `*_[a-z]` snake case into `*[A-Z]` camelCase.
130cfca06d7SDimitry Andric   for (size_t pos = 1, e = input.size(); pos < e; ++pos) {
131cfca06d7SDimitry Andric     if (input[pos] == '_' && pos != (e - 1) && std::islower(input[pos + 1]))
132cfca06d7SDimitry Andric       output.push_back(llvm::toUpper(input[++pos]));
133cfca06d7SDimitry Andric     else
134cfca06d7SDimitry Andric       output.push_back(input[pos]);
135cfca06d7SDimitry Andric   }
136cfca06d7SDimitry Andric   return output;
137cfca06d7SDimitry Andric }
138