Bug 790807: Add 64 bit nsAString::ToInteger; r=bsmedberg

This commit is contained in:
Steve Workman
2012-09-17 21:10:50 -04:00
parent ff695ae62a
commit 0bca6b8108
4 changed files with 210 additions and 0 deletions

View File

@@ -515,6 +515,36 @@ nsAString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
return result;
}
int64_t
nsAString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
{
NS_ConvertUTF16toUTF8 narrow(*this);
const char *fmt;
switch (aRadix) {
case 10:
fmt = "%lli";
break;
case 16:
fmt = "%llx";
break;
default:
NS_ERROR("Unrecognized radix!");
*aErrorCode = NS_ERROR_INVALID_ARG;
return 0;
}
int64_t result = 0;
if (PR_sscanf(narrow.get(), fmt, &result) == 1)
*aErrorCode = NS_OK;
else
*aErrorCode = NS_ERROR_FAILURE;
return result;
}
#endif // XPCOM_GLUE_AVOID_NSPR
// nsACString
@@ -921,6 +951,34 @@ nsACString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
return result;
}
int64_t
nsACString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
{
const char *fmt;
switch (aRadix) {
case 10:
fmt = "%lli";
break;
case 16:
fmt = "%llx";
break;
default:
NS_ERROR("Unrecognized radix!");
*aErrorCode = NS_ERROR_INVALID_ARG;
return 0;
}
int64_t result = 0;
if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
*aErrorCode = NS_OK;
else
*aErrorCode = NS_ERROR_FAILURE;
return result;
}
#endif // XPCOM_GLUE_AVOID_NSPR
// Substrings

View File

@@ -360,6 +360,14 @@ public:
*/
NS_HIDDEN_(int32_t) ToInteger(nsresult* aErrorCode,
uint32_t aRadix = 10) const;
/**
* Convert this string to a 64-bit integer.
*
* @param aErrorCode pointer to contain result code.
* @param aRadix must be 10 or 16
*/
NS_HIDDEN_(int64_t) ToInteger64(nsresult* aErrorCode,
uint32_t aRadix = 10) const;
#endif // XPCOM_GLUE_AVOID_NSPR
protected:
@@ -711,6 +719,14 @@ public:
*/
NS_HIDDEN_(int32_t) ToInteger(nsresult* aErrorCode,
uint32_t aRadix = 10) const;
/**
* Convert this string to a 64-bit integer.
*
* @param aErrorCode pointer to contain result code.
* @param aRadix must be 10 or 16
*/
NS_HIDDEN_(int64_t) ToInteger64(nsresult* aErrorCode,
uint32_t aRadix = 10) const;
#endif // XPCOM_GLUE_AVOID_NSPR
protected:

View File

@@ -251,6 +251,15 @@ class nsTString_CharT : public nsTSubstring_CharT
*/
int32_t ToInteger( nsresult* aErrorCode, uint32_t aRadix=kRadix10 ) const;
/**
* Perform string to 64-bit int conversion.
* @param aErrorCode will contain error if one occurs
* @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
* @return 64-bit int rep of string value, and possible (out) error code
*/
int64_t ToInteger64( nsresult* aErrorCode, uint32_t aRadix=kRadix10 ) const;
/**
* |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
* any _other_ way than they are now. Consider these alternatives

View File

@@ -233,6 +233,133 @@ nsTString_CharT::ToInteger( nsresult* aErrorCode, uint32_t aRadix ) const
/**
* nsTString::ToInteger64
*/
int64_t
nsTString_CharT::ToInteger64( nsresult* aErrorCode, uint32_t aRadix ) const
{
CharT* cp=mData;
int32_t theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
int64_t result=0;
bool negate=false;
CharT theChar=0;
//initial value, override if we find an integer
*aErrorCode=NS_ERROR_ILLEGAL_VALUE;
if(cp) {
//begin by skipping over leading chars that shouldn't be part of the number...
CharT* endcp=cp+mLength;
bool done=false;
while((cp<endcp) && (!done)){
switch(*cp++) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
theRadix=16;
done=true;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
done=true;
break;
case '-':
negate=true; //fall through...
break;
case 'X': case 'x':
theRadix=16;
break;
default:
break;
} //switch
}
if (done) {
//integer found
*aErrorCode = NS_OK;
if (aRadix!=kAutoDetect) theRadix = aRadix; // override
//now iterate the numeric chars and build our result
CharT* first=--cp; //in case we have to back up.
bool haveValue = false;
while(cp<endcp){
int64_t oldresult = result;
theChar=*cp++;
if(('0'<=theChar) && (theChar<='9')){
result = (theRadix * result) + (theChar-'0');
haveValue = true;
}
else if((theChar>='A') && (theChar<='F')) {
if(10==theRadix) {
if(kAutoDetect==aRadix){
theRadix=16;
cp=first; //backup
result=0;
haveValue = false;
}
else {
*aErrorCode=NS_ERROR_ILLEGAL_VALUE;
result=0;
break;
}
}
else {
result = (theRadix * result) + ((theChar-'A')+10);
haveValue = true;
}
}
else if((theChar>='a') && (theChar<='f')) {
if(10==theRadix) {
if(kAutoDetect==aRadix){
theRadix=16;
cp=first; //backup
result=0;
haveValue = false;
}
else {
*aErrorCode=NS_ERROR_ILLEGAL_VALUE;
result=0;
break;
}
}
else {
result = (theRadix * result) + ((theChar-'a')+10);
haveValue = true;
}
}
else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) {
continue;
}
else if((('#'==theChar) || ('+'==theChar)) && !haveValue) {
continue;
}
else {
//we've encountered a char that's not a legal number or sign
break;
}
if (result < oldresult) {
// overflow!
*aErrorCode = NS_ERROR_ILLEGAL_VALUE;
result = 0;
break;
}
} //while
if(negate)
result=-result;
} //if
}
return result;
}
/**
* nsTString::Mid
*/