blob: a4c0e87c28eacd1574f4f1bc4da72b334d262bc4 [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) {
Chris Lattner6441e542009-09-20 22:56:43 +000092 if (Str.startswith("0x")) {
93 Str = Str.substr(2);
94 Radix = 16;
95 } else if (Str.startswith("0b")) {
96 Str = Str.substr(2);
97 Radix = 2;
98 } else if (Str.startswith("0"))
99 Radix = 8;
100 else
Chris Lattnercea14382009-09-19 19:47:14 +0000101 Radix = 10;
Chris Lattnercea14382009-09-19 19:47:14 +0000102 }
103
104 // Empty strings (after the radix autosense) are invalid.
105 if (Str.empty()) return true;
106
107 // Parse all the bytes of the string given this radix. Watch for overflow.
108 Result = 0;
109 while (!Str.empty()) {
110 unsigned CharVal;
111 if (Str[0] >= '0' && Str[0] <= '9')
112 CharVal = Str[0]-'0';
113 else if (Str[0] >= 'a' && Str[0] <= 'z')
114 CharVal = Str[0]-'a'+10;
115 else if (Str[0] >= 'A' && Str[0] <= 'Z')
116 CharVal = Str[0]-'A'+10;
117 else
118 return true;
119
120 // If the parsed value is larger than the integer radix, the string is
121 // invalid.
122 if (CharVal >= Radix)
123 return true;
124
125 // Add in this character.
126 unsigned long long PrevResult = Result;
127 Result = Result*Radix+CharVal;
128
129 // Check for overflow.
130 if (Result < PrevResult)
131 return true;
132
133 Str = Str.substr(1);
134 }
135
136 return false;
137}
138
139bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
140 return GetAsUnsignedInteger(*this, Radix, Result);
141}
142
Chris Lattner63c6b7d2009-09-19 23:58:48 +0000143
144bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
145 unsigned long long ULLVal;
146
147 // Handle positive strings first.
148 if (empty() || front() != '-') {
149 if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
150 // Check for value so large it overflows a signed value.
151 (long long)ULLVal < 0)
152 return true;
153 Result = ULLVal;
154 return false;
155 }
156
157 // Get the positive part of the value.
158 if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
159 // Reject values so large they'd overflow as negative signed, but allow
160 // "-0". This negates the unsigned so that the negative isn't undefined
161 // on signed overflow.
162 (long long)-ULLVal > 0)
163 return true;
164
165 Result = -ULLVal;
166 return false;
167}
168
169bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
170 long long Val;
171 if (getAsInteger(Radix, Val) ||
172 (int)Val != Val)
173 return true;
174 Result = Val;
175 return false;
176}
177
178bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
179 unsigned long long Val;
180 if (getAsInteger(Radix, Val) ||
181 (unsigned)Val != Val)
182 return true;
183 Result = Val;
184 return false;
185}