add some more overloads of StringRef::getAsInteger for
[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 using namespace llvm;
12
13 const size_t StringRef::npos;
14
15 /// GetAsUnsignedInteger - Workhorse method that converts a integer character
16 /// sequence of radix up to 36 to an unsigned long long value.
17 static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix,
18                                  unsigned long long &Result) {
19   // Autosense radix if not specified.
20   if (Radix == 0) {
21     if (Str[0] != '0') {
22       Radix = 10;
23     } else {
24       if (Str.size() < 2) {
25         Radix = 8;
26       } else {
27         if (Str[1] == 'x') {
28           Str = Str.substr(2);
29           Radix = 16;
30         } else if (Str[1] == 'b') {
31           Str = Str.substr(2);
32           Radix = 2;
33         } else {
34           Radix = 8;
35         }
36       }
37     }
38   }
39   
40   // Empty strings (after the radix autosense) are invalid.
41   if (Str.empty()) return true;
42   
43   // Parse all the bytes of the string given this radix.  Watch for overflow.
44   Result = 0;
45   while (!Str.empty()) {
46     unsigned CharVal;
47     if (Str[0] >= '0' && Str[0] <= '9')
48       CharVal = Str[0]-'0';
49     else if (Str[0] >= 'a' && Str[0] <= 'z')
50       CharVal = Str[0]-'a'+10;
51     else if (Str[0] >= 'A' && Str[0] <= 'Z')
52       CharVal = Str[0]-'A'+10;
53     else
54       return true;
55     
56     // If the parsed value is larger than the integer radix, the string is
57     // invalid.
58     if (CharVal >= Radix)
59       return true;
60     
61     // Add in this character.
62     unsigned long long PrevResult = Result;
63     Result = Result*Radix+CharVal;
64     
65     // Check for overflow.
66     if (Result < PrevResult)
67       return true;
68
69     Str = Str.substr(1);
70   }
71   
72   return false;
73 }
74
75 bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const {
76   return GetAsUnsignedInteger(*this, Radix, Result);
77 }
78
79
80 bool StringRef::getAsInteger(unsigned Radix, long long &Result) const {
81   unsigned long long ULLVal;
82   
83   // Handle positive strings first.
84   if (empty() || front() != '-') {
85     if (GetAsUnsignedInteger(*this, Radix, ULLVal) ||
86         // Check for value so large it overflows a signed value.
87         (long long)ULLVal < 0)
88       return true;
89     Result = ULLVal;
90     return false;
91   }
92   
93   // Get the positive part of the value.
94   if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) ||
95       // Reject values so large they'd overflow as negative signed, but allow
96       // "-0".  This negates the unsigned so that the negative isn't undefined
97       // on signed overflow.
98       (long long)-ULLVal > 0)
99     return true;
100   
101   Result = -ULLVal;
102   return false;
103 }
104
105 bool StringRef::getAsInteger(unsigned Radix, int &Result) const {
106   long long Val;
107   if (getAsInteger(Radix, Val) ||
108       (int)Val != Val)
109     return true;
110   Result = Val;
111   return false;
112 }
113
114 bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const {
115   unsigned long long Val;
116   if (getAsInteger(Radix, Val) ||
117       (unsigned)Val != Val)
118     return true;
119   Result = Val;
120   return false;
121 }