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 using namespace llvm; 12 13 // MSVC emits references to this into the translation units which reference it. 14 #ifndef _MSC_VER 15 const size_t StringRef::npos; 16 #endif 17 18 static char ascii_tolower(char x) { 19 if (x >= 'A' && x <= 'Z') 20 return x - 'A' + 'a'; 21 return x; 22 } 23 24 /// compare_lower - Compare strings, ignoring case. 25 int StringRef::compare_lower(StringRef RHS) const { 26 for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) { 27 char LHC = ascii_tolower(Data[I]); 28 char RHC = ascii_tolower(RHS.Data[I]); 29 if (LHC != RHC) 30 return LHC < RHC ? -1 : 1; 31 } 32 33 if (Length == RHS.Length) 34 return 0; 35 return Length < RHS.Length ? -1 : 1; 36 } 37 38 //===----------------------------------------------------------------------===// 39 // String Searching 40 //===----------------------------------------------------------------------===// 41 42 43 /// find - Search for the first string \arg Str in the string. 44 /// 45 /// \return - The index of the first occurence of \arg Str, or npos if not 46 /// found. 47 size_t StringRef::find(StringRef Str, size_t From) const { 48 size_t N = Str.size(); 49 if (N > Length) 50 return npos; 51 for (size_t e = Length - N + 1, i = std::min(From, e); i != e; ++i) 52 if (substr(i, N).equals(Str)) 53 return i; 54 return npos; 55 } 56 57 /// rfind - Search for the last string \arg Str in the string. 58 /// 59 /// \return - The index of the last occurence of \arg Str, or npos if not 60 /// found. 61 size_t StringRef::rfind(StringRef Str) const { 62 size_t N = Str.size(); 63 if (N > Length) 64 return npos; 65 for (size_t i = Length - N + 1, e = 0; i != e;) { 66 --i; 67 if (substr(i, N).equals(Str)) 68 return i; 69 } 70 return npos; 71 } 72 73 /// find_first_of - Find the first character in the string that is in \arg 74 /// Chars, or npos if not found. 75 /// 76 /// Note: O(size() * Chars.size()) 77 StringRef::size_type StringRef::find_first_of(StringRef Chars, 78 size_t From) const { 79 for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 80 if (Chars.find(Data[i]) != npos) 81 return i; 82 return npos; 83 } 84 85 /// find_first_not_of - Find the first character in the string that is not 86 /// \arg C or npos if not found. 87 StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { 88 for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 89 if (Data[i] != C) 90 return i; 91 return npos; 92 } 93 94 /// find_first_not_of - Find the first character in the string that is not 95 /// in the string \arg Chars, or npos if not found. 96 /// 97 /// Note: O(size() * Chars.size()) 98 StringRef::size_type StringRef::find_first_not_of(StringRef Chars, 99 size_t From) const { 100 for (size_type i = std::min(From, Length), e = Length; i != e; ++i) 101 if (Chars.find(Data[i]) == npos) 102 return i; 103 return npos; 104 } 105 106 107 //===----------------------------------------------------------------------===// 108 // Helpful Algorithms 109 //===----------------------------------------------------------------------===// 110 111 /// count - Return the number of non-overlapped occurrences of \arg Str in 112 /// the string. 113 size_t StringRef::count(StringRef Str) const { 114 size_t Count = 0; 115 size_t N = Str.size(); 116 if (N > Length) 117 return 0; 118 for (size_t i = 0, e = Length - N + 1; i != e; ++i) 119 if (substr(i, N).equals(Str)) 120 ++Count; 121 return Count; 122 } 123 124 /// GetAsUnsignedInteger - Workhorse method that converts a integer character 125 /// sequence of radix up to 36 to an unsigned long long value. 126 static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix, 127 unsigned long long &Result) { 128 // Autosense radix if not specified. 129 if (Radix == 0) { 130 if (Str.startswith("0x")) { 131 Str = Str.substr(2); 132 Radix = 16; 133 } else if (Str.startswith("0b")) { 134 Str = Str.substr(2); 135 Radix = 2; 136 } else if (Str.startswith("0")) 137 Radix = 8; 138 else 139 Radix = 10; 140 } 141 142 // Empty strings (after the radix autosense) are invalid. 143 if (Str.empty()) return true; 144 145 // Parse all the bytes of the string given this radix. Watch for overflow. 146 Result = 0; 147 while (!Str.empty()) { 148 unsigned CharVal; 149 if (Str[0] >= '0' && Str[0] <= '9') 150 CharVal = Str[0]-'0'; 151 else if (Str[0] >= 'a' && Str[0] <= 'z') 152 CharVal = Str[0]-'a'+10; 153 else if (Str[0] >= 'A' && Str[0] <= 'Z') 154 CharVal = Str[0]-'A'+10; 155 else 156 return true; 157 158 // If the parsed value is larger than the integer radix, the string is 159 // invalid. 160 if (CharVal >= Radix) 161 return true; 162 163 // Add in this character. 164 unsigned long long PrevResult = Result; 165 Result = Result*Radix+CharVal; 166 167 // Check for overflow. 168 if (Result < PrevResult) 169 return true; 170 171 Str = Str.substr(1); 172 } 173 174 return false; 175 } 176 177 bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const { 178 return GetAsUnsignedInteger(*this, Radix, Result); 179 } 180 181 182 bool StringRef::getAsInteger(unsigned Radix, long long &Result) const { 183 unsigned long long ULLVal; 184 185 // Handle positive strings first. 186 if (empty() || front() != '-') { 187 if (GetAsUnsignedInteger(*this, Radix, ULLVal) || 188 // Check for value so large it overflows a signed value. 189 (long long)ULLVal < 0) 190 return true; 191 Result = ULLVal; 192 return false; 193 } 194 195 // Get the positive part of the value. 196 if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) || 197 // Reject values so large they'd overflow as negative signed, but allow 198 // "-0". This negates the unsigned so that the negative isn't undefined 199 // on signed overflow. 200 (long long)-ULLVal > 0) 201 return true; 202 203 Result = -ULLVal; 204 return false; 205 } 206 207 bool StringRef::getAsInteger(unsigned Radix, int &Result) const { 208 long long Val; 209 if (getAsInteger(Radix, Val) || 210 (int)Val != Val) 211 return true; 212 Result = Val; 213 return false; 214 } 215 216 bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const { 217 unsigned long long Val; 218 if (getAsInteger(Radix, Val) || 219 (unsigned)Val != Val) 220 return true; 221 Result = Val; 222 return false; 223 } 224