Author: mturk Date: Mon Jun 29 07:56:10 2009 New Revision: 789248 URL: http://svn.apache.org/viewvc?rev=789248&view=rev Log: Add Ascii atoi/atol methods
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestStrings.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java?rev=789248&r1=789247&r2=789248&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/util/Ascii.java Mon Jun 29 07:56:10 2009 @@ -259,5 +259,183 @@ arr[i] = (byte)ccs_cupper[(int)arr[i] & 0xff]; } + public static int atoi(byte[] arr, int srcPos, int len, int base) + { + int acc; + int val; + int neg; + int any; + int i = srcPos; + int c; + + // Skip leading spaces + if (len < 1) + return 0; + do { + c = arr[i++]; + } while (isspace(c) && i < len); + + if (c == '-') { + neg = 1; + if (i < len) + c = arr[i++]; + else { + // EINVAL + return 0; + } + } else { + neg = 0; + if (c == '+') { + if (i < len) + c = arr[i++]; + else { + // EINVAL + return 0; + } + } + } + if ((base == 0 || base == 16) && + c == '0' && i < len && (arr[i] == 'x' || arr[i] == 'X')) { + if ((i + 1) < len) { + c = arr[i + 1]; + i += 2; + base = 16; + } + else { + // EINVAL + return 0; + } + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) { + // EINVAL + return acc; + } + val = 0; + while (i <= len) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + val *= base; + if ((any < 0) || /* already noted an over/under flow - short circuit */ + (neg != 0 && (val > acc || (val -= c) > acc)) || /* underflow */ + (neg == 0 && (val < acc || (val += c) < acc))) { /* overflow */ + any = -1; /* once noted, over/underflows never go away */ + break; + } else { + acc = val; + any = 1; + } + if (i < len) + c = arr[i]; + i++; + } + + if (any < 0) { + acc = neg == 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } else if (any == 0) { + // EINVAL + } + return acc; + } + + public static long atol(byte[] arr, int srcPos, int len, int base) + { + long acc; + long val; + int neg; + int any; + int i = srcPos; + int c; + + // Skip leading spaces + if (len < 1) + return 0; + do { + c = arr[i++]; + } while (isspace(c) && i < len); + + if (c == '-') { + neg = 1; + if (i < len) + c = arr[i++]; + else { + // EINVAL + return 0; + } + } else { + neg = 0; + if (c == '+') { + if (i < len) + c = arr[i++]; + else { + // EINVAL + return 0; + } + } + } + if ((base == 0 || base == 16) && + c == '0' && i < len && (arr[i] == 'x' || arr[i] == 'X')) { + if ((i + 1) < len) { + c = arr[i + 1]; + i += 2; + base = 16; + } + else { + // EINVAL + return 0; + } + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) { + // EINVAL + return acc; + } + val = 0; + while (i <= len) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + val *= base; + if ((any < 0) || /* already noted an over/under flow - short circuit */ + (neg != 0 && (val > acc || (val -= c) > acc)) || /* underflow */ + (neg == 0 && (val < acc || (val += c) < acc))) { /* overflow */ + any = -1; /* once noted, over/underflows never go away */ + break; + } else { + acc = val; + any = 1; + } + if (i < len) + c = arr[i]; + i++; + } + + if (any < 0) { + acc = neg == 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } else if (any == 0) { + // EINVAL + } + return acc; + } + } Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestStrings.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestStrings.java?rev=789248&r1=789247&r2=789248&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestStrings.java (original) +++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestStrings.java Mon Jun 29 07:56:10 2009 @@ -159,5 +159,105 @@ assertEquals("Lower Ascii", (byte)0xF4, b[0]); } + public void testAsciiAtoii() + throws Exception + { + byte [] b = " +1234".getBytes(); + int i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Atoi", 1234, i); + } + + public void testAsciiAtoix() + throws Exception + { + byte [] b = " +0x1234".getBytes(); + int i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Atol", 0x1234, i); + } + + public void testAsciiAtoiErr() + throws Exception + { + byte [] b = "".getBytes(); + int i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Empty", 0, i); + b = " ".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Space", 0, i); + b = " -".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Sign", 0, i); + b = " +".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("Plus", 0, i); + b = " 0x".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("EmptyHex", 0, i); + b = " 0xm".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("NonHex", 0, i); + } + + public void testAsciiAtoiOverflow() + throws Exception + { + byte [] b = "9223372036854775810".getBytes(); + int i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("MaxOverflow", Integer.MAX_VALUE, i); + b = "-9223372036854775810".getBytes(); + i = Ascii.atoi(b, 0, b.length, 0); + assertEquals("MinOverflow", Integer.MIN_VALUE, i); + } + + public void testAsciiAtoll() + throws Exception + { + byte [] b = " +1234".getBytes(); + long l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Atol", 1234L, l); + } + + public void testAsciiAtolx() + throws Exception + { + byte [] b = " +0x1234".getBytes(); + long l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Atol", 0x1234L, l); + } + + public void testAsciiAtolErr() + throws Exception + { + byte [] b = "".getBytes(); + long l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Empty", 0, l); + b = " ".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Space", 0, l); + b = " -".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Sign", 0, l); + b = " +".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("Plus", 0, l); + b = " 0x".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("EmptyHex", 0, l); + b = " 0xm".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("NonHex", 0, l); + } + + public void testAsciiAtolOverflow() + throws Exception + { + byte [] b = "9223372036854775810".getBytes(); + long l = Ascii.atol(b, 0, b.length, 0); + assertEquals("MaxOverflow", Long.MAX_VALUE, l); + b = "-9223372036854775810".getBytes(); + l = Ascii.atol(b, 0, b.length, 0); + assertEquals("MinOverflow", Long.MIN_VALUE, l); + } + }