Switch StringRef::edit_distance over to using raw pointers, since both
[oota-llvm.git] / lib / Support / StringRef.cpp
1 //===-- 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"
11 #include <cstring>
12
13 using namespace llvm;
14
15 // MSVC emits references to this into the translation units which reference it.
16 #ifndef _MSC_VER
17 const size_t StringRef::npos;
18 #endif
19
20 static char ascii_tolower(char x) {
21   if (x >= 'A' && x <= 'Z')
22     return x - 'A' + 'a';
23   return x;
24 }
25
26 /// compare_lower - Compare strings, ignoring case.
27 int StringRef::compare_lower(StringRef RHS) const {
28   for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) {
29     char LHC = ascii_tolower(Data[I]);
30     char RHC = ascii_tolower(RHS.Data[I]);
31     if (LHC != RHC)
32       return LHC < RHC ? -1 : 1;
33   }
34
35   if (Length == RHS.Length)
36         return 0;
37   return Length < RHS.Length ? -1 : 1;
38 }
39
40 // Compute the edit distance between the two given strings.
41 unsigned StringRef::edit_distance(llvm::StringRef Other, 
42                                   bool AllowReplacements) {
43   // The algorithm implemented below is the "classic"
44   // dynamic-programming algorithm for computing the Levenshtein
45   // distance, which is described here:
46   //
47   //   http://en.wikipedia.org/wiki/Levenshtein_distance
48   //
49   // Although the algorithm is typically described using an m x n
50   // array, only two rows are used at a time, so this implemenation
51   // just keeps two separate vectors for those two rows.
52   size_type m = size();
53   size_type n = Other.size();
54
55   unsigned SmallPrevious[32];
56   unsigned SmallCurrent[32];
57   
58   unsigned *previous = SmallPrevious;
59   unsigned *current = SmallCurrent;
60   if (n + 1 > 32) {
61     previous = new unsigned [n+1];
62     current = new unsigned [n+1];
63   }
64   
65   for (unsigned i = 0; i <= n; ++i) 
66     previous[i] = i;
67
68   for (size_type y = 1; y <= m; ++y) {
69     std::memset(current, 0, (n + 1) * sizeof(unsigned));
70     current[0] = y;
71     for (size_type x = 1; x <= n; ++x) {
72       if (AllowReplacements) {
73         current[x] = min(previous[x-1] + ((*this)[y-1] == Other[x-1]? 0u:1u),
74                          min(current[x-1], previous[x])+1);
75       }
76       else {
77         if ((*this)[y-1] == Other[x-1]) current[x] = previous[x-1];
78         else current[x] = min(current[x-1], previous[x]) + 1;
79       }
80     }
81     
82     unsigned *tmp = current;
83     current = previous;
84     previous = tmp;
85   }
86
87   unsigned Result = previous[n];
88   if (n + 1 > 32) {
89     delete [] previous;
90     delete [] current;
91   }
92   
93   return Result;
94 }
95
96 //===----------------------------------------------------------------------===//
97 // String Searching
98 //===----------------------------------------------------------------------===//
99
100
101 /// find - Search for the first string \arg Str in the string.
102 ///
103 /// \return - The index of the first occurence of \arg Str, or npos if not
104 /// found.
105 size_t StringRef::find(StringRef Str, size_t From) const {
106   size_t N = Str.size();
107   if (N > Length)
108     return npos;
109   for (size_t e = Length - N + 1, i = min(From, e); i != e; ++i)
110     if (substr(i, N).equals(Str))
111       return i;
112   return npos;
113 }
114
115 /// rfind - Search for the last string \arg Str in the string.
116 ///
117 /// \return - The index of the last occurence of \arg Str, or npos if not
118 /// found.
119 size_t StringRef::rfind(StringRef Str) const {
120   size_t N = Str.size();
121   if (N > Length)
122     return npos;
123   for (size_t i = Length - N + 1, e = 0; i != e;) {
124     --i;
125     if (substr(i, N).equals(Str))
126       return i;
127   }
128   return npos;
129 }
130
131 /// find_first_of - Find the first character in the string that is in \arg
132 /// Chars, or npos if not found.
133 ///
134 /// Note: O(size() * Chars.size())
135 StringRef::size_type StringRef::find_first_of(StringRef Chars,
136                                               size_t From) const {
137   for (size_type i = min(From, Length), e = Length; i != e; ++i)
138     if (Chars.find(Data[i]) != npos)
139       return i;
140   return npos;
141 }
142
143 /// find_first_not_of - Find the first character in the string that is not
144 /// \arg C or npos if not found.
145 StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const {
146   for (size_type i = min(From, Length), e = Length; i != e; ++i)
147     if (Data[i] != C)
148       return i;
149   return npos;
150 }
151
152 /// find_first_not_of - Find the first character in the string that is not
153 /// in the string \arg Chars, or npos if not found.
154 ///
155 /// Note: O(size() * Chars.size())
156 StringRef::size_type StringRef::find_first_not_of(StringRef Chars,
157                                                   size_t From) const {
158   for (size_type i = min(From, Length), e = Length; i != e; ++i)
159     if (Chars.find(Data[i]) == npos)
160       return i;
161   return npos;
162 }
163
164
165 //===----------------------------------------------------------------------===//
166 // Helpful Algorithms
167 //===----------------------------------------------------------------------===//
168
169 /// count - Return the number of non-overlapped occurrences of \arg Str in
170 /// the string.
171 size_t StringRef::count(StringRef Str) const {
172   size_t Count = 0;
173   size_t N = Str.size();
174   if (N > Length)
175     return 0;
176   for (size_t i = 0, e = Length - N + 1; i != e; ++i)
177     if (substr(i, N).equals(Str))
178       ++Count;
179   return Count;
180 }
181
182 /// GetAsUnsignedInteger - Workhorse method that converts a integer character
183 /// sequence of radix up to 36 to an unsigned long long value.
184 static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
185                                  unsigned long long &Result) {
186   // Autosense radix if not specified.
187   if (Radix == 0) {
188     if (Str.startswith("0x")) {
189       Str = Str.substr(2);
190       Radix = 16;
191     } else if (Str.startswith("0b")) {
192       Str = Str.substr(2);
193       Radix = 2;
194     } else if (Str.startswith("0"))
195       Radix = 8;
196     else
197       Radix = 10;
198   }
199   
200   // Empty strings (after the radix autosense) are invalid.
201   if (Str.empty()) return true;
202   
203   // Parse all the bytes of the string given this radix.  Watch for overflow.
204   Result = 0;
205   while (!Str.empty()) {
206     unsigned CharVal;
207     if (Str[0] >= '0' && Str[0] <= '9')
208       CharVal = Str[0]-'0';
209     else if (Str[0] >= 'a' && Str[0] <= 'z')
210       CharVal = Str[0]-'a'+10;
211     else if (Str[0] >= 'A' && Str[0] <= 'Z')
212       CharVal = Str[0]-'A'+10;
213     else
214       return true;
215     
216     // If the parsed value is larger than the integer radix, the string is
217     // invalid.
218     if (CharVal >= Radix)
219       return true;
220     
221     // Add in this character.
222     unsigned long long PrevResult = Result;
223     Result = Result*Radix+CharVal;
224     
225     // Check for overflow.
226     if (Result < PrevResult)
227       return true;
228
229     Str = Str.substr(1);
230   }
231   
232   return false;
233 }
234
235 bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
236   return GetAsUnsignedInteger(*this, Radix, Result);
237 }
238
239
240 bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
241   unsigned long long ULLVal;
242   
243   // Handle positive strings first.
244   if (empty() || front() != '-') {
245     if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
246         // Check for value so large it overflows a signed value.
247         (long long)ULLVal < 0)
248       return true;
249     Result = ULLVal;
250     return false;
251   }
252   
253   // Get the positive part of the value.
254   if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
255       // Reject values so large they'd overflow as negative signed, but allow
256       // "-0".  This negates the unsigned so that the negative isn't undefined
257       // on signed overflow.
258       (long long)-ULLVal > 0)
259     return true;
260   
261   Result = -ULLVal;
262   return false;
263 }
264
265 bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
266   long long Val;
267   if (getAsInteger(Radix, Val) ||
268       (int)Val != Val)
269     return true;
270   Result = Val;
271   return false;
272 }
273
274 bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
275   unsigned long long Val;
276   if (getAsInteger(Radix, Val) ||
277       (unsigned)Val != Val)
278     return true;
279   Result = Val;
280   return false;
281 }