All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.vesalainen.lang.Primitives Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Timo Vesalainen
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

package org.vesalainen.lang;

import org.vesalainen.util.CharSequences;

/**
 * Numbers class contains number parsing methods parsing numbers from CharSequence
 * rather that String. This is the main difference to parsing methods in Integer,
 * Float, ...
 * 
 * 

For most numbers, methods in this class return the same as methods in * java.lang. * * @see java.lang.Byte * @see java.lang.Short * @see java.lang.Integer * @see java.lang.Long * @see java.lang.Float * @see java.lang.Double * @author Timo Vesalainen */ public class Primitives { private static final int IntLimit = Integer.MAX_VALUE/10-10; private static final long LongLimit = Long.MAX_VALUE/10-10; private enum FloatState {Significand, Decimal, Exponent}; /** * Write value to byte array * @param value * @return * @see java.nio.ByteBuffer#putFloat(float) */ public static final byte[] writeFloat(float value) { byte[] array = new byte[4]; writeFloat(value, array); return array; } /** * Write value to byte array * @param value * @param array * @see java.nio.ByteBuffer#putFloat(float) */ public static final void writeFloat(float value, byte[] array) { writeFloat(value, array, 0); } /** * Write value to byte array * @param value * @param array * @param offset * @see java.nio.ByteBuffer#putFloat(float) */ public static final void writeFloat(float value, byte[] array, int offset) { writeInt(Float.floatToRawIntBits(value), array, offset); } /** * Read value from byte array * @param array * @return * @see java.nio.ByteBuffer#getFloat() */ public static final float readFloat(byte[] array) { return Float.intBitsToFloat(readInt(array, 0)); } /** * Read value from byte array * @param array * @param offset * @return * @see java.nio.ByteBuffer#getFloat() */ public static final float readFloat(byte[] array, int offset) { return Float.intBitsToFloat(readInt(array, offset)); } /** * Write value to byte array * @param value * @return * @see java.nio.ByteBuffer#putDouble(double) */ public static final byte[] writeDouble(double value) { byte[] array = new byte[8]; writeDouble(value, array); return array; } /** * Write value to byte array * @param value * @param array * @see java.nio.ByteBuffer#putDouble(double) */ public static final void writeDouble(double value, byte[] array) { writeDouble(value, array, 0); } /** * Write value to byte array * @param value * @param array * @param offset * @see java.nio.ByteBuffer#putDouble(double) */ public static final void writeDouble(double value, byte[] array, int offset) { writeLong(Double.doubleToRawLongBits(value), array, offset); } /** * Read value from byte array * @param array * @return * @see java.nio.ByteBuffer#getDouble() */ public static final double readDouble(byte[] array) { return readDouble(array, 0); } /** * Read value from byte array * @param array * @param offset * @see java.nio.ByteBuffer#getDouble() * @return */ public static final double readDouble(byte[] array, int offset) { return Double.longBitsToDouble(readLong(array, offset)); } /** * Write value to byte array * @param value * @return * @see java.nio.ByteBuffer#putLong(long) */ public static final byte[] writeLong(long value) { byte[] array = new byte[8]; writeLong(value, array); return array; } /** * Write value to byte array * @param value * @param array * @see java.nio.ByteBuffer#putLong(long) */ public static final void writeLong(long value, byte[] array) { writeLong(value, array, 0); } /** * Write value to byte array * @param value * @param array * @param offset * @see java.nio.ByteBuffer#putLong(long) */ public static final void writeLong(long value, byte[] array, int offset) { if (array.length < offset + 8) { throw new IllegalArgumentException("no room in array"); } array[offset] = (byte) (value >> 56); array[offset + 1] = (byte) ((value >> 48) & 0xff); array[offset + 2] = (byte) ((value >> 40) & 0xff); array[offset + 3] = (byte) ((value >> 32) & 0xff); array[offset + 4] = (byte) ((value >> 24) & 0xff); array[offset + 5] = (byte) ((value >> 16) & 0xff); array[offset + 6] = (byte) ((value >> 8) & 0xff); array[offset + 7] = (byte) (value & 0xff); } /** * Read value from byte array * @param array * @return * @see java.nio.ByteBuffer#getLong(long) */ public static final long readLong(byte[] array) { return readLong(array, 0); } /** * Read value from byte array * @param array * @param offset * @return * @see java.nio.ByteBuffer#getLong(long) */ public static final long readLong(byte[] array, int offset) { if (array.length < offset + 8) { throw new IllegalArgumentException("no room in array"); } return (((long)array[offset]<<56) & 0xff00000000000000L) + (((long)array[offset + 1]<<48) & 0xff000000000000L) + (((long)array[offset + 2]<<40) & 0xff0000000000L) + (((long)array[offset + 3]<<32) & 0xff00000000L) + (((long)array[offset + 4]<<24) & 0xff000000L) + (((long)array[offset + 5]<<16) & 0xff0000L) + (((long)array[offset + 6]<<8) & 0xff00L) + ((long)array[offset + 7] & 0xff ); } /** * Write value to byte array * @param value * @return * @see java.nio.ByteBuffer#putInt(int) */ public static final byte[] writeInt(int value) { byte[] array = new byte[4]; writeInt(value, array); return array; } /** * Write value to byte array * @param value * @param array * @see java.nio.ByteBuffer#putInt(int) */ public static final void writeInt(int value, byte[] array) { writeInt(value, array, 0); } /** * Write value to byte array * @param value * @param array * @param offset * @see java.nio.ByteBuffer#putInt(int) */ public static final void writeInt(int value, byte[] array, int offset) { if (array.length < offset + 4) { throw new IllegalArgumentException("no room in array"); } array[offset] = (byte) (value >> 24); array[offset + 1] = (byte) ((value >> 16) & 0xff); array[offset + 2] = (byte) ((value >> 8) & 0xff); array[offset + 3] = (byte) (value & 0xff); } /** * Read value from byte array * @param array * @return * @see java.nio.ByteBuffer#getInt(int) */ public static final int readInt(byte[] array) { return readInt(array, 0); } /** * Read value from byte array * @param array * @param offset * @return * @see java.nio.ByteBuffer#getInt(int) */ public static final int readInt(byte[] array, int offset) { if (array.length < offset + 4) { throw new IllegalArgumentException("no room in array"); } return ((array[offset]<<24) & 0xff000000) + ((array[offset + 1]<<16) & 0xff0000) + ((array[offset + 2]<<8) & 0xff00) + (array[offset + 3] & 0xff ); } /** * Write value to byte array * @param value * @return * @see java.nio.ByteBuffer#putShort(short) */ public static final byte[] writeShort(short value) { byte[] array = new byte[2]; writeShort(value, array); return array; } /** * Write value to byte array * @param value * @param array * @see java.nio.ByteBuffer#putShort(short) */ public static final void writeShort(short value, byte[] array) { writeShort(value, array, 0); } /** * Write value to byte array * @param value * @param array * @param offset * @see java.nio.ByteBuffer#putShort(short) */ public static final void writeShort(short value, byte[] array, int offset) { if (array.length < offset + 2) { throw new IllegalArgumentException("no room in array"); } array[offset] = (byte) (value >> 8); array[offset + 1] = (byte) (value & 0xff); } /** * Read value from byte array * @param array * @return * @see java.nio.ByteBuffer#getShort(short) */ public static final short readShort(byte[] array) { return readShort(array, 0); } /** * Read value from byte array * @param array * @param offset * @return * @see java.nio.ByteBuffer#getShort(short) */ public static final short readShort(byte[] array, int offset) { if (array.length < offset + 2) { throw new IllegalArgumentException("no room in array"); } return (short) (((array[offset]<<8) & 0xff00) + (array[offset + 1] & 0xff )); } /** * Return -1 for negative value, 1 for positive value and 0 for 0 * @param value * @return */ public static final int signum(int value) { return value < 0 ? -1 : value > 0 ? 1 : 0; } /** * Return -1 for negative value, 1 for positive value and 0 for 0 * @param value * @return */ public static final int signum(long value) { return value < 0 ? -1 : value > 0 ? 1 : 0; } /** * Returns char from input. * @param cs * @return * @throws IllegalArgumentException if input length is not 1. */ public static final char parseChar(CharSequence cs) { return parseChar(cs, 0, cs.length()); } /** * Returns char from input. * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws IllegalArgumentException if input length is not 1. */ public static final char parseChar(CharSequence cs, int beginIndex, int endIndex) { if (endIndex - beginIndex != 1) { throw new IllegalArgumentException("input length must be 1"); } return cs.charAt(beginIndex); } /** * Parses the char sequence argument as a boolean. The boolean returned represents * the value true if the char sequence argument is not null and is equal, ignoring * case, to the string "true". * @param cs * @return * @throws IllegalArgumentException if input length is not 4. * @see java.lang.Boolean#parseBoolean(java.lang.String) */ public static final boolean parseBoolean(CharSequence cs) { return parseBoolean(cs, 0, cs.length()); } /** * Parses the char sequence argument as a boolean. The boolean returned represents * the value true if the char sequence argument is not null and is equal, ignoring * case, to the string "true". * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws IllegalArgumentException if input length is not 4. * @see java.lang.Boolean#parseBoolean(java.lang.String) */ public static final boolean parseBoolean(CharSequence cs, int beginIndex, int endIndex) { return endIndex - beginIndex == 4 && Character.codePointCount(cs, beginIndex, endIndex) == 4 && Character.toUpperCase(Character.codePointAt(cs, beginIndex)) == 'T' && Character.toUpperCase(Character.codePointAt(cs, beginIndex+1)) == 'R' && Character.toUpperCase(Character.codePointAt(cs, beginIndex+2)) == 'U' && Character.toUpperCase(Character.codePointAt(cs, beginIndex+3)) == 'E'; } /** * Parses the char sequence argument as a boolean. The boolean returned represents * the value true if the char sequence argument is not null and it's digit value * is 1. * @param cs * @param radix Must be 2. * @return * @throws IllegalArgumentException radix != 2 or if code point count != 1 * or if input digit is not 0/1. * @see java.lang.Character#digit(int, int) * @see java.lang.Character#codePointCount(java.lang.CharSequence, int, int) */ public static final boolean parseBoolean(CharSequence cs, int radix) { return parseBoolean(cs, radix, 0, cs.length()); } /** * Parses the char sequence argument as a boolean. The boolean returned represents * the value true if the char sequence argument is not null and it's digit value * is 1. * @param cs * @param radix Must be 2. * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws IllegalArgumentException radix != 2 or if code point count != 1 * or if input digit is not 0/1. * @see java.lang.Character#digit(int, int) * @see java.lang.Character#codePointCount(java.lang.CharSequence, int, int) */ public static final boolean parseBoolean(CharSequence cs, int radix, int beginIndex, int endIndex) { if (radix != 2) { throw new IllegalArgumentException("radix must be 2"); } if (Character.codePointCount(cs, beginIndex, endIndex) != 1) { throw new IllegalArgumentException("input length must be 1"); } int digit = Character.digit(Character.codePointAt(cs, beginIndex), 2); switch (digit) { case 1: return true; case 0: return false; default: throw new IllegalArgumentException("input must be 0/1"); } } /** * Parses float from decimal floating point representation. * *

Input can start with '-' or '+'. *

All numbers are decimals. *

Decimal separator is '.' *

Exponent separator is 'e' or 'E' *

Examples *

-1234.56 *

+1234.56e12 *

-1234.56E-12 * @param cs * @return * @see java.lang.Float#parseFloat(java.lang.String) * @see java.lang.Character#digit(int, int) * @throws java.lang.NumberFormatException if input cannot be parsed to proper * float. */ public static final float parseFloat(CharSequence cs) { return parseFloat(cs, 0, cs.length()); } /** * Parses float from decimal floating point representation. * *

Input can start with '-' or '+'. *

All numbers are decimals. *

Decimal separator is '.' *

Exponent separator is 'e' or 'E' *

Examples *

-1234.56 *

+1234.56e12 *

-1234.56E-12 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @see java.lang.Float#parseFloat(java.lang.String) * @see java.lang.Character#digit(int, int) * @throws java.lang.NumberFormatException if input cannot be parsed to proper * float. */ public static final float parseFloat(CharSequence cs, int beginIndex, int endIndex) { FloatState fs = FloatState.Significand; int end = endIndex; int significand = 0; int sign = 1; int index = beginIndex; int decimal = 0; int exponent = 0; int exponentSign = 1; boolean overFlow = false; int cp = Character.codePointAt(cs, index); if (cp == '+') { index++; } if (cp == '-') { sign = -1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } while (index < end) { cp = Character.codePointAt(cs, index); if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } switch (cp) { default: int digit = Character.digit(cp, 10); if (digit != -1) { if (!overFlow && significand > IntLimit) { overFlow = true; } switch (fs) { case Significand: if (!overFlow) { significand *= 10; significand += digit; } else { decimal++; } break; case Decimal: if (!overFlow) { significand *= 10; significand += digit; decimal--; } break; case Exponent: exponent = 10*exponent + digit; break; } } else { throw new NumberFormatException("no float "+cs.subSequence(beginIndex, endIndex)); } break; case '.': if (fs != FloatState.Significand) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } fs = FloatState.Decimal; break; case 'e': case 'E': if (fs == FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } fs = FloatState.Exponent; break; case '-': if (fs != FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } exponentSign = -1; break; case '+': if (fs != FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } break; } } return (float) (sign * significand * Math.pow(10, exponentSign*exponent+decimal)); } /** * Parses double from decimal floating point representation. * *

Input can start with '-' or '+'. *

All number are decimals. *

Decimal separator is '.' *

Exponent separator is 'e' or 'E' *

Examples *

-1234.56 *

+1234.56e12 *

-1234.56E-12 * @param cs * @return * @see java.lang.Double#parseDouble(java.lang.String) * @see java.lang.Character#digit(int, int) * @throws java.lang.NumberFormatException if input cannot be parsed to proper * double. */ public static final double parseDouble(CharSequence cs) { return parseDouble(cs, 0, cs.length()); } /** * Parses double from decimal floating point representation. * *

Input can start with '-' or '+'. *

All number are decimals. *

Decimal separator is '.' *

Exponent separator is 'e' or 'E' *

Examples *

-1234.56 *

+1234.56e12 *

-1234.56E-12 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @see java.lang.Double#parseDouble(java.lang.String) * @see java.lang.Character#digit(int, int) * @throws java.lang.NumberFormatException if input cannot be parsed to proper * double. */ public static final double parseDouble(CharSequence cs, int beginIndex, int endIndex) { FloatState fs = FloatState.Significand; int end = endIndex; long significand = 0; int sign = 1; int index = beginIndex; int decimal = 0; int exponent = 0; int exponentSign = 1; boolean overFlow = false; int cp = Character.codePointAt(cs, index); if (cp == '+') { index++; } if (cp == '-') { sign = -1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } while (index < end) { cp = Character.codePointAt(cs, index); if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } switch (cp) { default: int digit = Character.digit(cp, 10); if (digit != -1) { if (!overFlow && significand > LongLimit) { overFlow = true; } switch (fs) { case Significand: if (!overFlow) { significand *= 10; significand += digit; } else { decimal++; } break; case Decimal: if (!overFlow) { significand *= 10; significand += digit; decimal--; } break; case Exponent: exponent = 10*exponent + digit; break; } } else { throw new NumberFormatException("no float "+cs.subSequence(beginIndex, endIndex)); } break; case '.': if (fs != FloatState.Significand) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } fs = FloatState.Decimal; break; case 'e': case 'E': if (fs == FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } fs = FloatState.Exponent; break; case '-': if (fs != FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } exponentSign = -1; break; case '+': if (fs != FloatState.Exponent) { throw new NumberFormatException("cannot convert "+cs.subSequence(beginIndex, endIndex)+" to float"); } break; } } return sign * significand * Math.pow(10, exponentSign*exponent+decimal); } /** * Equal to calling parseInt(cs, 10). * @param cs * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseInt(java.lang.String) * @see java.lang.Character#digit(int, int) */ public static final int parseInt(CharSequence cs) { if (CharSequences.startsWith(cs, "0b")) { return parseInt(cs, 2, 2, cs.length()); } if (CharSequences.startsWith(cs, "0x")) { return parseInt(cs, 16, 2, cs.length()); } return parseInt(cs, 10); } /** * Parses int from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseInt(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final int parseInt(CharSequence cs, int radix) { return parseInt(cs, radix, 0, cs.length()); } /** * Parses int from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseInt(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final int parseInt(CharSequence cs, int beginIndex, int endIndex) { return parseInt(cs, 10, beginIndex, endIndex); } /** * Parses int from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseInt(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final int parseInt(CharSequence cs, int radix, int beginIndex, int endIndex) { int size = Integer.SIZE; int end = endIndex; boolean twoComp = false; if (radix < 0) { twoComp = true; radix = -radix; check(cs, size, beginIndex, endIndex); } else { check(cs, radix, NumberRanges.IntRange, beginIndex, endIndex); } int result = 0; int sign = -1; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } index++; } if (cp == '-') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } sign = 1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } int count = Character.codePointCount(cs, index, end); if (count == size) { twoComp = false; } while (index < end) { result *= radix; cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); if (digit == -1) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } result -= digit; if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } } if (!twoComp || -result < (1<<(count-1))) { return sign*result; } else { return -result + (-1<Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * long. * @see java.lang.Long#parseLong(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final long parseLong(CharSequence cs, int radix) { return parseLong(cs, radix, 0, cs.length()); } /** * Parses long from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * long. * @see java.lang.Long#parseLong(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final long parseLong(CharSequence cs, int beginIndex, int endIndex) { return parseLong(cs, 10, beginIndex, endIndex); } /** * Parses long from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * long. * @see java.lang.Long#parseLong(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final long parseLong(CharSequence cs, int radix, int beginIndex, int endIndex) { int size = Long.SIZE; int end = endIndex; boolean twoComp = false; if (radix < 0) { twoComp = true; radix = -radix; check(cs, size, beginIndex, endIndex); } else { check(cs, radix, NumberRanges.LongRange, beginIndex, endIndex); } long result = 0; int sign = -1; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } index++; } if (cp == '-') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } sign = 1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } int count = Character.codePointCount(cs, index, end); if (count == size) { twoComp = false; } while (index < end) { result *= radix; cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); if (digit == -1) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } result -= digit; if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } } if (!twoComp || -result < (1<<(count-1))) { return sign*result; } else { return -result + (-1<Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * short. * @see java.lang.Short#parseShort(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final short parseShort(CharSequence cs, int radix) { return parseShort(cs, radix, 0, cs.length()); } /** * Parses short from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * short. * @see java.lang.Short#parseShort(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final short parseShort(CharSequence cs, int beginIndex, int endIndex) { return parseShort(cs, 10, beginIndex, endIndex); } /** * Parses short from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * short. * @see java.lang.Short#parseShort(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final short parseShort(CharSequence cs, int radix, int beginIndex, int endIndex) { int size = Short.SIZE; int end = endIndex; boolean twoComp = false; if (radix < 0) { twoComp = true; radix = -radix; check(cs, size, beginIndex, endIndex); } else { check(cs, radix, NumberRanges.ShortRange, beginIndex, endIndex); } short result = 0; int sign = -1; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } index++; } if (cp == '-') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } sign = 1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } int count = Character.codePointCount(cs, index, end); if (count == size) { twoComp = false; } while (index < end) { result *= radix; cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); if (digit == -1) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } result -= digit; if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } } if (!twoComp || -result < (1<<(count-1))) { return (short) (sign*result); } else { return (short) (-result + (-1<Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * byte. * @see java.lang.Byte#parseByte(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final byte parseByte(CharSequence cs, int radix) { return parseByte(cs, radix, 0, cs.length()); } /** * Parses byte from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * byte. * @see java.lang.Byte#parseByte(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final byte parseByte(CharSequence cs, int beginIndex, int endIndex) { return parseByte(cs, 10, beginIndex, endIndex); } /** * Parses byte from input. *

Input can start with '-' or '+'. *

Numeric value is according to radix *

Radix can also be -2, where input is parsed as 2-complement binary string. * Input beginning with '1' is always negative. Eg. '111' == -1, '110' == -2 * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * byte. * @see java.lang.Byte#parseByte(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final byte parseByte(CharSequence cs, int radix, int beginIndex, int endIndex) { int size = Byte.SIZE; int end = endIndex; boolean twoComp = false; if (radix < 0) { twoComp = true; radix = -radix; check(cs, size, beginIndex, endIndex); } else { check(cs, radix, NumberRanges.ByteRange, beginIndex, endIndex); } short result = 0; int sign = -1; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } index++; } if (cp == '-') { if (twoComp) { throw new NumberFormatException("no signs for 2-complement "+cs.subSequence(beginIndex, endIndex)); } sign = 1; index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } int count = Character.codePointCount(cs, index, end); if (count == size) { twoComp = false; } while (index < end) { result *= radix; cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); if (digit == -1) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } result -= digit; if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } } if (!twoComp || -result < (1<<(count-1))) { return (byte) (sign*result); } else { return (byte) (-result + (-1<Input can start with '+'. *

Numeric value is according to radix * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseUnsignedInt(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final int parseUnsignedInt(CharSequence cs, int radix) { return parseUnsignedInt(cs, radix, 0, cs.length()); } /** * Parses unsigned int from input. *

Input can start with '+'. *

Numeric value is according to radix * @param cs * @param radix A value between Character.MIN_RADIX and Character.MAX_RADIX or -2 * @param beginIndex the index to the first char of the text range. * @param endIndex the index after the last char of the text range. * @return * @throws java.lang.NumberFormatException if input cannot be parsed to proper * int. * @see java.lang.Integer#parseUnsignedInt(java.lang.String, int) * @see java.lang.Character#digit(int, int) */ public static final int parseUnsignedInt(CharSequence cs, int radix, int beginIndex, int endIndex) { check(cs, radix, NumberRanges.UnsignedIntRange, beginIndex, endIndex); int end = endIndex; int result = 0; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { index++; } if (index >= end) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } while (index < end) { result *= radix; cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); if (digit == -1) { throw new NumberFormatException("unparsable number "+cs.subSequence(beginIndex, endIndex)); } result += digit; if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } } return result; } private static void check(CharSequence cs, int radix, CharSequence[][] range, int beginIndex, int endIndex) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { throw new NumberFormatException(cs+" radix "+radix+" not supported"); } CharSequence lower = range[radix][0]; CharSequence upper = range[radix][1]; int sign = 1; int index = beginIndex; int cp = Character.codePointAt(cs, index); if (cp == '+') { index++; } if (cp == '-') { sign = -1; index++; } int count = Character.codePointCount(cs, index, endIndex); cp = Character.codePointAt(cs, index); int digit = Character.digit(cp, radix); while (digit == 0 && count > 1) { if (Character.isBmpCodePoint(cp)) { index++; } else { index += 2; } cp = Character.codePointAt(cs, index); digit = Character.digit(cp, radix); count--; } if (sign == -1) { if (Character.codePointAt(lower, 0) != '-') { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+" not in range["+lower+" - "+upper+"]"); } if (count+1 > lower.length()) { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+" not in range["+lower+" - "+upper+"]"); } if (count+1 == lower.length() && isGreater(cs, radix, lower, beginIndex, endIndex)) { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+" not in range["+lower+" - "+upper+"]"); } } else { if (count > upper.length()) { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+" not in range["+lower+" - "+upper+"]"); } if (count == upper.length() && isGreater(cs, radix, upper, beginIndex, endIndex)) { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+" not in range["+lower+" - "+upper+"]"); } } } private static boolean isGreater(CharSequence cs, int radix, CharSequence range, int beginIndex, int endIndex) { int end = endIndex; int count = Character.codePointCount(cs, beginIndex, end); int ii = 0; int jj = 0; switch (cs.charAt(beginIndex)) { case '-': ii = 1; jj = 1; break; case '+': ii = 1; break; } for (;ii d2) { return true; } if (d1 < d2) { return false; } if (Character.isBmpCodePoint(cp1)) { jj++; } else { jj += 2; } } return false; } private static void check(CharSequence cs, int size, int beginIndex, int endIndex) { int end = endIndex; int index = beginIndex; int count = Character.codePointCount(cs, index, end); if (count > size) { throw new NumberFormatException(cs.subSequence(beginIndex, endIndex)+"not valid number"); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy