mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
165 lines
5.2 KiB
Java
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;}
|
|
}
|