blob: af64642a989d96b12e8761f3b01f651bf6749c73 [file] [log] [blame]
Daniel Dunbare6551282009-09-16 22:38:48 +00001//===-- StringRef.cpp - Lightweight String References ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/ADT/StringRef.h"
11using namespace llvm;
12
13const size_t StringRef::npos;
Chris Lattnercea14382009-09-19 19:47:14 +000014
Chris Lattner05a32c82009-09-20 01:22:16 +000015//===----------------------------------------------------------------------===//
16// String Searching
17//===----------------------------------------------------------------------===//
18
19
20/// find - Search for the first string \arg Str in the string.
21///
22/// \return - The index of the first occurence of \arg Str, or npos if not
23/// found.
24size_t StringRef::find(const StringRef &Str) const {
25 size_t N = Str.size();
26 if (N > Length)
27 return npos;
28 for (size_t i = 0, e = Length - N + 1; i != e; ++i)
29 if (substr(i, N).equals(Str))
30 return i;
31 return npos;
32}
33
34/// rfind - Search for the last string \arg Str in the string.
35///
36/// \return - The index of the last occurence of \arg Str, or npos if not
37/// found.
38size_t StringRef::rfind(const StringRef &Str) const {
39 size_t N = Str.size();
40 if (N > Length)
41 return npos;
42 for (size_t i = Length - N + 1, e = 0; i != e;) {
43 --i;
44 if (substr(i, N).equals(Str))
45 return i;
46 }
47 return npos;
48}
49
50/// find_first_of - Find the first character from the string 'Chars' in the
51/// current string or return npos if not in string.
52StringRef::size_type StringRef::find_first_of(StringRef Chars) const {
53 for (size_type i = 0, e = Length; i != e; ++i)
54 if (Chars.find(Data[i]) != npos)
55 return i;
56 return npos;
57}
58
59/// find_first_not_of - Find the first character in the string that is not
60/// in the string 'Chars' or return npos if all are in string. Same as find.
61StringRef::size_type StringRef::find_first_not_of(StringRef Chars) const {
62 for (size_type i = 0, e = Length; i != e; ++i)
63 if (Chars.find(Data[i]) == npos)
64 return i;
65 return npos;
66}
67
68
69//===----------------------------------------------------------------------===//
70// Helpful Algorithms
71//===----------------------------------------------------------------------===//
72
73/// count - Return the number of non-overlapped occurrences of \arg Str in
74/// the string.
75size_t StringRef::count(const StringRef &Str) const {
76 size_t Count = 0;
77 size_t N = Str.size();
78 if (N > Length)
79 return 0;
80 for (size_t i = 0, e = Length - N + 1; i != e; ++i)
81 if (substr(i, N).equals(Str))
82 ++Count;
83 return Count;
84}
85
Chris Lattner63c6b7d2009-09-19 23:58:48 +000086/// GetAsUnsignedInteger - Workhorse method that converts a integer character
87/// sequence of radix up to 36 to an unsigned long long value.
Chris Lattnercea14382009-09-19 19:47:14 +000088static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
89 unsigned long long &Result) {
90 // Autosense radix if not specified.
91 if (Radix == 0) {
92 if (Str[0] != '0') {
93 Radix = 10;
94 } else {
95 if (Str.size() < 2) {
96 Radix = 8;
97 } else {
98 if (Str[1] == 'x') {
99 Str = Str.substr(2);
100 Radix = 16;
101 } else if (Str[1] == 'b') {
102 Str = Str.substr(2);
103 Radix = 2;
104 } else {
105 Radix = 8;
106 }
107 }
108 }
109 }
110
111 // Empty strings (after the radix autosense) are invalid.
112 if (Str.empty()) return true;
113
114 // Parse all the bytes of the string given this radix. Watch for overflow.
115 Result = 0;
116 while (!Str.empty()) {
117 unsigned CharVal;
118 if (Str[0] >= '0' && Str[0] <= '9')
119 CharVal = Str[0]-'0';
120 else if (Str[0] >= 'a' && Str[0] <= 'z')
121 CharVal = Str[0]-'a'+10;
122 else if (Str[0] >= 'A' && Str[0] <= 'Z')
123 CharVal = Str[0]-'A'+10;
124 else
125 return true;
126
127 // If the parsed value is larger than the integer radix, the string is
128 // invalid.
129 if (CharVal >= Radix)
130 return true;
131
132 // Add in this character.
133 unsigned long long PrevResult = Result;
134 Result = Result*Radix+CharVal;
135
136 // Check for overflow.
137 if (Result < PrevResult)
138 return true;
139
140 Str = Str.substr(1);
141 }
142
143 return false;
144}
145
146bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
147 return GetAsUnsignedInteger(*this, Radix, Result);
148}
149
Chris Lattner63c6b7d2009-09-19 23:58:48 +0000150
151bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
152 unsigned long long ULLVal;
153
154 // Handle positive strings first.
155 if (empty() || front() != '-') {
156 if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
157 // Check for value so large it overflows a signed value.
158 (long long)ULLVal < 0)
159 return true;
160 Result = ULLVal;
161 return false;
162 }
163
164 // Get the positive part of the value.
165 if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
166 // Reject values so large they'd overflow as negative signed, but allow
167 // "-0". This negates the unsigned so that the negative isn't undefined
168 // on signed overflow.
169 (long long)-ULLVal > 0)
170 return true;
171
172 Result = -ULLVal;
173 return false;
174}
175
176bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
177 long long Val;
178 if (getAsInteger(Radix, Val) ||
179 (int)Val != Val)
180 return true;
181 Result = Val;
182 return false;
183}
184
185bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
186 unsigned long long Val;
187 if (getAsInteger(Radix, Val) ||
188 (unsigned)Val != Val)
189 return true;
190 Result = Val;
191 return false;
192}