1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-10-27 20:34:16 +00:00
gnosygnu_xowa/400_xowa/src_060_utl/gplx/NumberParser.java
2014-06-30 00:15:52 -04:00

165 lines
5.2 KiB
Java

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class NumberParser {
public int AsInt() {return (int)int_val;} long int_val = 0;
public DecimalAdp AsDec() {return dec_val == null ? DecimalAdp_.long_(int_val) : dec_val;} DecimalAdp dec_val = null;
public boolean HasErr() {return hasErr;} private boolean hasErr;
public boolean HasFrac() {return hasFrac;} private boolean hasFrac;
public boolean Hex_enabled() {return hex_enabled;} public NumberParser Hex_enabled_(boolean v) {hex_enabled = v; return this;} private boolean hex_enabled;
public NumberParser Parse(byte[] src) {return Parse(src, 0, src.length);}
public NumberParser Parse(byte[] ary, int bgn, int end) {
int loop_bgn = end - 1, loop_end = bgn - 1, exp_multiplier = 1, factor = 10;
long multiplier = 1, frc_multiplier = 1;
int_val = 0; dec_val = null; boolean comma_nil = true;
long frc_int = 0;
hasErr = false; hasFrac = false; boolean has_exp = false, has_neg = false, exp_neg = false, has_plus = false, has_num = false;
boolean input_is_hex = false;
if (hex_enabled) {
if (loop_end + 2 < end) { // ArrayOutOfBounds check
byte b_2 = ary[loop_end + 2];
switch (b_2) {
case Byte_ascii.Ltr_x:
case Byte_ascii.Ltr_X: // is 2nd char x?
if (ary[loop_end + 1] == Byte_ascii.Num_0) { // is 1st char 0?
factor = 16;
input_is_hex = true;
}
break;
default:
break;
}
}
}
for (int i = loop_bgn; i > loop_end; i--) {
byte cur = ary[i];
switch (cur) {
case Byte_ascii.Num_0:
case Byte_ascii.Num_1:
case Byte_ascii.Num_2:
case Byte_ascii.Num_3:
case Byte_ascii.Num_4:
case Byte_ascii.Num_5:
case Byte_ascii.Num_6:
case Byte_ascii.Num_7:
case Byte_ascii.Num_8:
case Byte_ascii.Num_9:
int_val += (cur - Byte_ascii.Num_0) * multiplier;
multiplier *= factor;
has_num = true;
break;
case Byte_ascii.Dot:
if (hasFrac) return IsErr_();
frc_int = int_val;
int_val = 0;
frc_multiplier = multiplier;
multiplier = 1;
hasFrac = true;
break;
case Byte_ascii.Comma:
if (comma_nil)
comma_nil = false;
else
return IsErr_();
break;
case Byte_ascii.Dash:
if (has_neg) return IsErr_();
has_neg = true;
break;
case Byte_ascii.Space:
if (i == bgn) {} // space at bgn
else
return IsErr_();
break;
case Byte_ascii.Plus:
if (has_plus) return IsErr_();
has_plus = true;
break;
case Byte_ascii.Ltr_e:
case Byte_ascii.Ltr_E:
if (input_is_hex) {
int_val += 14 * multiplier; // NOTE: 14=value of e/E
multiplier *= factor;
has_num = true;
}
else {
if (has_exp) return IsErr_();
exp_neg = has_neg;
exp_multiplier = (int)Math_.Pow(10, int_val);
int_val = 0;
multiplier = 1;
has_exp = true;
has_neg = false;
has_plus = false; // allow +1E+2
}
break;
case Byte_ascii.Ltr_A:
case Byte_ascii.Ltr_B:
case Byte_ascii.Ltr_C:
case Byte_ascii.Ltr_D:
case Byte_ascii.Ltr_F:
if (input_is_hex) {
int_val += (cur - Byte_ascii.Ltr_A + 10) * multiplier;
multiplier *= factor;
has_num = true;
}
else
return IsErr_();
break;
case Byte_ascii.Ltr_a:
case Byte_ascii.Ltr_b:
case Byte_ascii.Ltr_c:
case Byte_ascii.Ltr_d:
case Byte_ascii.Ltr_f:
if (input_is_hex) {
int_val += (cur - Byte_ascii.Ltr_a + 10) * multiplier;
multiplier *= factor;
has_num = true;
}
else
return IsErr_();
break;
case Byte_ascii.Ltr_x:
case Byte_ascii.Ltr_X:
if (input_is_hex)
return (factor == 16) ? this : IsErr_(); // check for '0x'
else
return IsErr_();
default:
return IsErr_();
}
}
if (!has_num) return IsErr_(); // handles situations wherein just symbols; EX: "+", ".", "-.", " , " etc.
if (hasFrac) {
long full_val = (((int_val * frc_multiplier) + frc_int));
if (has_neg) full_val *= -1;
if (has_exp) {
if (exp_neg) frc_multiplier *= exp_multiplier; // divide, so apply to frc
else full_val *= exp_multiplier; // multiply, so apply to full_val
}
dec_val = DecimalAdp_.divide_(full_val, frc_multiplier);
}
else {
if (has_neg) int_val *= -1;
if (has_exp) int_val = exp_neg ? int_val / exp_multiplier : int_val * exp_multiplier;
}
return this;
}
NumberParser IsErr_() {hasErr = true; return this;}
}