Merge remote-tracking branch 'origin/GP-4955_ryanmkurtz_elf--SQUASHED'

(Closes #6912)
This commit is contained in:
Ryan Kurtz 2024-10-01 13:44:16 -04:00
commit 3cc122cffa
8 changed files with 339 additions and 140 deletions

View File

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -89,11 +89,12 @@ public class FindReferencesToFieldByNameOrOffsetAction extends AbstractFindRefer
return null; // cancelled return null; // cancelled
} }
Long longChoice = parseInt(userChoice); try {
if (longChoice != null) { return new FieldMatcher(dt, NumericUtilities.parseInt(userChoice));
return new FieldMatcher(dt, longChoice.intValue()); }
catch (NumberFormatException e) {
return new FieldMatcher(dt, userChoice);
} }
return new FieldMatcher(dt, userChoice);
} }
private String[] getCompositeFieldNames(Composite composite) { private String[] getCompositeFieldNames(Composite composite) {
@ -112,8 +113,4 @@ public class FindReferencesToFieldByNameOrOffsetAction extends AbstractFindRefer
return names.toArray(String[]::new); return names.toArray(String[]::new);
} }
private Long parseInt(String s) {
return NumericUtilities.parseNumber(s, null);
}
} }

View File

@ -21,6 +21,8 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import org.apache.commons.lang3.StringUtils;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
@ -246,12 +248,12 @@ public class AskDialog<T> extends DialogComponentProvider {
protected Integer getValueAsInt() { protected Integer getValueAsInt() {
String text = getValueAsString(); String text = getValueAsString();
return text != null ? NumericUtilities.parseInt(text) : null; return !StringUtils.isBlank(text) ? NumericUtilities.parseInt(text) : null;
} }
protected Long getValueAsLong() { protected Long getValueAsLong() {
String text = getValueAsString(); String text = getValueAsString();
return text != null ? NumericUtilities.parseLong(text) : null; return !StringUtils.isBlank(text) ? NumericUtilities.parseLong(text) : null;
} }
protected Double getValueAsDouble() { protected Double getValueAsDouble() {

View File

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -220,9 +220,9 @@ public class ElfLoaderOptionsFactory {
if (!String.class.isAssignableFrom(option.getValueClass())) { if (!String.class.isAssignableFrom(option.getValueClass())) {
return "Invalid type for option: " + name + " - " + option.getValueClass(); return "Invalid type for option: " + name + " - " + option.getValueClass();
} }
String value = (String) option.getValue(); String value = ((String) option.getValue());
try { try {
space.getAddress(Long.parseUnsignedLong(value, 16), true);// verify valid address space.getAddress(NumericUtilities.parseHexLong(value), true);// verify valid address
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
return "Invalid " + name + " - expecting hexidecimal address offset"; return "Invalid " + name + " - expecting hexidecimal address offset";

View File

@ -18,6 +18,7 @@ package ghidra.app.util.bin.format.pdb;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import ghidra.app.util.SymbolPathParser; import ghidra.app.util.SymbolPathParser;
import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataType;
@ -134,14 +135,15 @@ public class DefaultPdbMember extends PdbMember {
try { try {
int colonIndex = bitSizeOffsetStr.indexOf(':'); int colonIndex = bitSizeOffsetStr.indexOf(':');
if (colonIndex > 0) { if (colonIndex > 0) {
bitFieldOffset = (int) NumericUtilities.parseNumber( bitFieldOffset =
bitSizeOffsetStr.substring(colonIndex + 1)); NumericUtilities.parseInt(bitSizeOffsetStr.substring(colonIndex + 1));
bitSizeOffsetStr = bitSizeOffsetStr.substring(0, colonIndex); bitSizeOffsetStr = bitSizeOffsetStr.substring(0, colonIndex);
} }
else { else {
dataTypeParser.setMissingBitOffsetError(); dataTypeParser.setMissingBitOffsetError();
} }
bitFieldSize = (int) NumericUtilities.parseNumber(bitSizeOffsetStr); NumberUtils.toInt(bitSizeOffsetStr, 0);
bitFieldSize = NumericUtilities.parseInt(bitSizeOffsetStr);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
Msg.error(this, "Invalid PDB bitfield specification: " + name); Msg.error(this, "Invalid PDB bitfield specification: " + name);

View File

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -151,8 +151,7 @@ public class NumberRangeInputDialog extends DialogComponentProvider {
String trimmed = rangeText.trim(); String trimmed = rangeText.trim();
if (!trimmed.contains(RANGE_DELIMITER)) { if (!trimmed.contains(RANGE_DELIMITER)) {
try { try {
long parsedLong = NumericUtilities.parseLong(trimmed); int intValue = NumericUtilities.parseInt(trimmed);
int intValue = (int) parsedLong;
rangeList.addRange(intValue, intValue); rangeList.addRange(intValue, intValue);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
@ -165,12 +164,8 @@ public class NumberRangeInputDialog extends DialogComponentProvider {
// this must be a range // this must be a range
String[] startAndEnd = trimmed.split(RANGE_DELIMITER); String[] startAndEnd = trimmed.split(RANGE_DELIMITER);
try { try {
long parsedLong = NumericUtilities.parseLong(startAndEnd[0]); int startInt = NumericUtilities.parseInt(startAndEnd[0]);
int startInt = (int) parsedLong; int endInt = NumericUtilities.parseInt(startAndEnd[1]);
parsedLong = NumericUtilities.parseLong(startAndEnd[1]);
int endInt = (int) parsedLong;
rangeList.addRange(startInt, endInt); rangeList.addRange(startInt, endInt);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {

View File

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -172,8 +172,9 @@ public class GValidatedTextField extends JTextField {
@Override @Override
public void validate(String oldText, String newText) throws ValidationFailedException { public void validate(String oldText, String newText) throws ValidationFailedException {
try { try {
long oldLong = NumericUtilities.parseLong(oldText);
long newLong = NumericUtilities.parseLong(newText); long oldLong = sanitizeInput(oldText);
long newLong = sanitizeInput(newText);
validateLong(oldLong, newLong); validateLong(oldLong, newLong);
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
@ -181,7 +182,52 @@ public class GValidatedTextField extends JTextField {
} }
} }
@SuppressWarnings("unused")
public void validateLong(long oldLong, long newLong) throws ValidationFailedException { public void validateLong(long oldLong, long newLong) throws ValidationFailedException {
// do nothing
}
/**
* Similar to {@link NumericUtilities#parseLong(String)}, but we return 0 if the string
* is null, empty, or looks like a partially entered value (such as "-", "0x", etc)
*
* @param s the string to parse
* @return the parsed {@code long} value, or 0 if the string is null, empty, or looks
* like a partially entered value (such as "-", "0x", etc)
* @throws NumberFormatException if the string does not represent a valid {@code long}
* value
*/
private long sanitizeInput(String s) throws NumberFormatException {
// Trim the string and return 0 if it's empty. This could be a partial input.
s = (s == null ? "" : s.trim());
if (s.isEmpty()) {
return 0;
}
// Chop off the optional sign character of the string, we'll add it back later
long sign = 1;
if (s.startsWith("-")) {
sign = -1;
s = s.substring(1);
}
else if (s.startsWith("+")) {
s = s.substring(1);
}
// Chop off the optional hex prefix...we'll decide to do hex later
boolean hexPrefix = s.startsWith("0x") || s.startsWith("0X");
if (hexPrefix) {
s = s.substring(2);
}
// Since we might have chopped off prefixes, check again and return 0 if it's empty.
// This could be a partial input.
if (s.isEmpty()) {
return 0;
}
return sign *
(hexPrefix ? NumericUtilities.parseHexLong(s) : NumericUtilities.parseLong(s));
} }
} }
} }

View File

@ -18,6 +18,7 @@ package ghidra.util;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -29,6 +30,7 @@ import util.CollectionUtils;
public final class NumericUtilities { public final class NumericUtilities {
public static final BigInteger MAX_UNSIGNED_LONG = new BigInteger("ffffffffffffffff", 16); public static final BigInteger MAX_UNSIGNED_LONG = new BigInteger("ffffffffffffffff", 16);
public static final BigInteger MAX_SIGNED_LONG = new BigInteger("7fffffffffffffff", 16); public static final BigInteger MAX_SIGNED_LONG = new BigInteger("7fffffffffffffff", 16);
public static final BigInteger MAX_UNSIGNED_INT = new BigInteger("ffffffff", 16);
public static final long MAX_UNSIGNED_INT32_AS_LONG = 0xffffffffL; public static final long MAX_UNSIGNED_INT32_AS_LONG = 0xffffffffL;
private final static String HEX_PREFIX_X = "0X"; private final static String HEX_PREFIX_X = "0X";
@ -64,7 +66,9 @@ public final class NumericUtilities {
* *
* @param numStr the number string * @param numStr the number string
* @return the long value or 0 * @return the long value or 0
* @deprecated use {@link #parseLong(String)} instead
*/ */
@Deprecated(since = "11.3", forRemoval = true)
public static long parseNumber(String numStr) { public static long parseNumber(String numStr) {
return parseNumber(numStr, Long.valueOf(0)); return parseNumber(numStr, Long.valueOf(0));
} }
@ -75,7 +79,9 @@ public final class NumericUtilities {
* @param s the string to parse * @param s the string to parse
* @param defaultValue the default value to use if the string cannot be parsed * @param defaultValue the default value to use if the string cannot be parsed
* @return the long value * @return the long value
* @deprecated use {@link #parseLong(String, long)} instead
*/ */
@Deprecated(since = "11.3", forRemoval = true)
public static Long parseNumber(String s, Long defaultValue) { public static Long parseNumber(String s, Long defaultValue) {
s = (s == null ? "" : s.trim()); s = (s == null ? "" : s.trim());
if (s.length() == 0) { if (s.length() == 0) {
@ -104,90 +110,149 @@ public final class NumericUtilities {
* the top bit set to be implicitly parsed as negative values. * the top bit set to be implicitly parsed as negative values.
* *
* @param s the string to parse * @param s the string to parse
* @return the {@code int} value, or 0 if the string to parse is null or blank * @return the parsed {@code int} value
* @throws NumberFormatException if the string does not represent a valid {@code int} value * @throws NumberFormatException if the string does not represent a valid {@code int} value
*/ */
public static int parseInt(String s) { public static int parseInt(String s) throws NumberFormatException {
String origStr = s; return parseHelper(s, false, BigInteger::intValue, MAX_UNSIGNED_INT);
int sign = 1;
s = (s == null ? "" : s.trim());
if (s.length() == 0) {
return 0;
}
if (s.startsWith("-")) {
sign = -1;
s = s.substring(1);
}
int radix = 10;
if (s.startsWith(HEX_PREFIX_x) || s.startsWith(HEX_PREFIX_X)) {
if (s.length() > 10) {
throw new NumberFormatException(s + " has too many digits.");
}
s = s.substring(2);
radix = 16;
}
if (s.length() == 0) {
return 0;
}
try {
BigInteger bi = new BigInteger(s, radix);
return bi.intValue() * sign;
}
catch (NumberFormatException e) {
// This is a little hacky, but the message should be complete and report about the
// original string
NumberFormatException e2 =
new NumberFormatException("Cannot parse int from " + origStr);
e2.setStackTrace(e.getStackTrace());
throw e2;
}
catch (ArithmeticException e) {
throw new NumberFormatException(origStr + " is too big.");
}
} }
/** /**
* Parses the given decimal/hex string as a {@code long} value. This method allows values with * Parses the given decimal/hex string as an {@code int} value. This method allows values with
* the top bit set to be implicitly parsed as negative values. * the top bit set to be implicitly parsed as negative values.
* *
* @param s the string to parse * @param s the string to parse
* @return the {@code long} value, or 0 if the string to parse is null or blank * @param defaultValue the default value to return if the string does not represent a valid
* {@code int} value
* @return the parsed {@code int} value or the {@code defaultValue} if the string does not
* represent a valid {@code int} value
*/
public static int parseInt(String s, int defaultValue) {
try {
return parseInt(s);
}
catch (NumberFormatException e) {
return defaultValue;
}
}
/**
* Parses the given decimal/hex string as an {@code long} value. This method allows values with
* the top bit set to be implicitly parsed as negative values.
*
* @param s the string to parse
* @return the parsed {@code long} value
* @throws NumberFormatException if the string does not represent a valid {@code long} value * @throws NumberFormatException if the string does not represent a valid {@code long} value
*/ */
public static long parseLong(String s) { public static long parseLong(String s) throws NumberFormatException {
String origStr = s; return parseHelper(s, false, BigInteger::longValue, MAX_UNSIGNED_LONG);
long sign = 1; }
s = (s == null ? "" : s.trim()); /**
if (s.length() == 0) { * Parses the given decimal/hex string as an {@code long} value. This method allows values with
return 0; * the top bit set to be implicitly parsed as negative values.
*
* @param s the string to parse
* @param defaultValue the default value to return if the string does not represent a valid
* {@code long} value
* @return the parsed {@code long} value or the {@code defaultValue} if the string does not
* represent a valid {@code long} value
*/
public static long parseLong(String s, long defaultValue) {
try {
return parseLong(s);
} }
if (s.startsWith("-")) { catch (NumberFormatException e) {
sign = -1; return defaultValue;
}
}
/**
* Parses the given hex string as a {@code long} value.
* <p>
* Note: The string is treated as hex regardless of whether or not it contains the {@code 0x}
* prefix.
*
* @param s the string to parse
* @return the parsed {@code long} value
* @throws NumberFormatException if the string does not represent a valid value
*/
public static long parseHexLong(String s) throws NumberFormatException {
return parseHelper(s, true, BigInteger::longValue, MAX_UNSIGNED_LONG);
}
/**
* Parses the given hex string as a {@link BigInteger} value.
* <p>
* Note: The string is treated as hex regardless of whether or not it contains the {@code 0x}
* prefix.
*
* @param s the string to parse
* @return the parsed {@link BigInteger} value
* @throws NumberFormatException if the string does not represent a valid value
* @deprecated use {@link #parseHexLong(String)} instead
*/
@Deprecated(since = "11.3", forRemoval = true)
public static BigInteger parseHexBigInteger(String s) throws NumberFormatException {
return parseHelper(s, true, Function.identity(), MAX_UNSIGNED_LONG);
}
/**
* Parses the given decimal/hex string as a custom type. This method allows values with the top
* bit set to be implicitly parsed as negative values.
*
* @param s the string to parse
* @param forceHex true if the string to parse should be treated as hex, even if it doesn't
* start with {@code 0x}; otherwise, false;
* @param func a {@link Function} used to convert the parsed {@link BigInteger} to a custom type
* @param max the maximum value that can be used to represent the type of value being parsed if
* it were treated as unsigned
* @param <T> The type of value being parsed
* @return the parsed value
* @throws NumberFormatException if the string does not represent a valid value
*/
private static <T> T parseHelper(String s, boolean forceHex, Function<BigInteger, T> func,
BigInteger max) throws NumberFormatException {
String origStr = s;
// Trim the string, and throw exception if it's null/empty
s = (s == null ? "" : s.trim());
if (s.isEmpty()) {
throw new NumberFormatException("String to parse is empty");
}
// Chop off the optional sign character of the string, we'll add it back later
String sign = "";
if (s.startsWith("-") || s.startsWith("+")) {
sign = s.substring(0, 1);
s = s.substring(1); s = s.substring(1);
} }
int radix = 10;
if (s.startsWith(HEX_PREFIX_x) || s.startsWith(HEX_PREFIX_X)) { // Process the radix
if (s.length() > 18) { boolean hexPrefix = s.startsWith(HEX_PREFIX_x) || s.startsWith(HEX_PREFIX_X);
throw new NumberFormatException(s + " has too many digits."); int radix = forceHex || hexPrefix ? 16 : 10;
} if (hexPrefix) {
s = s.substring(2); s = s.substring(2);
radix = 16;
} }
if (s.length() == 0) {
return 0; // Make sure next character is not + or - (protects against things like "0x-ffff")
if (!s.isEmpty() && (s.charAt(0) == '-' || s.charAt(0) == '+')) {
throw new NumberFormatException("Cannot parse " + origStr);
} }
// Try to convert the string to the desired type
try { try {
BigInteger bi = new BigInteger(s, radix);
return bi.longValue() * sign; // Check size
if (new BigInteger(s, radix).compareTo(max) > 0) {
throw new NumberFormatException(s + " exceeds maximum data type size.");
}
return func.apply(new BigInteger(sign + s, radix));
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// A little hacky, but the message should be complete and report the original string // A little hacky, but the message should be complete and report the original string
NumberFormatException e2 = NumberFormatException e2 = new NumberFormatException("Cannot parse " + origStr);
new NumberFormatException("Cannot parse long from " + origStr);
e2.setStackTrace(e.getStackTrace()); e2.setStackTrace(e.getStackTrace());
throw e2; throw e2;
} }
@ -196,47 +261,6 @@ public final class NumericUtilities {
} }
} }
/**
* Parses the given string as a hex long value, detecting whether or not it begins with a hex
* prefix, and if not, parses as a long int value.
* @param s the string to parse
* @return the long value
* @throws NumberFormatException if the string is blank
*/
public static long parseHexLong(String s) {
return parseHexBigInteger(s).longValue();
}
/**
* Parses the given hex string as a BigIntge value, detecting whether or not it begins with a
* hex prefix, and if not, parses as a long int value.
* @param s the string to parse
* @return the long value
* @throws NumberFormatException if the string is blank
*/
public static BigInteger parseHexBigInteger(String s) {
s = (s == null ? "" : s.trim());
if (s.length() == 0) {
throw new NumberFormatException(s + " no digits.");
}
boolean negative = false;
if (s.startsWith("-")) {
negative = true;
s = s.substring(1);
}
if (s.startsWith(HEX_PREFIX_x) || s.startsWith(HEX_PREFIX_X)) {
s = s.substring(2);
}
if (negative) {
s = "-" + s;
}
return new BigInteger(s, 16);
}
private static BigInteger decodeMagnitude(int p, String s) { private static BigInteger decodeMagnitude(int p, String s) {
// Special case, so it doesn't get chewed by octal parser // Special case, so it doesn't get chewed by octal parser
if ("0".equals(s)) { if ("0".equals(s)) {
@ -314,7 +338,7 @@ public final class NumericUtilities {
* @return the string * @return the string
*/ */
public final static String toSignedHexString(long value) { public final static String toSignedHexString(long value) {
StringBuffer buf = new StringBuffer(); StringBuilder buf = new StringBuilder();
if (value < 0) { if (value < 0) {
buf.append("-"); buf.append("-");
} }

View File

@ -15,8 +15,7 @@
*/ */
package ghidra.util; package ghidra.util;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.fail;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;
@ -362,60 +361,194 @@ public class NumericUtilitiesTest {
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("+"); NumericUtilities.decodeBigInteger("+");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("-"); NumericUtilities.decodeBigInteger("-");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("0x"); NumericUtilities.decodeBigInteger("0x");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("0b"); NumericUtilities.decodeBigInteger("0b");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("a01"); NumericUtilities.decodeBigInteger("a01");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("081"); NumericUtilities.decodeBigInteger("081");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("0x9g"); NumericUtilities.decodeBigInteger("0x9g");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger(" 10"); NumericUtilities.decodeBigInteger(" 10");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
} }
try { try {
NumericUtilities.decodeBigInteger("10 "); NumericUtilities.decodeBigInteger("10 ");
fail(); fail();
} }
catch (NumberFormatException e) { catch (NumberFormatException e) {
// do nothing
}
}
@Test
public void testParse() {
// parseInt()
assertEquals(-1, NumericUtilities.parseInt("0xffffffff"));
assertEquals(-1, NumericUtilities.parseInt("+0xffffffff"));
assertEquals(1, NumericUtilities.parseInt("-0xffffffff"));
assertEquals(0, NumericUtilities.parseInt("0x100000000", 0));
assertEquals(-1, NumericUtilities.parseInt("4294967295")); // 0xffffffff
try {
assertEquals(0, NumericUtilities.parseInt("0x100000000"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseInt("4294967296")); // 0x100000000
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseInt("0x-5"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseInt(null));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseInt(" "));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
// parseLong()
assertEquals(-1, NumericUtilities.parseLong("0xffffffffffffffff"));
assertEquals(-1, NumericUtilities.parseLong("+0xffffffffffffffff"));
assertEquals(1, NumericUtilities.parseLong("-0xffffffffffffffff"));
assertEquals(0, NumericUtilities.parseLong("0x10000000000000000", 0));
assertEquals(-1, NumericUtilities.parseLong("18446744073709551615")); // 0xffffffffffffffff
try {
assertEquals(0, NumericUtilities.parseLong("0x10000000000000000"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseLong("18446744073709551616")); // 0x10000000000000000
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseInt("0x-5"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseLong(null));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseLong(" "));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
// parseHexLong()
assertEquals(-1, NumericUtilities.parseHexLong("ffffffffffffffff"));
assertEquals(-1, NumericUtilities.parseHexLong("0xffffffffffffffff"));
assertEquals(-1, NumericUtilities.parseHexLong("+ffffffffffffffff"));
assertEquals(-1, NumericUtilities.parseHexLong("+0xffffffffffffffff"));
assertEquals(1, NumericUtilities.parseHexLong("-ffffffffffffffff"));
assertEquals(1, NumericUtilities.parseHexLong("-0xffffffffffffffff"));
try {
assertEquals(0, NumericUtilities.parseHexLong("0x10000000000000000"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseHexLong("0x-5"));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseHexLong(null));
fail();
}
catch (NumberFormatException e) {
// do nothing
}
try {
assertEquals(0, NumericUtilities.parseHexLong(" "));
fail();
}
catch (NumberFormatException e) {
// do nothing
} }
} }
} }