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