diff --git a/agrona/src/main/java/org/agrona/AsciiEncoding.java b/agrona/src/main/java/org/agrona/AsciiEncoding.java
index dee3fa09c..418ecb2ef 100644
--- a/agrona/src/main/java/org/agrona/AsciiEncoding.java
+++ b/agrona/src/main/java/org/agrona/AsciiEncoding.java
@@ -127,21 +127,20 @@ public static int getDigit(final int index, final char value)
* @param index at which the number begins.
* @param length of the encoded number in characters.
* @throws AsciiNumberFormatException if cs
is not an int value
- * @throws IndexOutOfBoundsException if cs
is empty
+ * @throws IndexOutOfBoundsException if parsing results in access outside string boundaries, or length is negative
* @return the parsed value.
*/
public static int parseIntAscii(final CharSequence cs, final int index, final int length)
{
- final int endExclusive = index + length;
- final int first = cs.charAt(index);
- int i = index;
- final boolean hasSign = first == MINUS_SIGN;
-
- if (hasSign && length > 1)
+ if (length <= 1)
{
- i++;
+ return parseSingleDigit(cs, index, length);
}
+ final boolean hasSign = cs.charAt(index) == MINUS_SIGN;
+ final int endExclusive = index + length;
+ int i = hasSign ? index + 1 : index;
+
if (length >= 10)
{
checkIntLimits(cs, index, length, i, hasSign);
@@ -168,21 +167,20 @@ public static int parseIntAscii(final CharSequence cs, final int index, final in
* @param index at which the number begins.
* @param length of the encoded number in characters.
* @throws AsciiNumberFormatException if cs
is not a long value
- * @throws IndexOutOfBoundsException if cs
is empty
+ * @throws IndexOutOfBoundsException if parsing results in access outside string boundaries, or length is negative
* @return the parsed value.
*/
public static long parseLongAscii(final CharSequence cs, final int index, final int length)
{
- final int endExclusive = index + length;
- final int first = cs.charAt(index);
- int i = index;
- final boolean hasSign = first == MINUS_SIGN;
-
- if (hasSign && length > 1)
+ if (length <= 1)
{
- i++;
+ return parseSingleDigit(cs, index, length);
}
+ final boolean hasSign = cs.charAt(index) == MINUS_SIGN;
+ final int endExclusive = index + length;
+ int i = hasSign ? index + 1 : index;
+
if (length >= 19)
{
checkLongLimits(cs, index, length, i, hasSign);
@@ -202,6 +200,22 @@ public static long parseLongAscii(final CharSequence cs, final int index, final
return tally;
}
+ private static int parseSingleDigit(final CharSequence cs, final int index, final int length)
+ {
+ if (length == 1)
+ {
+ return AsciiEncoding.getDigit(index, cs.charAt(index));
+ }
+ else if (length == 0)
+ {
+ throw new AsciiNumberFormatException("'' is not a valid int @ " + index);
+ }
+ else
+ {
+ throw new IndexOutOfBoundsException("length=" + length);
+ }
+ }
+
private static void checkIntLimits(
final CharSequence cs, final int index, final int length, final int i, final boolean hasSign)
{
diff --git a/agrona/src/test/java/org/agrona/AsciiEncodingTest.java b/agrona/src/test/java/org/agrona/AsciiEncodingTest.java
index 4a44d62af..ddb91ee5d 100644
--- a/agrona/src/test/java/org/agrona/AsciiEncodingTest.java
+++ b/agrona/src/test/java/org/agrona/AsciiEncodingTest.java
@@ -151,12 +151,12 @@ public void shouldThrowExceptionWhenParsingLongContainingLonePlusSign()
@Test
public void shouldThrowExceptionWhenParsingEmptyInteger()
{
- assertThrows(IndexOutOfBoundsException.class, () -> parseIntAscii("", 0, 0));
+ assertThrows(AsciiNumberFormatException.class, () -> parseIntAscii("", 0, 0));
}
@Test
public void shouldThrowExceptionWhenParsingEmptyLong()
{
- assertThrows(IndexOutOfBoundsException.class, () -> parseLongAscii("", 0, 0));
+ assertThrows(AsciiNumberFormatException.class, () -> parseLongAscii("", 0, 0));
}
}