14 #ifndef LLVM_ADT_STRINGEXTRAS_H
15 #define LLVM_ADT_STRINGEXTRAS_H
37 inline char hexdigit(
unsigned X,
bool LowerCase =
false) {
39 static const char LUT[] =
"0123456789ABCDEF";
40 const uint8_t
Offset = LowerCase ? 32 : 0;
47 inline std::vector<StringRef> toStringRefArray(
const char *
const *Strings) {
48 std::vector<StringRef>
Result;
50 Result.push_back(*Strings++);
55 inline StringRef
toStringRef(
bool B) {
return StringRef(
B ?
"true" :
"false"); }
58 inline StringRef
toStringRef(ArrayRef<uint8_t> Input) {
59 return StringRef(
reinterpret_cast<const char *
>(Input.begin()), Input.size());
63 inline ArrayRef<uint8_t> arrayRefFromStringRef(StringRef Input) {
64 return {Input.bytes_begin(), Input.bytes_end()};
71 inline unsigned hexDigitValue(
char C) {
73 static const int16_t LUT[256] = {
74 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
77 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
78 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
79 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
80 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
81 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
82 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
83 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
84 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
85 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
86 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
87 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
88 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
89 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
92 return LUT[
static_cast<unsigned char>(
C)];
96 inline bool isDigit(
char C) {
return C >=
'0' &&
C <=
'9'; }
99 inline bool isHexDigit(
char C) {
return hexDigitValue(
C) != ~0U; }
102 inline bool isAlpha(
char C) {
103 return (
'a' <=
C &&
C <=
'z') || (
'A' <=
C &&
C <=
'Z');
108 inline bool isAlnum(
char C) {
return isAlpha(
C) ||
isDigit(
C); }
111 inline bool isASCII(
char C) {
return static_cast<unsigned char>(
C) <= 127; }
126 unsigned char UC =
static_cast<unsigned char>(
C);
127 return (0x20 <= UC) && (UC <= 0x7E);
133 inline bool isSpace(
char C) {
134 return C ==
' ' ||
C ==
'\f' ||
C ==
'\n' ||
C ==
'\r' ||
C ==
'\t' ||
139 inline char toLower(
char x) {
140 if (
x >=
'A' &&
x <=
'Z')
141 return x -
'A' +
'a';
146 inline char toUpper(
char x) {
147 if (
x >=
'a' &&
x <=
'z')
148 return x -
'a' +
'A';
152 inline std::string utohexstr(
uint64_t X,
bool LowerCase =
false,
153 unsigned Width = 0) {
157 if (
X == 0) *--BufPtr =
'0';
160 unsigned char Mod =
static_cast<unsigned char>(
X) & 15;
161 *--BufPtr = hexdigit(
Mod, LowerCase);
165 return std::string(BufPtr,
std::end(Buffer));
170 inline void toHex(ArrayRef<uint8_t> Input,
bool LowerCase,
171 SmallVectorImpl<char> &Output) {
172 const size_t Length = Input.size();
173 Output.resize_for_overwrite(
Length * 2);
176 const uint8_t
c = Input[
i];
177 Output[
i * 2 ] = hexdigit(
c >> 4, LowerCase);
178 Output[
i * 2 + 1] = hexdigit(
c & 15, LowerCase);
182 inline std::string
toHex(ArrayRef<uint8_t> Input,
bool LowerCase =
false) {
183 SmallString<16> Output;
184 toHex(Input, LowerCase, Output);
185 return std::string(Output);
188 inline std::string
toHex(StringRef Input,
bool LowerCase =
false) {
189 return toHex(arrayRefFromStringRef(Input), LowerCase);
196 inline bool tryGetHexFromNibbles(
char MSB,
char LSB, uint8_t &Hex) {
197 unsigned U1 = hexDigitValue(MSB);
198 unsigned U2 = hexDigitValue(LSB);
199 if (U1 == ~0U || U2 == ~0U)
202 Hex =
static_cast<uint8_t
>((U1 << 4) | U2);
208 inline uint8_t hexFromNibbles(
char MSB,
char LSB) {
210 bool GotHex = tryGetHexFromNibbles(MSB, LSB, Hex);
212 assert(GotHex &&
"MSB and/or LSB do not correspond to hex digits");
220 inline bool tryGetFromHex(StringRef Input, std::string &Output) {
226 Output.resize((Input.size() + 1) / 2);
227 char *OutputPtr =
const_cast<char *
>(Output.data());
228 if (Input.size() % 2 == 1) {
230 if (!tryGetHexFromNibbles(
'0', Input.front(), Hex))
233 Input = Input.drop_front();
239 size_t InputSize = Input.size();
240 assert(InputSize % 2 == 0);
241 const char *InputPtr = Input.data();
242 for (
size_t OutputIndex = 0; OutputIndex < InputSize / 2; ++OutputIndex) {
244 if (!tryGetHexFromNibbles(InputPtr[OutputIndex * 2 + 0],
245 InputPtr[OutputIndex * 2 + 1],
248 OutputPtr[OutputIndex] = Hex;
255 inline std::string fromHex(StringRef Input) {
257 bool GotHex = tryGetFromHex(Input, Hex);
259 assert(GotHex &&
"Input contains non hex digits");
266 template <
typename N>
bool to_integer(StringRef
S,
N &Num,
unsigned Base = 0) {
267 return !
S.getAsInteger(
Base, Num);
271 template <
typename N>
272 inline bool to_float(
const Twine &T,
N &Num,
N (*StrTo)(
const char *,
char **)) {
273 SmallString<32> Storage;
274 StringRef
S =
T.toNullTerminatedStringRef(Storage);
276 N Temp = StrTo(
S.data(), &End);
284 inline bool to_float(
const Twine &T,
float &Num) {
285 return detail::to_float(T, Num, strtof);
288 inline bool to_float(
const Twine &T,
double &Num) {
289 return detail::to_float(T, Num, strtod);
292 inline bool to_float(
const Twine &T,
long double &Num) {
293 return detail::to_float(T, Num, strtold);
296 inline std::string utostr(
uint64_t X,
bool isNeg =
false) {
300 if (
X == 0) *--BufPtr =
'0';
303 *--BufPtr =
'0' + char(
X % 10);
307 if (isNeg) *--BufPtr =
'-';
308 return std::string(BufPtr,
std::end(Buffer));
311 inline std::string itostr(int64_t
X) {
318 inline std::string
toString(
const APInt &
I,
unsigned Radix,
bool Signed,
319 bool formatAsCLiteral =
false) {
321 I.toString(
S, Radix,
Signed, formatAsCLiteral);
322 return std::string(
S.str());
340 std::pair<StringRef, StringRef> getToken(StringRef
Source,
341 StringRef Delimiters =
" \t\n\v\f\r");
345 void SplitString(StringRef
Source,
346 SmallVectorImpl<StringRef> &OutFragments,
347 StringRef Delimiters =
" \t\n\v\f\r");
350 inline StringRef getOrdinalSuffix(
unsigned Val) {
363 default:
return "th";
370 void printEscapedString(StringRef Name, raw_ostream &Out);
374 void printHTMLEscaped(StringRef String, raw_ostream &Out);
377 void printLowerCase(StringRef String, raw_ostream &Out);
382 std::string convertToSnakeFromCamelCase(StringRef
input);
388 std::string convertToCamelFromSnakeCase(StringRef
input,
389 bool capitalizeFirst =
false);
393 template <
typename IteratorT>
394 inline std::string join_impl(IteratorT Begin, IteratorT End,
395 StringRef Separator, std::input_iterator_tag) {
401 while (++Begin != End) {
408 template <
typename IteratorT>
409 inline std::string join_impl(IteratorT Begin, IteratorT End,
410 StringRef Separator, std::forward_iterator_tag) {
415 size_t Len = (std::distance(Begin, End) - 1) * Separator.size();
416 for (IteratorT
I = Begin;
I != End; ++
I)
419 size_t PrevCapacity =
S.capacity();
422 while (++Begin != End) {
426 assert(PrevCapacity ==
S.capacity() &&
"String grew during building");
430 template <
typename Sep>
431 inline void join_items_impl(std::string &Result, Sep Separator) {}
433 template <
typename Sep,
typename Arg>
434 inline void join_items_impl(std::string &Result, Sep Separator,
439 template <
typename Sep,
typename Arg1,
typename...
Args>
440 inline void join_items_impl(std::string &Result, Sep Separator,
const Arg1 &A1,
444 join_items_impl(Result, Separator, std::forward<Args>(Items)...);
447 inline size_t join_one_item_size(
char) {
return 1; }
448 inline size_t join_one_item_size(
const char *
S) {
return S ? ::strlen(
S) : 0; }
450 template <
typename T>
inline size_t join_one_item_size(
const T &Str) {
454 template <
typename...
Args>
inline size_t join_items_size(
Args &&...Items) {
455 return (0 + ... + join_one_item_size(std::forward<Args>(Items)));
462 template <
typename IteratorT>
463 inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
464 using tag =
typename std::iterator_traits<IteratorT>::iterator_category;
465 return detail::join_impl(Begin, End, Separator, tag());
470 template <
typename Range>
471 inline std::string join(Range &&R, StringRef Separator) {
472 return join(
R.begin(),
R.end(), Separator);
479 template <
typename Sep,
typename...
Args>
480 inline std::string join_items(Sep Separator,
Args &&... Items) {
482 if (
sizeof...(Items) == 0)
485 size_t NS = detail::join_one_item_size(Separator);
486 size_t NI = detail::join_items_size(std::forward<Args>(Items)...);
487 Result.reserve(NI + (
sizeof...(Items) - 1) * NS + 1);
488 detail::join_items_impl(Result, Separator, std::forward<Args>(Items)...);
501 class ListSeparator {
506 ListSeparator(StringRef Separator =
", ") : Separator(Separator) {}
507 operator StringRef() {
517 class SplittingIterator
518 :
public iterator_facade_base<SplittingIterator, std::forward_iterator_tag,
520 char SeparatorStorage;
526 SplittingIterator(StringRef Str, StringRef Separator)
527 : Next(Str), Separator(Separator) {
531 SplittingIterator(StringRef Str,
char Separator)
532 : SeparatorStorage(Separator), Next(Str),
533 Separator(&SeparatorStorage, 1) {
537 SplittingIterator(
const SplittingIterator &R)
538 : SeparatorStorage(
R.SeparatorStorage), Current(
R.Current), Next(
R.Next),
539 Separator(
R.Separator) {
540 if (
R.Separator.data() == &
R.SeparatorStorage)
541 Separator = StringRef(&SeparatorStorage, 1);
544 SplittingIterator &operator=(
const SplittingIterator &R) {
548 SeparatorStorage =
R.SeparatorStorage;
551 Separator =
R.Separator;
552 if (
R.Separator.data() == &
R.SeparatorStorage)
553 Separator = StringRef(&SeparatorStorage, 1);
557 bool operator==(
const SplittingIterator &R)
const {
558 assert(Separator ==
R.Separator);
559 return Current.data() ==
R.Current.data();
562 const StringRef &
operator*()
const {
return Current; }
564 StringRef &
operator*() {
return Current; }
566 SplittingIterator &operator++() {
567 std::tie(Current, Next) = Next.split(Separator);
583 inline iterator_range<SplittingIterator>
split(StringRef Str, StringRef Separator) {
584 return {SplittingIterator(Str, Separator),
585 SplittingIterator(StringRef(), Separator)};
588 inline iterator_range<SplittingIterator>
split(StringRef Str,
char Separator) {
589 return {SplittingIterator(Str, Separator),
590 SplittingIterator(StringRef(), Separator)};
595 #endif // LLVM_ADT_STRINGEXTRAS_H