blob: 6905edf19e12be1dd16a547326a9e9d05dae21a8 [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
Daniel Dunbar77696be2009-09-22 03:34:40 +000013// MSVC emits references to this into the translation units which reference it.
14#ifndef _MSC_VER
Daniel Dunbare6551282009-09-16 22:38:48 +000015const size_t StringRef::npos;
Daniel Dunbar77696be2009-09-22 03:34:40 +000016#endif
Chris Lattnercea14382009-09-19 19:47:14 +000017
Chris Lattner05a32c82009-09-20 01:22:16 +000018//===----------------------------------------------------------------------===//
19// String Searching
20//===----------------------------------------------------------------------===//
21
22
23/// find - Search for the first string \arg Str in the string.
24///
25/// \return - The index of the first occurence of \arg Str, or npos if not
26/// found.
Daniel Dunbar64066bd2009-11-11 00:28:53 +000027size_t StringRef::find(StringRef Str, size_t From) const {
Chris Lattner05a32c82009-09-20 01:22:16 +000028 size_t N = Str.size();
29 if (N > Length)
30 return npos;
Daniel Dunbar64066bd2009-11-11 00:28:53 +000031 for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i)
Chris Lattner05a32c82009-09-20 01:22:16 +000032 if (substr(i, N).equals(Str))
33 return i;
34 return npos;
35}
36
37/// rfind - Search for the last string \arg Str in the string.
38///
39/// \return - The index of the last occurence of \arg Str, or npos if not
40/// found.
Daniel Dunbar2928c832009-11-06 10:58:06 +000041size_t StringRef::rfind(StringRef Str) const {
Chris Lattner05a32c82009-09-20 01:22:16 +000042 size_t N = Str.size();
43 if (N > Length)
44 return npos;
45 for (size_t i = Length - N + 1, e = 0; i != e;) {
46 --i;
47 if (substr(i, N).equals(Str))
48 return i;
49 }
50 return npos;
51}
52
Daniel Dunbar64066bd2009-11-11 00:28:53 +000053/// find_first_of - Find the first character in the string that is in \arg
54/// Chars, or npos if not found.
55///
56/// Note: O(size() * Chars.size())
57StringRef::size_type StringRef::find_first_of(StringRef Chars,
58 size_t From) const {
59 for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
Chris Lattner05a32c82009-09-20 01:22:16 +000060 if (Chars.find(Data[i]) != npos)
61 return i;
62 return npos;
63}
64
65/// find_first_not_of - Find the first character in the string that is not
Daniel Dunbar64066bd2009-11-11 00:28:53 +000066/// \arg C or npos if not found.
67StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const {
68 for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
69 if (Data[i] != C)
70 return i;
71 return npos;
72}
73
74/// find_first_not_of - Find the first character in the string that is not
75/// in the string \arg Chars, or npos if not found.
76///
77/// Note: O(size() * Chars.size())
78StringRef::size_type StringRef::find_first_not_of(StringRef Chars,
79 size_t From) const {
80 for (size_type i = std::min(From, Length), e = Length; i != e; ++i)
Chris Lattner05a32c82009-09-20 01:22:16 +000081 if (Chars.find(Data[i]) == npos)
82 return i;
83 return npos;
84}
85
86
87//===----------------------------------------------------------------------===//
88// Helpful Algorithms
89//===----------------------------------------------------------------------===//
90
91/// count - Return the number of non-overlapped occurrences of \arg Str in
92/// the string.
Daniel Dunbar2928c832009-11-06 10:58:06 +000093size_t StringRef::count(StringRef Str) const {
Chris Lattner05a32c82009-09-20 01:22:16 +000094 size_t Count = 0;
95 size_t N = Str.size();
96 if (N > Length)
97 return 0;
98 for (size_t i = 0, e = Length - N + 1; i != e; ++i)
99 if (substr(i, N).equals(Str))
100 ++Count;
101 return Count;
102}
103
Chris Lattner63c6b7d2009-09-19 23:58:48 +0000104/// GetAsUnsignedInteger - Workhorse method that converts a integer character
105/// sequence of radix up to 36 to an unsigned long long value.
Chris Lattnercea14382009-09-19 19:47:14 +0000106static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
107 unsigned long long &Result) {
108 // Autosense radix if not specified.
109 if (Radix == 0) {
Chris Lattner6441e542009-09-20 22:56:43 +0000110 if (Str.startswith("0x")) {
111 Str = Str.substr(2);
112 Radix = 16;
113 } else if (Str.startswith("0b")) {
114 Str = Str.substr(2);
115 Radix = 2;
116 } else if (Str.startswith("0"))
117 Radix = 8;
118 else
Chris Lattnercea14382009-09-19 19:47:14 +0000119 Radix = 10;
Chris Lattnercea14382009-09-19 19:47:14 +0000120 }
121
122 // Empty strings (after the radix autosense) are invalid.
123 if (Str.empty()) return true;
124
125 // Parse all the bytes of the string given this radix. Watch for overflow.
126 Result = 0;
127 while (!Str.empty()) {
128 unsigned CharVal;
129 if (Str[0] >= '0' && Str[0] <= '9')
130 CharVal = Str[0]-'0';
131 else if (Str[0] >= 'a' && Str[0] <= 'z')
132 CharVal = Str[0]-'a'+10;
133 else if (Str[0] >= 'A' && Str[0] <= 'Z')
134 CharVal = Str[0]-'A'+10;
135 else
136 return true;
137
138 // If the parsed value is larger than the integer radix, the string is
139 // invalid.
140 if (CharVal >= Radix)
141 return true;
142
143 // Add in this character.
144 unsigned long long PrevResult = Result;
145 Result = Result*Radix+CharVal;
146
147 // Check for overflow.
148 if (Result < PrevResult)
149 return true;
150
151 Str = Str.substr(1);
152 }
153
154 return false;
155}
156
157bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
158 return GetAsUnsignedInteger(*this, Radix, Result);
159}
160
Chris Lattner63c6b7d2009-09-19 23:58:48 +0000161
162bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
163 unsigned long long ULLVal;
164
165 // Handle positive strings first.
166 if (empty() || front() != '-') {
167 if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
168 // Check for value so large it overflows a signed value.
169 (long long)ULLVal < 0)
170 return true;
171 Result = ULLVal;
172 return false;
173 }
174
175 // Get the positive part of the value.
176 if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
177 // Reject values so large they'd overflow as negative signed, but allow
178 // "-0". This negates the unsigned so that the negative isn't undefined
179 // on signed overflow.
180 (long long)-ULLVal > 0)
181 return true;
182
183 Result = -ULLVal;
184 return false;
185}
186
187bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
188 long long Val;
189 if (getAsInteger(Radix, Val) ||
190 (int)Val != Val)
191 return true;
192 Result = Val;
193 return false;
194}
195
196bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
197 unsigned long long Val;
198 if (getAsInteger(Radix, Val) ||
199 (unsigned)Val != Val)
200 return true;
201 Result = Val;
202 return false;
203}