StringUtil.parseNumber

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5005 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Tom Conkling
2008-04-19 01:06:41 +00:00
parent 3b863e30fa
commit ab02c0ee30
+89 -1
View File
@@ -22,7 +22,6 @@
package com.threerings.util {
import flash.utils.ByteArray;
import flash.utils.describeType; // function import
public class StringUtil
@@ -126,6 +125,48 @@ public class StringUtil
return uint(result);
}
/**
* Parse a Number from a String, throwing an ArgumentError if there are any
* invalid characters.
*
* 1.5, 2e-3, -Infinity, Infinity, and NaN are all valid Strings.
*
* @param str the String to parse.
*/
public static function parseNumber (str :String) :Number
{
var originalString :String = str;
if (str == null) {
throw new ArgumentError("Cannot parseNumber(null)");
}
// deal with a few special cases
if (str == "Infinity") {
return Infinity;
} else if (str == "-Infinity") {
return -Infinity;
} else if (str == "NaN") {
return NaN;
}
// validate all characters before the "e"
str = validateDecimal(str, true, true);
// validate all characters after the "e"
if (null != str && str.charAt(0) == "e") {
str = str.substring(1);
validateDecimal(str, false, false);
}
if (null == str) {
throw new ArgumentError("Could not convert '" + originalString + "' to Number");
}
// let Flash do the actual conversion
return parseFloat(originalString);
}
/**
* Append 0 or more copies of the padChar String to the input String
* until it is at least the specified length.
@@ -388,6 +429,49 @@ public class StringUtil
return data;
}
/**
* Internal helper function for parseNumber.
*/
protected static function validateDecimal (str :String, allowDot :Boolean, allowTrailingE :Boolean) :String
{
// skip the leading minus
if (str.charAt(0) == "-") {
str = str.substring(1);
}
// validate that the characters in the string are all integers,
// with at most one '.'
var seenDot :Boolean;
var seenDigit :Boolean;
while (str.length > 0) {
var char :String = str.charAt(0);
if (char == ".") {
if (!allowDot || seenDot) {
return null;
}
seenDot = true;
} else if (char == "e") {
if (!allowTrailingE) {
return null;
}
break;
} else if (DECIMAL.indexOf(char) >= 0) {
seenDigit = true;
} else {
return null;
}
str = str.substring(1);
}
// ensure we've seen at least one digit so far
if (!seenDigit) {
return null;
}
return str;
}
/**
* Internal helper function for parseInteger and parseUnsignedInteger.
*/
@@ -446,6 +530,10 @@ public class StringUtil
protected static const HEX :Array = [ "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
/** Decimal digits. */
protected static const DECIMAL :Array = [ "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9" ];
/** A regular expression that finds URLs. */
protected static const URL_REGEXP :RegExp =
new RegExp("(http|https|ftp)://\\S+", "i");