001: package com.tagtraum.perf.gcviewer.util;
002:
003: /**
004: * Fast methods for parsing ints and longs.
005: * <p>
006: * This class originally stems form the book "Performant Java Programmieren" by Hendrik Schreiber
007: *
008: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
009: * @version $Id: $
010: * @see <a href="http://www.tagtraum.com/performance/">"Performant Java Programmieren" by Hendrik Schreiber</a>
011: */
012: public class NumberParser {
013: // replace parseInt(String) with parseInt(CharSequence) in later version
014: // replace parseLong(String) with parseLong(CharSequence) in later version
015:
016: public static final int MAX_NEGATIVE_INTEGER_CHARS = Integer
017: .toString(Integer.MIN_VALUE).length();
018: public static final int MAX_POSITIVE_INTEGER_CHARS = Integer
019: .toString(Integer.MAX_VALUE).length();
020:
021: public static final int MAX_NEGATIVE_LONG_CHARS = Long.toString(
022: Long.MIN_VALUE).length();
023: public static final int MAX_POSITIVE_LONG_CHARS = Long.toString(
024: Long.MAX_VALUE).length();
025:
026: public static int parseInt(char[] cb, int offset, int length)
027: throws NumberFormatException {
028: if (cb == null)
029: throw new NumberFormatException("null");
030: int result = 0;
031: boolean negative = false;
032: int i = 0;
033: int limit;
034: int digit;
035:
036: if (length > 0) {
037: if (cb[offset] == '-') {
038: if (length > MAX_NEGATIVE_INTEGER_CHARS)
039: throw new NumberFormatException(new String(cb,
040: offset, length));
041: negative = true;
042: limit = Integer.MIN_VALUE;
043: i++;
044: } else {
045: if (length > MAX_POSITIVE_INTEGER_CHARS)
046: throw new NumberFormatException(new String(cb,
047: offset, length));
048: limit = -Integer.MAX_VALUE;
049: }
050: while (i < length) {
051: digit = cb[offset + i++] - '0';
052: if (digit < 0 || digit > 9) {
053: throw new NumberFormatException(new String(cb,
054: offset, length));
055: }
056: result *= 10;
057: if (result < limit + digit) {
058: throw new NumberFormatException(new String(cb,
059: offset, length));
060: }
061: result -= digit;
062: }
063: } else {
064: throw new NumberFormatException(new String(cb, offset,
065: length));
066: }
067: if (negative) {
068: if (i > 1) {
069: return result;
070: } else {
071: throw new NumberFormatException(new String(cb, offset,
072: length));
073: }
074: } else {
075: return -result;
076: }
077: }
078:
079: public static int parseInt(String s) throws NumberFormatException {
080: return parseInt(s, 0, s.length());
081: }
082:
083: public static int parseInt(String s, int offset, int length)
084: throws NumberFormatException {
085: // for speed this is a copy of parseInt(string) instead of just using toCharArrays()...
086: if (s == null)
087: throw new NumberFormatException("null");
088: int result = 0;
089: boolean negative = false;
090: int i = 0;
091: int limit;
092: int digit;
093:
094: if (length > 0) {
095: if (s.charAt(offset) == '-') {
096: if (length > MAX_NEGATIVE_INTEGER_CHARS)
097: throw new NumberFormatException(s);
098: negative = true;
099: limit = Integer.MIN_VALUE;
100: i++;
101: } else {
102: if (length > MAX_POSITIVE_INTEGER_CHARS)
103: throw new NumberFormatException(s);
104: limit = -Integer.MAX_VALUE;
105: }
106: while (i < length) {
107: digit = s.charAt(offset + i++) - '0';
108: if (digit < 0 || digit > 9) {
109: throw new NumberFormatException(s);
110: }
111: result *= 10;
112: if (result < limit + digit) {
113: throw new NumberFormatException(s);
114: }
115: result -= digit;
116: }
117: } else {
118: throw new NumberFormatException(s);
119: }
120: if (negative) {
121: if (i > 1) {
122: return result;
123: } else {
124: throw new NumberFormatException(s);
125: }
126: } else {
127: return -result;
128: }
129: }
130:
131: public static long parseLong(String s) throws NumberFormatException {
132: return parseLong(s, 0, s.length());
133: }
134:
135: public static long parseLong(String s, int offset, int length)
136: throws NumberFormatException {
137: if (s == null)
138: throw new NumberFormatException("null");
139: long result = 0;
140: boolean negative = false;
141: int i = 0;
142: long limit;
143: int digit;
144:
145: if (length > 0) {
146: if (s.charAt(offset) == '-') {
147: // shortcut for ints
148: if (length <= MAX_NEGATIVE_INTEGER_CHARS)
149: return (long) parseInt(s, offset, length);
150: if (length > MAX_NEGATIVE_LONG_CHARS)
151: throw new NumberFormatException(s);
152: negative = true;
153: limit = Long.MIN_VALUE;
154: i++;
155: } else {
156: // shortcut for ints
157: if (length <= MAX_POSITIVE_INTEGER_CHARS)
158: return (long) parseInt(s, offset, length);
159: if (length > MAX_POSITIVE_LONG_CHARS)
160: throw new NumberFormatException(s);
161: limit = -Long.MAX_VALUE;
162: }
163: while (i < length) {
164: digit = s.charAt(offset + i++) - '0';
165: if (digit < 0 || digit > 9) {
166: throw new NumberFormatException(s);
167: }
168: result *= 10L;
169: if (result < limit + digit) {
170: throw new NumberFormatException(s);
171: }
172: result -= digit;
173: }
174: } else {
175: throw new NumberFormatException(s);
176: }
177: if (negative) {
178: if (i > 1) {
179: return result;
180: } else {
181: throw new NumberFormatException(s);
182: }
183: } else {
184: return -result;
185: }
186: }
187:
188: public static long parseLong(char[] cb, int offset, int length)
189: throws NumberFormatException {
190: // for speed this is a copy of parseLong(string) instead of just using toCharArrays()...
191: if (cb == null)
192: throw new NumberFormatException("null");
193: long result = 0;
194: boolean negative = false;
195: int i = 0;
196: long limit;
197: int digit;
198:
199: if (length > 0) {
200: if (cb[offset] == '-') {
201: // shortcut for ints
202: if (length <= MAX_NEGATIVE_INTEGER_CHARS)
203: return (long) parseInt(cb, offset, length);
204: if (length > MAX_NEGATIVE_LONG_CHARS)
205: throw new NumberFormatException(new String(cb,
206: offset, length));
207: negative = true;
208: limit = Long.MIN_VALUE;
209: i++;
210: } else {
211: // shortcut for ints
212: if (length <= MAX_POSITIVE_INTEGER_CHARS)
213: return (long) parseInt(cb, offset, length);
214: if (length > MAX_POSITIVE_LONG_CHARS)
215: throw new NumberFormatException(new String(cb,
216: offset, length));
217: limit = -Long.MAX_VALUE;
218: }
219: while (i < length) {
220: digit = cb[offset + i++] - '0';
221: if (digit < 0 || digit > 9) {
222: throw new NumberFormatException(new String(cb,
223: offset, length));
224: }
225: result *= 10L;
226: if (result < limit + digit) {
227: throw new NumberFormatException(new String(cb,
228: offset, length));
229: }
230: result -= digit;
231: }
232: } else {
233: throw new NumberFormatException(new String(cb, offset,
234: length));
235: }
236: if (negative) {
237: if (i > 1) {
238: return result;
239: } else {
240: throw new NumberFormatException(new String(cb, offset,
241: length));
242: }
243: } else {
244: return -result;
245: }
246: }
247: }
|