FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
DirectXShaderCompiler/lib/Support/StringRef.cpp at main · microsoft/DirectXShaderCompiler · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
microsoft
/
DirectXShaderCompiler
Public
Notifications
You must be signed in to change notification settings
Fork
897
Star
3.6k
Code
Issues
654
Pull requests
140
Discussions
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Discussions
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
DirectXShaderCompiler
/
lib
/
Support
/
StringRef.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
489 lines (415 loc) · 14.4 KB
Breadcrumbs
DirectXShaderCompiler
/
lib
/
Support
/
StringRef.cpp
Copy path
File metadata and controls
489 lines (415 loc) · 14.4 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
//
===-- StringRef.cpp - Lightweight String References ---------------------===//
//
//
The LLVM Compiler Infrastructure
//
//
This file is distributed under the University of Illinois Open Source
//
License. See LICENSE.TXT for details.
//
//
===----------------------------------------------------------------------===//
#
include
"
llvm/ADT/StringRef.h
"
#
include
"
llvm/ADT/APInt.h
"
#
include
"
llvm/ADT/Hashing.h
"
#
include
"
llvm/ADT/edit_distance.h
"
#
include
<
bitset
>
#
include
<
limits
>
using
namespace
llvm
;
//
MSVC emits references to this into the translation units which reference it.
#
ifndef
_MSC_VER
const
size_t
StringRef::npos;
#
endif
static
char
ascii_tolower
(
char
x) {
if
(x >=
'
A
'
&& x <=
'
Z
'
)
return
x -
'
A
'
+
'
a
'
;
return
x;
}
static
char
ascii_toupper
(
char
x) {
if
(x >=
'
a
'
&& x <=
'
z
'
)
return
x -
'
a
'
+
'
A
'
;
return
x;
}
static
bool
ascii_isdigit
(
char
x) {
return
x >=
'
0
'
&& x <=
'
9
'
;
}
//
strncasecmp() is not available on non-POSIX systems, so define an
//
alternative function here.
static
int
ascii_strncasecmp
(
const
char
*
LHS
,
const
char
*
RHS
,
size_t
Length) {
for
(
size_t
I =
0
; I < Length; ++I) {
unsigned
char
LHC
=
ascii_tolower
(
LHS
[I]);
unsigned
char
RHC
=
ascii_tolower
(
RHS
[I]);
if
(
LHC
!=
RHC
)
return
LHC
<
RHC
? -
1
:
1
;
}
return
0
;
}
//
/ compare_lower - Compare strings, ignoring case.
int
StringRef::compare_lower
(StringRef
RHS
)
const
{
if
(
int
Res =
ascii_strncasecmp
(Data,
RHS
.
Data
,
std::min
(Length,
RHS
.
Length
)))
return
Res;
if
(Length ==
RHS
.
Length
)
return
0
;
return
Length <
RHS
.
Length
? -
1
:
1
;
}
//
/ Check if this string starts with the given \p Prefix, ignoring case.
bool
StringRef::startswith_lower
(StringRef Prefix)
const
{
return
Length >= Prefix.
Length
&&
ascii_strncasecmp
(Data, Prefix.
Data
, Prefix.
Length
) ==
0
;
}
//
/ Check if this string ends with the given \p Suffix, ignoring case.
bool
StringRef::endswith_lower
(StringRef Suffix)
const
{
return
Length >= Suffix.
Length
&&
ascii_strncasecmp
(
end
() - Suffix.
Length
, Suffix.
Data
, Suffix.
Length
) ==
0
;
}
//
/ compare_numeric - Compare strings, handle embedded numbers.
int
StringRef::compare_numeric
(StringRef
RHS
)
const
{
for
(
size_t
I =
0
, E =
std::min
(Length,
RHS
.
Length
); I != E; ++I) {
//
Check for sequences of digits.
if
(
ascii_isdigit
(Data[I]) &&
ascii_isdigit
(
RHS
.
Data
[I])) {
//
The longer sequence of numbers is considered larger.
//
This doesn't really handle prefixed zeros well.
size_t
J;
for
(J = I +
1
; J != E +
1
; ++J) {
bool
ld = J < Length &&
ascii_isdigit
(Data[J]);
bool
rd = J <
RHS
.
Length
&&
ascii_isdigit
(
RHS
.
Data
[J]);
if
(ld != rd)
return
rd ? -
1
:
1
;
if
(!rd)
break
;
}
//
The two number sequences have the same length (J-I), just memcmp them.
if
(
int
Res =
compareMemory
(Data + I,
RHS
.
Data
+ I, J - I))
return
Res <
0
? -
1
:
1
;
//
Identical number sequences, continue search after the numbers.
I = J -
1
;
continue
;
}
if
(Data[I] !=
RHS
.
Data
[I])
return
(
unsigned
char
)Data[I] < (
unsigned
char
)
RHS
.
Data
[I] ? -
1
:
1
;
}
if
(Length ==
RHS
.
Length
)
return
0
;
return
Length <
RHS
.
Length
? -
1
:
1
;
}
//
Compute the edit distance between the two given strings.
unsigned
StringRef::edit_distance
(llvm::StringRef Other,
bool
AllowReplacements,
unsigned
MaxEditDistance)
const
{
return
llvm::ComputeEditDistance
(
makeArrayRef
(
data
(),
size
()),
makeArrayRef
(Other.
data
(), Other.
size
()),
AllowReplacements, MaxEditDistance);
}
//
===----------------------------------------------------------------------===//
//
String Operations
//
===----------------------------------------------------------------------===//
std::string
StringRef::lower
()
const
{
std::string
Result
(
size
(),
char
());
for
(size_type i =
0
, e =
size
(); i != e; ++i) {
Result[i] =
ascii_tolower
(Data[i]);
}
return
Result;
}
std::string
StringRef::upper
()
const
{
std::string
Result
(
size
(),
char
());
for
(size_type i =
0
, e =
size
(); i != e; ++i) {
Result[i] =
ascii_toupper
(Data[i]);
}
return
Result;
}
//
===----------------------------------------------------------------------===//
//
String Searching
//
===----------------------------------------------------------------------===//
//
/ find - Search for the first string \arg Str in the string.
//
/
//
/ \return - The index of the first occurrence of \arg Str, or npos if not
//
/ found.
size_t
StringRef::find
(StringRef Str,
size_t
From)
const
{
size_t
N = Str.
size
();
if
(N > Length)
return
npos;
//
For short haystacks or unsupported needles fall back to the naive algorithm
if
(Length <
16
|| N >
255
|| N ==
0
) {
for
(
size_t
e = Length - N +
1
, i =
std::min
(From, e); i != e; ++i)
if
(
substr
(i, N).
equals
(Str))
return
i;
return
npos;
}
if
(From >= Length)
return
npos;
//
Build the bad char heuristic table, with uint8_t to reduce cache thrashing.
uint8_t
BadCharSkip[
256
];
std::memset
(BadCharSkip, N,
256
);
for
(
unsigned
i =
0
; i != N-
1
; ++i)
BadCharSkip[(
uint8_t
)Str[i]] = N-
1
-i;
unsigned
Len = Length-From, Pos = From;
while
(Len >= N) {
if
(
substr
(Pos, N).
equals
(Str))
//
See if this is the correct substring.
return
Pos;
//
Otherwise skip the appropriate number of bytes.
uint8_t
Skip = BadCharSkip[(
uint8_t
)(*
this
)[Pos+N-
1
]];
Len -= Skip;
Pos += Skip;
}
return
npos;
}
//
/ rfind - Search for the last string \arg Str in the string.
//
/
//
/ \return - The index of the last occurrence of \arg Str, or npos if not
//
/ found.
size_t
StringRef::rfind
(StringRef Str)
const
{
size_t
N = Str.
size
();
if
(N > Length)
return
npos;
for
(
size_t
i = Length - N +
1
, e =
0
; i != e;) {
--i;
if
(
substr
(i, N).
equals
(Str))
return
i;
}
return
npos;
}
//
/ find_first_of - Find the first character in the string that is in \arg
//
/ Chars, or npos if not found.
//
/
//
/ Note: O(size() + Chars.size())
StringRef::size_type
StringRef::find_first_of
(StringRef Chars,
size_t
From)
const
{
std::bitset<
1
<<
CHAR_BIT
> CharBits;
for
(size_type i =
0
; i != Chars.
size
(); ++i)
CharBits.
set
((
unsigned
char
)Chars[i]);
for
(size_type i =
std::min
(From, Length), e = Length; i != e; ++i)
if
(CharBits.
test
((
unsigned
char
)Data[i]))
return
i;
return
npos;
}
//
/ find_first_not_of - Find the first character in the string that is not
//
/ \arg C or npos if not found.
StringRef::size_type
StringRef::find_first_not_of
(
char
C,
size_t
From)
const
{
for
(size_type i =
std::min
(From, Length), e = Length; i != e; ++i)
if
(Data[i] != C)
return
i;
return
npos;
}
//
/ find_first_not_of - Find the first character in the string that is not
//
/ in the string \arg Chars, or npos if not found.
//
/
//
/ Note: O(size() + Chars.size())
StringRef::size_type
StringRef::find_first_not_of
(StringRef Chars,
size_t
From)
const
{
std::bitset<
1
<<
CHAR_BIT
> CharBits;
for
(size_type i =
0
; i != Chars.
size
(); ++i)
CharBits.
set
((
unsigned
char
)Chars[i]);
for
(size_type i =
std::min
(From, Length), e = Length; i != e; ++i)
if
(!CharBits.
test
((
unsigned
char
)Data[i]))
return
i;
return
npos;
}
//
/ find_last_of - Find the last character in the string that is in \arg C,
//
/ or npos if not found.
//
/
//
/ Note: O(size() + Chars.size())
StringRef::size_type
StringRef::find_last_of
(StringRef Chars,
size_t
From)
const
{
std::bitset<
1
<<
CHAR_BIT
> CharBits;
for
(size_type i =
0
; i != Chars.
size
(); ++i)
CharBits.
set
((
unsigned
char
)Chars[i]);
for
(size_type i =
std::min
(From, Length) -
1
, e = -
1
; i != e; --i)
if
(CharBits.
test
((
unsigned
char
)Data[i]))
return
i;
return
npos;
}
//
/ find_last_not_of - Find the last character in the string that is not
//
/ \arg C, or npos if not found.
StringRef::size_type
StringRef::find_last_not_of
(
char
C,
size_t
From)
const
{
for
(size_type i =
std::min
(From, Length) -
1
, e = -
1
; i != e; --i)
if
(Data[i] != C)
return
i;
return
npos;
}
//
/ find_last_not_of - Find the last character in the string that is not in
//
/ \arg Chars, or npos if not found.
//
/
//
/ Note: O(size() + Chars.size())
StringRef::size_type
StringRef::find_last_not_of
(StringRef Chars,
size_t
From)
const
{
std::bitset<
1
<<
CHAR_BIT
> CharBits;
for
(size_type i =
0
, e = Chars.
size
(); i != e; ++i)
CharBits.
set
((
unsigned
char
)Chars[i]);
for
(size_type i =
std::min
(From, Length) -
1
, e = -
1
; i != e; --i)
if
(!CharBits.
test
((
unsigned
char
)Data[i]))
return
i;
return
npos;
}
void
StringRef::split
(SmallVectorImpl<StringRef> &A,
StringRef Separators,
int
MaxSplit,
bool
KeepEmpty)
const
{
StringRef rest = *
this
;
//
rest.data() is used to distinguish cases like "a," that splits into
//
"a" + "" and "a" that splits into "a" + 0.
for
(
int
splits =
0
;
rest.
data
() !=
nullptr
&& (MaxSplit <
0
|| splits < MaxSplit);
++splits) {
std::pair<StringRef, StringRef> p = rest.
split
(Separators);
if
(KeepEmpty || p.
first
.
size
() !=
0
)
A.
push_back
(p.
first
);
rest = p.
second
;
}
//
If we have a tail left, add it.
if
(rest.
data
() !=
nullptr
&& (rest.
size
() !=
0
|| KeepEmpty))
A.
push_back
(rest);
}
//
===----------------------------------------------------------------------===//
//
Helpful Algorithms
//
===----------------------------------------------------------------------===//
//
/ count - Return the number of non-overlapped occurrences of \arg Str in
//
/ the string.
size_t
StringRef::count
(StringRef Str)
const
{
size_t
Count =
0
;
size_t
N = Str.
size
();
if
(N > Length)
return
0
;
for
(
size_t
i =
0
, e = Length - N +
1
; i != e; ++i)
if
(
substr
(i, N).
equals
(Str))
++Count;
return
Count;
}
static
unsigned
GetAutoSenseRadix
(StringRef &Str) {
if
(Str.
startswith
(
"
0x
"
)) {
Str = Str.
substr
(
2
);
return
16
;
}
if
(Str.
startswith
(
"
0b
"
)) {
Str = Str.
substr
(
2
);
return
2
;
}
if
(Str.
startswith
(
"
0o
"
)) {
Str = Str.
substr
(
2
);
return
8
;
}
if
(Str.
startswith
(
"
0
"
))
return
8
;
return
10
;
}
//
/ GetAsUnsignedInteger - Workhorse method that converts a integer character
//
/ sequence of radix up to 36 to an unsigned long long value.
bool
llvm::getAsUnsignedInteger
(StringRef Str,
unsigned
Radix,
unsigned
long
long
&Result) {
//
Autosense radix if not specified.
if
(Radix ==
0
)
Radix =
GetAutoSenseRadix
(Str);
//
Empty strings (after the radix autosense) are invalid.
if
(Str.
empty
())
return
true
;
//
Parse all the bytes of the string given this radix. Watch for overflow.
Result =
0
;
while
(!Str.
empty
()) {
unsigned
CharVal;
if
(Str[
0
] >=
'
0
'
&& Str[
0
] <=
'
9
'
)
CharVal = Str[
0
]-
'
0
'
;
else
if
(Str[
0
] >=
'
a
'
&& Str[
0
] <=
'
z
'
)
CharVal = Str[
0
]-
'
a
'
+
10
;
else
if
(Str[
0
] >=
'
A
'
&& Str[
0
] <=
'
Z
'
)
CharVal = Str[
0
]-
'
A
'
+
10
;
else
return
true
;
//
If the parsed value is larger than the integer radix, the string is
//
invalid.
if
(CharVal >= Radix)
return
true
;
//
Add in this character.
unsigned
long
long
PrevResult = Result;
Result = Result*Radix+CharVal;
//
Check for overflow by shifting back and seeing if bits were lost.
if
(Result/Radix < PrevResult)
return
true
;
Str = Str.
substr
(
1
);
}
return
false
;
}
bool
llvm::getAsSignedInteger
(StringRef Str,
unsigned
Radix,
long
long
&Result) {
unsigned
long
long
ULLVal;
//
Handle positive strings first.
if
(Str.
empty
() || Str.
front
() !=
'
-
'
) {
if
(
getAsUnsignedInteger
(Str, Radix, ULLVal) ||
//
Check for value so large it overflows a signed value.
(
long
long
)ULLVal <
0
)
return
true
;
Result = ULLVal;
return
false
;
}
//
Get the positive part of the value.
if
(
getAsUnsignedInteger
(Str.
substr
(
1
), Radix, ULLVal) ||
//
Reject values larger than what can be represented as negative signed.
//
The most negative long long is LLONG_MIN, which has magnitude
//
(LLONG_MAX + 1). Values larger than this magnitude cannot be negated
//
without overflow.
ULLVal >
static_cast
<
unsigned
long
long
>(
std::numeric_limits<
long
long
>::
max
()) +
1
)
return
true
;
Result = (~ULLVal +
1
);
return
false
;
}
bool
StringRef::getAsInteger
(
unsigned
Radix, APInt &Result)
const
{
StringRef Str = *
this
;
//
Autosense radix if not specified.
if
(Radix ==
0
)
Radix =
GetAutoSenseRadix
(Str);
assert
(Radix >
1
&& Radix <=
36
);
//
Empty strings (after the radix autosense) are invalid.
if
(Str.
empty
())
return
true
;
//
Skip leading zeroes. This can be a significant improvement if
//
it means we don't need > 64 bits.
while
(!Str.
empty
() && Str.
front
() ==
'
0
'
)
Str = Str.
substr
(
1
);
//
If it was nothing but zeroes....
if
(Str.
empty
()) {
Result =
APInt
(
64
,
0
);
return
false
;
}
//
(Over-)estimate the required number of bits.
unsigned
Log2Radix =
0
;
while
((
1U
<< Log2Radix) < Radix) Log2Radix++;
bool
IsPowerOf2Radix = ((
1U
<< Log2Radix) == Radix);
unsigned
BitWidth = Log2Radix * Str.
size
();
if
(BitWidth < Result.
getBitWidth
())
BitWidth = Result.
getBitWidth
();
//
don't shrink the result
else
if
(BitWidth > Result.
getBitWidth
())
Result = Result.
zext
(BitWidth);
APInt RadixAP, CharAP;
//
unused unless !IsPowerOf2Radix
if
(!IsPowerOf2Radix) {
//
These must have the same bit-width as Result.
RadixAP =
APInt
(BitWidth, Radix);
CharAP =
APInt
(BitWidth,
0
);
}
//
Parse all the bytes of the string given this radix.
Result =
0
;
while
(!Str.
empty
()) {
unsigned
CharVal;
if
(Str[
0
] >=
'
0
'
&& Str[
0
] <=
'
9
'
)
CharVal = Str[
0
]-
'
0
'
;
else
if
(Str[
0
] >=
'
a
'
&& Str[
0
] <=
'
z
'
)
CharVal = Str[
0
]-
'
a
'
+
10
;
else
if
(Str[
0
] >=
'
A
'
&& Str[
0
] <=
'
Z
'
)
CharVal = Str[
0
]-
'
A
'
+
10
;
else
return
true
;
//
If the parsed value is larger than the integer radix, the string is
//
invalid.
if
(CharVal >= Radix)
return
true
;
//
Add in this character.
if
(IsPowerOf2Radix) {
Result <<= Log2Radix;
Result |= CharVal;
}
else
{
Result *= RadixAP;
CharAP = CharVal;
Result += CharAP;
}
Str = Str.
substr
(
1
);
}
return
false
;
}
//
Implementation of StringRef hashing.
hash_code
llvm::hash_value
(StringRef S) {
return
hash_combine_range
(S.
begin
(), S.
end
());
}
Back
|
FazBrowse Home
|
New Git URL