mirror of https://github.com/gnosygnu/xowa
parent
9d63f03b3d
commit
34c34f227c
@ -1,67 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
public class DecimalAdp implements CompareAble {
|
||||
public int compareTo(Object obj) {DecimalAdp comp = (DecimalAdp)obj; return under.compareTo(comp.under);}
|
||||
|
||||
protected DecimalAdp(BigDecimal v) {this.under = v;} BigDecimal under;
|
||||
protected DecimalAdp(int v) {this.under = new BigDecimal(v);}
|
||||
public String Xto_str() {
|
||||
BigDecimal tmp = under;
|
||||
int tmp_scale = tmp.scale();
|
||||
if (tmp_scale <= -14) return tmp.toString(); // NOTE: if large number, call .toString which will return exponential notaion (1E##) instead of literal (1000....); 14 matches MW code; DATE:2015-04-10
|
||||
if (tmp_scale > 14)
|
||||
tmp = tmp.setScale(14, RoundingMode.DOWN); // NOTE: if small number, round down to remove excessive zeroes; 14 matches PHP/C# values more closely; RoundingMode.Down for same reason; see E, Pi tests
|
||||
return tmp .stripTrailingZeros() // NOTE: stripTrailingZeros for exp tests; EX: 120.0 -> 120; 0.01200000000000 -> .012
|
||||
.toPlainString(); // NOTE: toPlainString b/c stripTrailingZeros now converts 120 to 1.2E+2 (and any other value that is a multiple of 10)
|
||||
}
|
||||
public String Xto_str(String fmt) {return new DecimalFormat(fmt).format(under);}
|
||||
@Override public String toString() {return under.toString();}
|
||||
public boolean Eq(DecimalAdp v) {return v.under.doubleValue() == under.doubleValue();}
|
||||
public BigDecimal Xto_decimal() {return under;}
|
||||
public long Xto_long_mult_1000() {return under.movePointRight(3).longValue();}
|
||||
public int Fraction1000() {return (int)(under.movePointRight(3).floatValue() % 1000);}
|
||||
public double Xto_double() {return under.doubleValue();}
|
||||
public int Xto_int() {return (int)under.doubleValue();}
|
||||
public long Xto_long() {return (long)under.doubleValue();}
|
||||
public DecimalAdp Op_add(DecimalAdp v) {return new DecimalAdp(under.add(v.under, DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_subtract(DecimalAdp v) {return new DecimalAdp(under.subtract(v.under, DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_mult(DecimalAdp v) {return new DecimalAdp(under.multiply(v.under));}
|
||||
public DecimalAdp Op_mult(double v) {return new DecimalAdp(under.multiply(new BigDecimal(v, DecimalAdp_.Gplx_rounding_context)));}
|
||||
public DecimalAdp Op_mult(long v) {return new DecimalAdp(under.multiply(new BigDecimal(v)));}
|
||||
public DecimalAdp Op_divide(DecimalAdp v) {return new DecimalAdp(under.divide(v.under, DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_mod(DecimalAdp v) {return new DecimalAdp(under.remainder(v.under, DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_sqrt() {return new DecimalAdp(new BigDecimal(Math_.Sqrt(under.doubleValue())));}
|
||||
public DecimalAdp Op_abs() {return new DecimalAdp(under.abs(DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_pow(int v) {return new DecimalAdp(under.pow(v, DecimalAdp_.Gplx_rounding_context));}
|
||||
public DecimalAdp Op_truncate_decimal() {return new DecimalAdp(under.intValue());}
|
||||
public DecimalAdp Op_round(int v) {return new DecimalAdp(under.setScale(v, RoundingMode.HALF_UP));}
|
||||
public boolean Comp_gte(DecimalAdp v) {return under.doubleValue() >= v.under.doubleValue();}
|
||||
public boolean Comp_gte(int v) {return under.doubleValue() >= v;}
|
||||
public boolean Comp_lte(DecimalAdp v) {return under.doubleValue() <= v.under.doubleValue();}
|
||||
public boolean Comp_lte(int v) {return under.doubleValue() <= v;}
|
||||
public boolean Comp_gt(DecimalAdp v) {return under.doubleValue() > v.under.doubleValue();}
|
||||
public boolean Comp_gt(int v) {return under.doubleValue() > v;}
|
||||
public boolean Comp_lt(DecimalAdp v) {return under.doubleValue() < v.under.doubleValue();}
|
||||
public boolean Comp_lt(int v) {return under.doubleValue() < v;}
|
||||
public boolean Eq(int v) {return under.doubleValue() == v;}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class DecimalAdp_ {
|
||||
public static final Class<?> Cls_ref_type = DecimalAdp.class;
|
||||
public static DecimalAdp as_(Object obj) {return obj instanceof DecimalAdp ? (DecimalAdp)obj : null;}
|
||||
public static final DecimalAdp Zero = new DecimalAdp(0);
|
||||
public static final DecimalAdp One = new DecimalAdp(1);
|
||||
public static final DecimalAdp Neg1 = new DecimalAdp(-1);
|
||||
public static final DecimalAdp Const_e = DecimalAdp_.double_(Math_.E);
|
||||
public static final DecimalAdp Const_pi = DecimalAdp_.double_(Math_.Pi);
|
||||
public static DecimalAdp base1000_(long v) {return divide_(v, 1000);}
|
||||
public static DecimalAdp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
|
||||
public static DecimalAdp parts_(long num, int frc) {
|
||||
// int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
|
||||
// int pow10 = (int)Math_.Pow(10, log10);
|
||||
int pow10 = XtoPow10(frc);
|
||||
return divide_((num * (pow10)) + frc, pow10);
|
||||
}
|
||||
public static DecimalAdp cast_(Object obj) {return (DecimalAdp)obj;}
|
||||
static int XtoPow10(int v) {
|
||||
if (v > -1 && v < 10) return 10;
|
||||
else if (v > 9 && v < 100) return 100;
|
||||
else if (v > 99 && v < 1000) return 1000;
|
||||
else if (v > 999 && v < 10000) return 10000;
|
||||
else if (v > 9999 && v < 100000) return 100000;
|
||||
else if (v > 99999 && v < 1000000) return 1000000;
|
||||
else if (v > 999999 && v < 10000000) return 10000000;
|
||||
else if (v > 9999999 && v < 100000000) return 100000000;
|
||||
else if (v > 99999999 && v < 1000000000) return 1000000000;
|
||||
else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
|
||||
}
|
||||
public static String CalcPctStr(long dividend, long divisor, String fmt) {
|
||||
if (divisor == 0) return "%ERR";
|
||||
return DecimalAdp_.float_(Float_.Div(dividend, divisor) * 100).Xto_str(fmt) + "%";
|
||||
}
|
||||
public static DecimalAdp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
|
||||
public static DecimalAdp divide_(long lhs, long rhs) {
return new DecimalAdp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
}
public static DecimalAdp int_(int v) {return new DecimalAdp(new BigDecimal(v));}
public static DecimalAdp long_(long v) {return new DecimalAdp(new BigDecimal(v));}
|
||||
public static DecimalAdp float_(float v) {return new DecimalAdp(new BigDecimal(v));}
public static DecimalAdp double_(double v) {return new DecimalAdp(new BigDecimal(v));}
|
||||
public static DecimalAdp double_thru_str_(double v) {return new DecimalAdp(BigDecimal.valueOf(v));}
|
||||
public static DecimalAdp db_(Object v) {return new DecimalAdp((BigDecimal)v);}
public static DecimalAdp parse_(String raw) {return new DecimalAdp(new BigDecimal(raw));}
public static DecimalAdp pow_10_(int v) {return new DecimalAdp(new BigDecimal(1).scaleByPowerOfTen(v));}
|
||||
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
static final MathContext Gplx_rounding_context = new MathContext(28, RoundingMode.HALF_UP);
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
import org.junit.*;
|
||||
public class DecimalAdp__tst {
|
||||
@Test public void divide_() {
|
||||
tst_divide_(1, 1000, "0.001");
|
||||
tst_divide_(1, 3, "0.33333333333333");
|
||||
tst_divide_(1, 7, "0.14285714285714");
|
||||
} void tst_divide_(int lhs, int rhs, String expd) {Tfds.Eq(expd, DecimalAdp_.divide_(lhs, rhs).Xto_str());}
|
||||
@Test public void base1000_() {
|
||||
tst_base1000_(1000, "1");
|
||||
tst_base1000_(1234, "1.234");
|
||||
tst_base1000_(123, "0.123");
|
||||
} void tst_base1000_(int val, String expd) {Tfds.Eq(expd, DecimalAdp_.base1000_(val).Xto_str());}
|
||||
@Test public void parts_() {
|
||||
tst_parts_(1, 0, "1");
|
||||
tst_parts_(1, 2, "1.2");
|
||||
tst_parts_(1, 23, "1.23");
|
||||
tst_parts_(123, 4567, "123.4567");
|
||||
} void tst_parts_(int num, int fracs, String expd) {Tfds.Eq(expd, DecimalAdp_.parts_(num, fracs).Xto_str());}
|
||||
@Test public void parse_() {
|
||||
tst_parse_("1", "1");
|
||||
tst_parse_("1.2", "1.2");
|
||||
tst_parse_("0.1", "0.1");
|
||||
} void tst_parse_(String raw, String expd) {Tfds.Eq(expd, DecimalAdp_.parse_(raw).Xto_str());}
|
||||
@Test public void Truncate_decimal() {
|
||||
tst_Truncate_decimal("1", "1");
|
||||
tst_Truncate_decimal("1.1", "1");
|
||||
tst_Truncate_decimal("1.9", "1");
|
||||
} void tst_Truncate_decimal(String raw, String expd) {Tfds.Eq(DecimalAdp_.parse_(expd).Xto_str(), DecimalAdp_.parse_(raw).Op_truncate_decimal().Xto_str());}
|
||||
@Test public void Fraction1000() {
|
||||
tst_Fraction1000(1, 1000, 1); // 0.001
|
||||
tst_Fraction1000(1, 3, 333); // 0.33333333
|
||||
tst_Fraction1000(1234, 1000, 234); // 1.234
|
||||
tst_Fraction1000(12345, 10000, 234); // 1.2345
|
||||
} void tst_Fraction1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, DecimalAdp_.divide_(lhs, rhs).Fraction1000());}
|
||||
@Test public void Lt() {
|
||||
tst_Lt(1,123, 2, true);
|
||||
tst_Lt(1,99999999, 2, true);
|
||||
} void tst_Lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, DecimalAdp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
|
||||
@Test public void XtoStr_fmt() {
|
||||
tst_XtoStr_fmt(1, 2, "0.0", "0.5");
|
||||
tst_XtoStr_fmt(1, 3, "0.0", "0.3");
|
||||
tst_XtoStr_fmt(10000, 7, "0,000.000", "1,428.571");
|
||||
} void tst_XtoStr_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, DecimalAdp_.divide_(l, r).Xto_str(fmt));}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
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;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
public class Decimal_adp implements CompareAble {
|
||||
public int compareTo(Object obj) {Decimal_adp comp = (Decimal_adp)obj; return under.compareTo(comp.under);}
|
||||
|
||||
protected Decimal_adp(BigDecimal v) {this.under = v;} private final BigDecimal under;
|
||||
protected Decimal_adp(int v) {this.under = new BigDecimal(v);}
|
||||
public Object Under() {return under;}
|
||||
public BigDecimal Under_as_native() {return under;}
|
||||
public int Precision() {return under.precision();}
|
||||
public int Frac_1000() {return (int)(under.movePointRight(3).floatValue() % 1000);}
|
||||
public boolean Eq(Decimal_adp v) {return v.under.doubleValue() == under.doubleValue();}
|
||||
public boolean Eq(int v) {return under.doubleValue() == v;}
|
||||
public String To_str() {
|
||||
BigDecimal tmp = under;
|
||||
int tmp_scale = tmp.scale();
|
||||
if (tmp_scale <= -14) return tmp.toString(); // NOTE: if large number, call .toString which will return exponential notaion (1E##) instead of literal (1000....); 14 matches MW code; DATE:2015-04-10
|
||||
if (tmp_scale > 14)
|
||||
tmp = tmp.setScale(14, RoundingMode.DOWN); // NOTE: if small number, round down to remove excessive zeroes; 14 matches PHP/C# values more closely; RoundingMode.Down for same reason; see E, Pi tests
|
||||
return tmp .stripTrailingZeros() // NOTE: stripTrailingZeros for exp tests; EX: 120.0 -> 120; 0.01200000000000 -> .012
|
||||
.toPlainString(); // NOTE: toPlainString b/c stripTrailingZeros now converts 120 to 1.2E+2 (and any other value that is a multiple of 10)
|
||||
}
|
||||
public String To_str(String fmt) {return new DecimalFormat(fmt).format(under);}
|
||||
@Override public String toString() {return under.toString();}
|
||||
public int To_int() {return (int)under.doubleValue();}
|
||||
public long To_long() {return (long)under.doubleValue();}
|
||||
public long To_long_mult_1000() {return under.movePointRight(3).longValue();}
|
||||
public double To_double() {return under.doubleValue();}
|
||||
public Decimal_adp Add(Decimal_adp v) {return new Decimal_adp(under.add(v.under, Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Subtract(Decimal_adp v) {return new Decimal_adp(under.subtract(v.under, Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Multiply(Decimal_adp v) {return new Decimal_adp(under.multiply(v.under));}
|
||||
public Decimal_adp Multiply(double v) {return new Decimal_adp(under.multiply(new BigDecimal(v, Decimal_adp_.Gplx_rounding_context)));}
|
||||
public Decimal_adp Multiply(long v) {return new Decimal_adp(under.multiply(new BigDecimal(v)));}
|
||||
public Decimal_adp Divide(Decimal_adp v) {return new Decimal_adp(under.divide(v.under, Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Mod(Decimal_adp v) {return new Decimal_adp(under.remainder(v.under, Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Abs() {return new Decimal_adp(under.abs(Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Pow(int v) {return new Decimal_adp(under.pow(v, Decimal_adp_.Gplx_rounding_context));}
|
||||
public Decimal_adp Sqrt() {return new Decimal_adp(new BigDecimal(Math_.Sqrt(under.doubleValue())));}
|
||||
public Decimal_adp Truncate() {return new Decimal_adp(under.intValue());}
|
||||
public Decimal_adp Round_old(int v) {return new Decimal_adp(under.setScale(v, RoundingMode.HALF_UP));}
|
||||
public Decimal_adp Round(int v) {
|
||||
BigDecimal new_val = null;
|
||||
if (v > 0) {
|
||||
new_val = under.setScale(v, RoundingMode.HALF_UP);
|
||||
}
|
||||
else {
|
||||
int actl_places = under.precision() - under.scale();
|
||||
int reqd_places = -v;
|
||||
if (reqd_places < actl_places)
|
||||
new_val = under.round(new java.math.MathContext(actl_places - reqd_places, RoundingMode.HALF_UP));
|
||||
else if (reqd_places == actl_places) {
|
||||
int base_10 = (int)Math_.Pow(10, reqd_places - 1);
|
||||
if (under.intValue() / base_10 < 5)
|
||||
new_val = BigDecimal.ZERO;
|
||||
else
|
||||
new_val = new BigDecimal(Math_.Pow(10, reqd_places));
|
||||
}
|
||||
else
|
||||
new_val = BigDecimal.ZERO;
|
||||
}
|
||||
return new Decimal_adp(new_val);
|
||||
}
|
||||
public boolean Comp_gte(Decimal_adp v) {return under.doubleValue() >= v.under.doubleValue();}
|
||||
public boolean Comp_gte(int v) {return under.doubleValue() >= v;}
|
||||
public boolean Comp_lte(Decimal_adp v) {return under.doubleValue() <= v.under.doubleValue();}
|
||||
public boolean Comp_lte(int v) {return under.doubleValue() <= v;}
|
||||
public boolean Comp_gt(Decimal_adp v) {return under.doubleValue() > v.under.doubleValue();}
|
||||
public boolean Comp_gt(int v) {return under.doubleValue() > v;}
|
||||
public boolean Comp_lt(Decimal_adp v) {return under.doubleValue() < v.under.doubleValue();}
|
||||
public boolean Comp_lt(int v) {return under.doubleValue() < v;}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
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;
|
||||
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class Decimal_adp_ {
|
||||
public static final Class<?> Cls_ref_type = Decimal_adp.class;
|
||||
public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
|
||||
public static final Decimal_adp Zero = new Decimal_adp(0);
|
||||
public static final Decimal_adp One = new Decimal_adp(1);
|
||||
public static final Decimal_adp Neg1 = new Decimal_adp(-1);
|
||||
public static final Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
|
||||
public static final Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
|
||||
public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
|
||||
public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
|
||||
public static Decimal_adp parts_(long num, int frc) {
|
||||
// int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
|
||||
// int pow10 = (int)Math_.Pow(10, log10);
|
||||
int pow10 = XtoPow10(frc);
|
||||
return divide_((num * (pow10)) + frc, pow10);
|
||||
}
|
||||
public static Decimal_adp cast_(Object obj) {return (Decimal_adp)obj;}
|
||||
static int XtoPow10(int v) {
|
||||
if (v > -1 && v < 10) return 10;
|
||||
else if (v > 9 && v < 100) return 100;
|
||||
else if (v > 99 && v < 1000) return 1000;
|
||||
else if (v > 999 && v < 10000) return 10000;
|
||||
else if (v > 9999 && v < 100000) return 100000;
|
||||
else if (v > 99999 && v < 1000000) return 1000000;
|
||||
else if (v > 999999 && v < 10000000) return 10000000;
|
||||
else if (v > 9999999 && v < 100000000) return 100000000;
|
||||
else if (v > 99999999 && v < 1000000000) return 1000000000;
|
||||
else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
|
||||
}
|
||||
public static String CalcPctStr(long dividend, long divisor, String fmt) {
|
||||
if (divisor == 0) return "%ERR";
|
||||
return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
|
||||
}
|
||||
public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
|
||||
public static Decimal_adp divide_(long lhs, long rhs) {
return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
}
public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
|
||||
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
public static Decimal_adp parse_(String raw) {return new Decimal_adp(new BigDecimal(raw));}
public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
|
||||
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
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;
|
||||
import org.junit.*;
|
||||
public class Decimal_adp__tst {
|
||||
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt();
|
||||
@Test public void divide_() {
|
||||
fxt.Test_divide(1, 1000, "0.001");
|
||||
fxt.Test_divide(1, 3, "0.33333333333333");
|
||||
fxt.Test_divide(1, 7, "0.14285714285714");
|
||||
}
|
||||
@Test public void base1000_() {
|
||||
fxt.Test_base_1000(1000, "1");
|
||||
fxt.Test_base_1000(1234, "1.234");
|
||||
fxt.Test_base_1000(123, "0.123");
|
||||
}
|
||||
@Test public void parts_() {
|
||||
fxt.Test_parts(1, 0, "1");
|
||||
fxt.Test_parts(1, 2, "1.2");
|
||||
fxt.Test_parts(1, 23, "1.23");
|
||||
fxt.Test_parts(123, 4567, "123.4567");
|
||||
}
|
||||
@Test public void parse_() {
|
||||
fxt.Test_parse("1", "1");
|
||||
fxt.Test_parse("1.2", "1.2");
|
||||
fxt.Test_parse("0.1", "0.1");
|
||||
}
|
||||
@Test public void Truncate_decimal() {
|
||||
fxt.Test_truncate_decimal("1", "1");
|
||||
fxt.Test_truncate_decimal("1.1", "1");
|
||||
fxt.Test_truncate_decimal("1.9", "1");
|
||||
}
|
||||
@Test public void Fraction1000() {
|
||||
fxt.Test_frac_1000(1, 1000, 1); // 0.001
|
||||
fxt.Test_frac_1000(1, 3, 333); // 0.33333333
|
||||
fxt.Test_frac_1000(1234, 1000, 234); // 1.234
|
||||
fxt.Test_frac_1000(12345, 10000, 234); // 1.2345
|
||||
}
|
||||
@Test public void Lt() {
|
||||
fxt.Test_comp_lt(1,123, 2, true);
|
||||
fxt.Test_comp_lt(1,99999999, 2, true);
|
||||
}
|
||||
@Test public void To_str_fmt() {
|
||||
fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
|
||||
fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
|
||||
fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
|
||||
}
|
||||
@Test public void Round() {
|
||||
fxt.Test_round("123.456", 3, "123.456");
|
||||
fxt.Test_round("123.456", 2, "123.46");
|
||||
fxt.Test_round("123.456", 1, "123.5");
|
||||
fxt.Test_round("123.456", 0, "123");
|
||||
fxt.Test_round("123.456", -1, "120");
|
||||
fxt.Test_round("123.456", -2, "100");
|
||||
fxt.Test_round("123.456", -3, "0");
|
||||
|
||||
fxt.Test_round("6", -1, "10");
|
||||
fxt.Test_round("5", -1, "10");
|
||||
fxt.Test_round("6", -2, "0");
|
||||
}
|
||||
}
|
||||
class Decimal_adp__fxt {
|
||||
public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
|
||||
public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
|
||||
public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
|
||||
public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse_(raw).To_str());}
|
||||
public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse_(expd).To_str(), Decimal_adp_.parse_(raw).Truncate().To_str());}
|
||||
public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
|
||||
public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
|
||||
public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
|
||||
public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse_(raw).Round(places).To_str(), "round");}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
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.core.net; import gplx.*; import gplx.core.*;
|
||||
public class Gfo_qarg_mgr {
|
||||
private final List_adp list = List_adp_.new_();
|
||||
private final Hash_adp hash = Hash_adp_bry.cs();
|
||||
public int Len() {return list.Count();}
|
||||
public boolean Match(byte[] key, byte[] val) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by(key);
|
||||
return arg == null ? false : Bry_.Eq(val, arg.Val_bry());
|
||||
}
|
||||
public Gfo_qarg_itm Get_at(int i) {return (Gfo_qarg_itm)list.Get_at(i);}
|
||||
public Gfo_qarg_itm Get_arg(byte[] key) {return (Gfo_qarg_itm)hash.Get_by(key);}
|
||||
public int Get_val_int_or(byte[] key, int or) {
|
||||
byte[] val_bry = Get_val_bry_or(key, null); if (val_bry == null) return or;
|
||||
return Bry_.To_int_or(val_bry, or);
|
||||
}
|
||||
public byte[] Get_val_bry_or(byte[] key, byte[] or) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by(key);
|
||||
return arg == null ? or : arg.Val_bry();
|
||||
}
|
||||
public String Get_val_str_or(byte[] key, String or) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by(key);
|
||||
return arg == null ? or : String_.new_u8(arg.Val_bry());
|
||||
}
|
||||
public void Set_val_by_int(byte[] key, int val) {Set_val_by_bry(key, Bry_.new_a7(Int_.Xto_str(val)));}
|
||||
public void Set_val_by_bry(byte[] key, byte[] val) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by(key);
|
||||
if (arg == null) {
|
||||
arg = new Gfo_qarg_itm(key, Bry_.Empty);
|
||||
list.Add(arg);
|
||||
hash.Add(key, arg);
|
||||
}
|
||||
arg.Val_bry_(val);
|
||||
}
|
||||
public Gfo_qarg_mgr Load(Gfo_qarg_itm[] ary) {
|
||||
hash.Clear();
|
||||
list.Clear();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_qarg_itm itm = ary[i];
|
||||
list.Add(itm);
|
||||
hash.Add_if_dupe_use_nth(itm.Key_bry(), itm);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Gfo_qarg_itm[] To_ary() {return (Gfo_qarg_itm[])list.To_ary(Gfo_qarg_itm.class);}
|
||||
public byte[] Concat(Bry_bfr bfr, byte[]... ary) {
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] key = ary[i];
|
||||
Gfo_qarg_itm itm = Get_arg(key); if (itm == null) continue;
|
||||
bfr.Add_byte(Byte_ascii.Amp).Add(itm.Key_bry()).Add_byte(Byte_ascii.Eq).Add(itm.Val_bry());
|
||||
}
|
||||
return bfr.Xto_bry_and_clear();
|
||||
}
|
||||
public byte[] To_bry() {
|
||||
int len = list.Count(); if (len == 0) return Bry_.Empty;
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
To_bry(bfr, gplx.xowa.Xoa_app_.Utl__encoder_mgr().Href(), false);
|
||||
return bfr.Xto_bry_and_clear();
|
||||
}
|
||||
public void To_bry(Bry_bfr bfr, Url_encoder href_encoder, boolean encode) {
|
||||
int len = list.Count(); if (len == 0) return;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_qarg_itm itm = (Gfo_qarg_itm)list.Get_at(i);
|
||||
bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
|
||||
Write_or_encode(bfr, href_encoder, encode, itm.Key_bry());
|
||||
bfr.Add_byte(Byte_ascii.Eq);
|
||||
Write_or_encode(bfr, href_encoder, encode, itm.Val_bry());
|
||||
}
|
||||
}
|
||||
public static void Concat_bfr(Bry_bfr bfr, Url_encoder href_encoder, Gfo_qarg_itm[] ary) {Concat_bfr(bfr, href_encoder, ary, true);}
|
||||
private static void Concat_bfr(Bry_bfr bfr, Url_encoder href_encoder, Gfo_qarg_itm[] ary, boolean encode) {
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
Gfo_qarg_itm itm = ary[i];
|
||||
bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
|
||||
Write_or_encode(bfr, href_encoder, encode, itm.Key_bry());
|
||||
bfr.Add_byte(Byte_ascii.Eq);
|
||||
Write_or_encode(bfr, href_encoder, encode, itm.Val_bry());
|
||||
}
|
||||
}
|
||||
private static void Write_or_encode(Bry_bfr bfr, Url_encoder href_encoder, boolean encode, byte[] bry) {
|
||||
if (bry == null) return; // NOTE: need null check b/c itm.Val_bry can be null
|
||||
if (encode)
|
||||
href_encoder.Encode(bfr, bry);
|
||||
else
|
||||
bfr.Add(bry);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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.core.net; import gplx.*; import gplx.core.*;
|
||||
public class Gfo_url {
|
||||
public byte[] Raw() {return raw;} private byte[] raw;
|
||||
public byte Protocol_tid() {return protocol_tid;} private byte protocol_tid;
|
||||
public byte[] Protocol_bry() {return protocol_bry;} private byte[] protocol_bry;
|
||||
public byte[] Anch() {return anch;} private byte[] anch;
|
||||
public Gfo_qarg_itm[] Qargs() {return qargs;} private Gfo_qarg_itm[] qargs;
|
||||
public byte[][] Segs() {return segs;} private byte[][] segs; private int segs__len;
|
||||
public byte[] Segs__get_at(int i) {return i < segs__len ? segs[i] : null;}
|
||||
public byte[] Segs__get_at_1st() {return segs__len > 0 ? segs[0] : null;}
|
||||
public byte[] Segs__get_at_nth() {return segs__len > 1 ? segs[segs__len - 1] : null;}
|
||||
public Gfo_url Ctor(byte[] raw, byte protocol_tid, byte[] protocol_bry, byte[][] segs, Gfo_qarg_itm[] qargs, byte[] anch) {
|
||||
this.raw = raw;
|
||||
this.protocol_tid = protocol_tid; this.protocol_bry = protocol_bry;
|
||||
this.segs = segs; this.segs__len = segs.length;
|
||||
this.qargs = qargs;
|
||||
this.anch = anch;
|
||||
return this;
|
||||
}
|
||||
public static final Gfo_url Empty = new Gfo_url().Ctor(Bry_.Empty, Gfo_protocol_itm.Tid_unknown, Bry_.Empty, Bry_.Ary_empty, null, null);
|
||||
}
|
@ -0,0 +1,261 @@
|
||||
/*
|
||||
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.core.net; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
public class Gfo_url_parser {
|
||||
private final Btrie_slim_mgr protocols = Btrie_slim_mgr.ci_a7(); // ASCII:url_protocol; EX:"http:", "ftp:", etc
|
||||
private final Bry_ary segs_ary = new Bry_ary(4), qargs = new Bry_ary(4);
|
||||
private final Url_encoder encoder = Url_encoder.new_html_href_mw_().Itms_raw_same_many(Byte_ascii.Underline);
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.reset_(500);
|
||||
public byte[] Relative_url_protocol_bry() {return Gfo_protocol_itm.Itm_https.Key_w_colon_bry();} // NOTE: https b/c any WMF wiki will now default to WMF; DATE:2015-07-26
|
||||
public Gfo_url_parser() {
|
||||
Init_protocols(Gfo_protocol_itm.Ary());
|
||||
Init_protocol_itm(Gfo_protocol_itm.Bry_relative, Gfo_protocol_itm.Tid_relative_1);
|
||||
Init_protocol_itm(Gfo_protocol_itm.Bry_file, Gfo_protocol_itm.Tid_file);
|
||||
Init_protocol_itm(gplx.xowa.parsers.lnkes.Xop_lnke_wkr.Bry_xowa_protocol, Gfo_protocol_itm.Tid_xowa);
|
||||
}
|
||||
private void Init_protocols(Gfo_protocol_itm... itms) {
|
||||
int len = itms.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_protocol_itm itm = itms[i];
|
||||
Init_protocol_itm(itm.Key_w_colon_bry(), itm.Tid());
|
||||
}
|
||||
}
|
||||
public void Init_protocol_itm(byte[] key, byte protocol_tid) {
|
||||
protocols.Add_bry_byte(key, protocol_tid);
|
||||
}
|
||||
public void Parse_site_fast(Gfo_url_site_data site_data, byte[] src, int src_bgn, int src_end) {
|
||||
int pos = src_bgn; boolean rel = false;
|
||||
if (pos + 1 < src_end && src[pos] == Byte_ascii.Slash && src[pos + 1] == Byte_ascii.Slash) { // starts with "//"
|
||||
pos += 2;
|
||||
rel = true;
|
||||
}
|
||||
if (!rel) { // search for ":"; NOTE: only search if not rel; i.e.: "//"
|
||||
int colon_pos = Bry_finder.Find_fwd(src, Byte_ascii.Colon, pos, src_end); // no colon found; EX: "//a.org/b"; "a.org/b"
|
||||
if (colon_pos != Bry_.NotFound) // colon found; EX: "http://" or "https://"
|
||||
pos = colon_pos + Int_.Const_dlm_len;
|
||||
if (pos < src_end && src[pos] == Byte_ascii.Slash) { // skip slash after colon
|
||||
pos += 1;
|
||||
if (pos < src_end && src[pos] == Byte_ascii.Slash) // skip 2nd slash after colon
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
int slash_pos = Bry_finder.Find_fwd(src, Byte_ascii.Slash, pos, src_end);
|
||||
if (slash_pos == Bry_.NotFound) // no terminating slash; EX: http://a.org
|
||||
slash_pos = src_end;
|
||||
slash_pos = Bry_.Trim_end_pos(src, slash_pos);
|
||||
site_data.Atrs_set(rel, pos, slash_pos);
|
||||
}
|
||||
private static final int Area__path = 1, Area__qarg_key_1st = 2, Area__qarg_key_nth = 3, Area__qarg_val = 4, Area__anch = 5;
|
||||
private byte[] src; int src_bgn, src_end;
|
||||
private int area;
|
||||
private boolean encoded;
|
||||
private byte protocol_tid; private byte[] protocol_bry, anch;
|
||||
private int path_bgn, qarg_key_bgn, qarg_val_bgn, anch_bgn, anch_nth_bgn;
|
||||
public Gfo_url Parse(byte[] src) {return Parse(new Gfo_url(), src, 0, src.length);}
|
||||
public Gfo_url Parse(Gfo_url rv, byte[] src, int src_bgn, int src_end) {
|
||||
this.src = src; this.src_bgn = src_bgn; this.src_end = src_end;
|
||||
encoded = false;
|
||||
protocol_tid = Gfo_protocol_itm.Tid_null;
|
||||
protocol_bry = anch = null;
|
||||
path_bgn = qarg_key_bgn = qarg_val_bgn = anch_bgn = anch_nth_bgn = -1;
|
||||
segs_ary.Clear(); qargs.Clear();
|
||||
|
||||
int pos = src_bgn;
|
||||
Object protocol_obj = protocols.Match_bgn(src, src_bgn, src_end);
|
||||
pos = protocols.Match_pos();
|
||||
pos = Bry_finder.Find_fwd_while(src, pos, src_end, Byte_ascii.Slash);
|
||||
if (protocol_obj == null) {
|
||||
this.protocol_tid = Gfo_protocol_itm.Tid_unknown;
|
||||
}
|
||||
else {
|
||||
this.protocol_tid = ((Byte_obj_val)protocol_obj).Val();
|
||||
this.protocol_bry = Make_bry(src_bgn, pos);
|
||||
}
|
||||
|
||||
area = Area__path;
|
||||
path_bgn = pos;
|
||||
while (true) {
|
||||
if (pos == src_end) break;
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Slash: pos = Parse_slash(pos, b); break;
|
||||
case Byte_ascii.Question: pos = Parse_qarg_key_1st(pos, b); break;
|
||||
case Byte_ascii.Amp: pos = Parse_qarg_key_nth(pos, b); break;
|
||||
case Byte_ascii.Eq: pos = Parse_qarg_val(pos, b); break;
|
||||
case Byte_ascii.Hash: pos = Parse_anch(pos, b); break;
|
||||
case Byte_ascii.Percent: encoded = true; ++pos; break;
|
||||
default:
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
End_area(pos, Byte_ascii.Null);
|
||||
rv.Ctor(src, protocol_tid, protocol_bry, segs_ary.To_ary(0), Make_qargs(), anch);
|
||||
return rv;
|
||||
}
|
||||
private int Parse_slash(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__path: return End_area(pos, b);
|
||||
default: return pos + 1;
|
||||
}
|
||||
}
|
||||
private int Parse_anch(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__path:
|
||||
End_area(pos, b);
|
||||
area = Area__anch;
|
||||
anch_bgn = pos + 1;
|
||||
break;
|
||||
case Area__anch: // handle double; A#B#C -> "A#B", "C"
|
||||
Append_to_last_path(Byte_ascii.Hash, Make_bry(anch_bgn, pos));
|
||||
anch_bgn = pos + 1;
|
||||
break;
|
||||
case Area__qarg_val:
|
||||
case Area__qarg_key_1st:
|
||||
case Area__qarg_key_nth:
|
||||
if (anch_nth_bgn == -1)
|
||||
anch_nth_bgn = Bry_finder.Find_bwd(src, Byte_ascii.Hash, src_end);
|
||||
if (pos == anch_nth_bgn) {
|
||||
End_area(pos, b);
|
||||
area = Area__anch;
|
||||
anch_bgn = pos + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
private int Parse_qarg_key_1st(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__path: // only valid way to start qarg; EX: A?B=C
|
||||
End_area(pos, b);
|
||||
area = Area__qarg_key_1st;
|
||||
qarg_key_bgn = pos + 1;
|
||||
break;
|
||||
case Area__qarg_key_1st: // handle dupe; EX: A?B?C
|
||||
case Area__qarg_key_nth: // handle dupe; EX: A?B=C&D?
|
||||
case Area__qarg_val: // handle dupe; EX: A?B=?
|
||||
End_area(pos, b);
|
||||
Append_to_last_path__qargs();
|
||||
area = Area__qarg_key_1st;
|
||||
qarg_key_bgn = pos + 1;
|
||||
break;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
private int Parse_qarg_key_nth(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__path: // ignore if qarg not started; EX: A&B
|
||||
break;
|
||||
case Area__qarg_key_1st: // handle invalid; A?B&C
|
||||
case Area__qarg_key_nth: // handle invalid; A?B=C&D&E=F
|
||||
End_area(pos, b);
|
||||
qargs.Add(null);
|
||||
area = Area__qarg_key_nth;
|
||||
qarg_key_bgn = pos + 1;
|
||||
break;
|
||||
case Area__qarg_val:
|
||||
End_area(pos, b);
|
||||
area = Area__qarg_key_nth;
|
||||
qarg_key_bgn = pos + 1;
|
||||
break;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
private int Parse_qarg_val(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__qarg_key_1st:
|
||||
case Area__qarg_key_nth:
|
||||
End_area(pos, b); break;
|
||||
default: break;
|
||||
}
|
||||
return pos + 1;
|
||||
}
|
||||
private int End_area(int pos, byte b) {
|
||||
switch (area) {
|
||||
case Area__path:
|
||||
segs_ary.Add(Make_bry(path_bgn, pos));
|
||||
path_bgn = pos + 1;
|
||||
break;
|
||||
case Area__qarg_key_1st:
|
||||
case Area__qarg_key_nth:
|
||||
if (b == Byte_ascii.Null && qargs.Len() == 0) // handle A?b but not A?b=c&d
|
||||
Append_to_last_path(Byte_ascii.Question, Make_bry(qarg_key_bgn, src_end));
|
||||
else {
|
||||
qargs.Add(Make_bry(qarg_key_bgn, pos));
|
||||
qarg_val_bgn = pos + 1;
|
||||
area = Area__qarg_val;
|
||||
}
|
||||
break;
|
||||
case Area__qarg_val:
|
||||
qargs.Add(Make_bry(qarg_val_bgn, pos));
|
||||
qarg_key_bgn = pos + 1;
|
||||
qarg_val_bgn = -1;
|
||||
area = Area__qarg_key_nth;
|
||||
break;
|
||||
case Area__anch:
|
||||
if (b == Byte_ascii.Null && anch_bgn == src_end) // handle A# but not "A#B"
|
||||
Append_to_last_path(Byte_ascii.Hash, Make_bry(anch_bgn, src_end));
|
||||
else
|
||||
anch = Make_bry(anch_bgn, pos);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
encoded = false;
|
||||
return pos + 1;
|
||||
}
|
||||
private byte[] Make_bry(int bgn, int end) {
|
||||
return encoded ? encoder.Decode(tmp_bfr, src, bgn, end) : Bry_.Mid(src, bgn, end);
|
||||
}
|
||||
private Gfo_qarg_itm[] Make_qargs() {
|
||||
int qargs_len = qargs.Len(); if (qargs_len == 0) return Gfo_qarg_itm.Ary_empty;
|
||||
if (qargs_len % 2 == 1) ++qargs_len; // handle odd qargs; EX: ?A=B&C&D=E
|
||||
Gfo_qarg_itm[] rv = new Gfo_qarg_itm[qargs_len / 2];
|
||||
for (int i = 0; i < qargs_len; i += 2) {
|
||||
byte[] key = qargs.Get_at(i);
|
||||
int val_idx = i + 1;
|
||||
byte[] val = val_idx < qargs_len ? qargs.Get_at(val_idx) : null;
|
||||
rv[i / 2] = new Gfo_qarg_itm(key, val);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private void Append_to_last_path(byte b, byte[] append) {
|
||||
byte[] last_path = segs_ary.Get_at_last(); if (last_path == null) return;
|
||||
last_path = Bry_.Add_w_dlm(b, last_path, append);
|
||||
segs_ary.Set_at_last(last_path);
|
||||
}
|
||||
private void Append_to_last_path__qargs() {
|
||||
byte[] last_path = segs_ary.Get_at_last(); if (last_path == null) return;
|
||||
tmp_bfr.Add(last_path);
|
||||
int len = qargs.Len();
|
||||
if (len % 2 == 1) qargs.Add(null); // handle odd qargs
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
tmp_bfr.Add_byte(i == 0 ? Byte_ascii.Question : Byte_ascii.Amp);
|
||||
tmp_bfr.Add(qargs.Get_at(i));
|
||||
byte[] qarg_val = qargs.Get_at(i + 1);
|
||||
if (qarg_val != null) // handle "null" added above
|
||||
tmp_bfr.Add_byte_eq().Add(qarg_val);
|
||||
}
|
||||
qargs.Clear();
|
||||
segs_ary.Set_at_last(tmp_bfr.Xto_bry_and_clear());
|
||||
}
|
||||
public static final byte[] Bry_double_slash = new byte[] {Byte_ascii.Slash, Byte_ascii.Slash};
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
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.core.net; import gplx.*; import gplx.core.*;
|
||||
class Gfo_url_parser_fxt {
|
||||
private final Gfo_url_parser parser = new Gfo_url_parser();
|
||||
private Gfo_url actl;
|
||||
public Gfo_url_parser_fxt Chk_protocol_tid(byte v) {Tfds.Eq_byte(v, actl.Protocol_tid(), "protocol_tid"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_protocol_bry(String v) {Tfds.Eq_str(v, actl.Protocol_bry(), "protocol_bry"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_site(String v) {Tfds.Eq_str(v, actl.Segs__get_at_1st(), "site"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_page(String v) {Tfds.Eq_str(v, actl.Segs__get_at_nth(), "page"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_anch(String v) {Tfds.Eq_str(v, actl.Anch(), "anch"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_segs(String... ary) {Tfds.Eq_int(ary.length, actl.Segs().length, "segs_len"); Tfds.Eq_str_lines(String_.Concat_lines_nl(ary), String_.Concat_lines_nl(String_.Ary(actl.Segs())), "segs"); return this;}
|
||||
public Gfo_url_parser_fxt Chk_qargs(String... ary) {Tfds.Eq_str_lines(String_.To_str__as_kv_ary(ary), Gfo_qarg_itm.To_str(actl.Qargs()), "qargs"); return this;}
|
||||
public Gfo_url_parser_fxt Run_parse(String v) {
|
||||
this.actl = parser.Parse(Bry_.new_u8(v));
|
||||
return this;
|
||||
}
|
||||
public void Test_Parse_site_fast(String raw, String expd) {
|
||||
byte[] raw_bry = Bry_.new_u8(raw);
|
||||
parser.Parse_site_fast(site_data, raw_bry, 0, raw_bry.length);
|
||||
String actl = String_.new_u8(raw_bry, site_data.Site_bgn(), site_data.Site_end());
|
||||
Tfds.Eq(expd, actl);
|
||||
} private final Gfo_url_site_data site_data = new Gfo_url_site_data();
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
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.core.net; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*;
|
||||
public class Gfo_url_parser_tst {
|
||||
private final Gfo_url_parser_fxt tstr = new Gfo_url_parser_fxt();
|
||||
@Test public void Protocol__relative() {
|
||||
tstr.Run_parse("//en.wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_relative_1).Chk_protocol_bry("//").Chk_site("en.wikipedia.org");
|
||||
}
|
||||
@Test public void Protocol__none() {
|
||||
tstr.Run_parse("en.wikipedia.org/wiki/A").Chk_protocol_tid(Gfo_protocol_itm.Tid_unknown).Chk_segs("en.wikipedia.org", "wiki", "A");
|
||||
}
|
||||
@Test public void Site__parts__3() {
|
||||
tstr.Run_parse("https://en.wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_protocol_bry("https://").Chk_segs("en.wikipedia.org");
|
||||
}
|
||||
@Test public void Site__parts__2() {
|
||||
tstr.Run_parse("https://wikipedia.org").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_segs("wikipedia.org");
|
||||
}
|
||||
@Test public void Site__parts__1() {
|
||||
tstr.Run_parse("https://wikipedia").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_segs("wikipedia");
|
||||
}
|
||||
@Test public void Site__slash__none() {
|
||||
tstr.Run_parse("https:site").Chk_protocol_tid(Gfo_protocol_itm.Tid_https).Chk_site("site");
|
||||
}
|
||||
@Test public void Paths__1() {
|
||||
tstr.Run_parse("https://site/A").Chk_segs("site", "A");
|
||||
}
|
||||
@Test public void Paths__2() {
|
||||
tstr.Run_parse("https://site/wiki/A").Chk_segs("site", "wiki", "A");
|
||||
}
|
||||
@Test public void Paths__n() {
|
||||
tstr.Run_parse("https://site/wiki/A/B/C/D").Chk_segs("site", "wiki", "A", "B", "C", "D");
|
||||
}
|
||||
@Test public void Qargs__1() {
|
||||
tstr.Run_parse("https://site/A?B=C").Chk_page("A").Chk_qargs("B", "C");
|
||||
}
|
||||
@Test public void Qargs__2() {
|
||||
tstr.Run_parse("https://site/A?B=C&D=E").Chk_page("A").Chk_qargs("B", "C", "D", "E");
|
||||
}
|
||||
@Test public void Qargs__3() {
|
||||
tstr.Run_parse("https://site/A?B=C&D=E&F=G").Chk_page("A").Chk_qargs("B", "C", "D", "E", "F", "G");
|
||||
}
|
||||
@Test public void Qargs__ques__dupe__ques() {
|
||||
tstr.Run_parse("https://site/A?B?Y=Z").Chk_page("A?B").Chk_qargs("Y", "Z");
|
||||
}
|
||||
@Test public void Qargs__ques__dupe__amp() {
|
||||
tstr.Run_parse("https://site/A?B=C&D?Y=Z").Chk_page("A?B=C&D").Chk_qargs("Y", "Z");
|
||||
}
|
||||
@Test public void Qargs__ques__dupe__eq() {
|
||||
tstr.Run_parse("https://site/A?B=C?Y=Z").Chk_page("A?B=C").Chk_qargs("Y", "Z");
|
||||
}
|
||||
@Test public void Qargs__amp__dupe__ques() {
|
||||
tstr.Run_parse("https://site/A?B&Y=Z").Chk_page("A").Chk_qargs("B", null, "Y", "Z");
|
||||
}
|
||||
@Test public void Qargs__amp__dupe__amp() {
|
||||
tstr.Run_parse("https://site/A?B=C&D&Y=Z").Chk_page("A").Chk_qargs("B", "C", "D", null, "Y", "Z");
|
||||
}
|
||||
@Test public void Qargs__missing_val__0() {
|
||||
tstr.Run_parse("https://site/A?").Chk_page("A?").Chk_qargs();
|
||||
}
|
||||
@Test public void Qargs__missing_val__2() {
|
||||
tstr.Run_parse("https://site/A?B=C&D&F=G").Chk_page("A").Chk_qargs("B", "C", "D", null, "F", "G");
|
||||
}
|
||||
@Test public void Qargs__missing_val__n() {
|
||||
tstr.Run_parse("https://site/A?B=C&D=E&F").Chk_page("A").Chk_qargs("B", "C", "D", "E", "F", null);
|
||||
}
|
||||
@Test public void Qargs__site_less__missing__0() {
|
||||
tstr.Run_parse("A?B").Chk_segs("A?B").Chk_qargs();
|
||||
}
|
||||
@Test public void Qargs__site_less() {
|
||||
tstr.Run_parse("A?B=C&D=E").Chk_site("A").Chk_qargs("B", "C", "D", "E");
|
||||
}
|
||||
@Test public void Anch__basic() {
|
||||
tstr.Run_parse("https://site/A#B").Chk_page("A").Chk_anch("B");
|
||||
}
|
||||
@Test public void Anch__repeat__2() {
|
||||
tstr.Run_parse("https://site/A#B#C").Chk_page("A#B").Chk_anch("C");
|
||||
}
|
||||
@Test public void Anch__repeat__3() {
|
||||
tstr.Run_parse("https://site/A#B#C#D").Chk_page("A#B#C").Chk_anch("D");
|
||||
}
|
||||
@Test public void Anch__missing() {
|
||||
tstr.Run_parse("https://site/A#").Chk_page("A#").Chk_anch(null);
|
||||
}
|
||||
@Test public void Anch__missing__eos() {
|
||||
tstr.Run_parse("https://site/A#B#").Chk_page("A#B#").Chk_anch(null);
|
||||
}
|
||||
@Test public void Anch__qargs__basic() {
|
||||
tstr.Run_parse("https://site/A?B=C&D=E#F").Chk_page("A").Chk_qargs("B", "C", "D", "E").Chk_anch("F");
|
||||
}
|
||||
@Test public void Anch__qargs__repeat() {
|
||||
tstr.Run_parse("https://site/A?B=C#&D=E#F").Chk_page("A").Chk_qargs("B", "C#", "D", "E").Chk_anch("F");
|
||||
}
|
||||
@Test public void Anch__site_less() {
|
||||
tstr.Run_parse("A#B").Chk_site("A").Chk_anch("B");
|
||||
}
|
||||
@Test public void Encode__page() {
|
||||
tstr.Run_parse("http://site/A%27s").Chk_site("site").Chk_page("A's");
|
||||
}
|
||||
@Test public void Protocol_less__qargs() {
|
||||
tstr.Run_parse("Special:Search/Earth?fulltext=yes").Chk_segs("Special:Search", "Earth").Chk_page("Earth").Chk_qargs("fulltext", "yes");
|
||||
}
|
||||
@Test public void Parse_site_fast() {
|
||||
tstr.Test_Parse_site_fast("http://a.org/B" , "a.org");
|
||||
tstr.Test_Parse_site_fast("http://a.org" , "a.org");
|
||||
tstr.Test_Parse_site_fast("//a.org/B" , "a.org");
|
||||
tstr.Test_Parse_site_fast("//a.org/B:C" , "a.org");
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
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.xowa; import gplx.*;
|
||||
import gplx.core.net.*; import gplx.xowa.urls.*;
|
||||
import gplx.xowa.html.hrefs.*;
|
||||
public class Xoa_url {
|
||||
public int Tid() {return tid;} private int tid;
|
||||
public byte[] Raw() {return raw;} private byte[] raw = Bry_.Empty;
|
||||
public byte[] Wiki_bry() {return wiki_bry;} public Xoa_url Wiki_bry_(byte[] v) {wiki_bry = v; return this;} private byte[] wiki_bry;
|
||||
public byte[] Page_bry() {return page_bry;} public Xoa_url Page_bry_(byte[] v) {page_bry = v; return this;} private byte[] page_bry;
|
||||
public byte[] Anch_bry() {return anch_bry;} public Xoa_url Anch_bry_(byte[] v) {anch_bry = v; return this;} private byte[] anch_bry;
|
||||
public String Anch_str() {return anch_bry == null ? null : String_.new_u8(anch_bry);}
|
||||
public byte[][] Segs_ary() {return segs_ary;} private byte[][] segs_ary;
|
||||
public Gfo_qarg_itm[] Qargs_ary() {return qargs_ary;} public Xoa_url Qargs_ary_(Gfo_qarg_itm[] v) {qargs_ary = v; return this;} private Gfo_qarg_itm[] qargs_ary = Gfo_qarg_itm.Ary_empty;
|
||||
public Gfo_qarg_mgr Qargs_mgr() {if (qargs_mgr == null) qargs_mgr = new Gfo_qarg_mgr().Load(qargs_ary); return qargs_mgr;} private Gfo_qarg_mgr qargs_mgr;
|
||||
public byte Protocol_tid() {return protocol_tid;} private byte protocol_tid;
|
||||
public byte[] Protocol_bry() {return protocol_bry;} private byte[] protocol_bry;
|
||||
public boolean Protocol_is_relative() {return protocol_is_relative;} private boolean protocol_is_relative;
|
||||
public byte[] Vnt_bry() {return vnt_bry;} private byte[] vnt_bry;
|
||||
public boolean Wiki_is_missing() {return wiki_is_missing;} private boolean wiki_is_missing;
|
||||
public boolean Wiki_is_same() {return wiki_is_same;} private boolean wiki_is_same;
|
||||
public boolean Page_is_main() {return page_is_main;} private boolean page_is_main;
|
||||
public Xoa_url Ctor(int tid, byte[] raw, byte protocol_tid, byte[] protocol_bry, boolean protocol_is_relative
|
||||
, byte[] wiki, byte[] page, Gfo_qarg_itm[] qargs, byte[] anch
|
||||
, byte[][] segs_ary, byte[] vnt_bry, boolean wiki_is_missing, boolean wiki_is_same, boolean page_is_main) {
|
||||
this.tid = tid; this.raw = raw;
|
||||
this.protocol_tid = protocol_tid; this.protocol_bry = protocol_bry; this.protocol_is_relative = protocol_is_relative;
|
||||
this.wiki_bry = wiki; this.page_bry = page; this.qargs_ary = qargs; this.anch_bry = anch;
|
||||
this.segs_ary = segs_ary; this.vnt_bry = vnt_bry;
|
||||
this.wiki_is_missing = wiki_is_missing; this.wiki_is_same = wiki_is_same; this.page_is_main = page_is_main;
|
||||
return this;
|
||||
}
|
||||
public byte[] Page_for_lnki() {
|
||||
int raw_len = raw.length;
|
||||
int page_bgn = Page_bgn(raw_len);
|
||||
if (page_bgn == Bry_.NotFound) // no /wiki/ found; return page
|
||||
return page_bry == null ? Bry_.Empty : page_bry; // guard against null ref
|
||||
else
|
||||
return Bry_.Mid(raw, page_bgn, raw_len);// else take everything after "/wiki/";
|
||||
}
|
||||
private int Page_bgn(int raw_len) {
|
||||
int wiki_pos = Bry_finder.Find_fwd(raw, Xoh_href_.Bry__wiki, 0, raw_len); // look for /wiki/
|
||||
return wiki_pos == Bry_.NotFound ? Bry_.NotFound : wiki_pos + Xoh_href_.Bry__wiki.length;
|
||||
}
|
||||
public boolean Eq_page(Xoa_url comp) {return Bry_.Eq(wiki_bry, comp.wiki_bry) && Bry_.Eq(page_bry, comp.page_bry) && this.Qargs_mgr().Match(Xoa_url_.Qarg__redirect, Xoa_url_.Qarg__redirect__yes) == comp.Qargs_mgr().Match(Xoa_url_.Qarg__redirect, Xoa_url_.Qarg__redirect__yes);}
|
||||
public String To_str() {return String_.new_u8(To_bry(Bool_.Y, Bool_.Y));}
|
||||
public byte[] To_bry_page_w_anch() {
|
||||
byte[] page = page_bry, anch = anch_bry;
|
||||
byte[] anch_spr = anch == null ? null : Byte_ascii.Hash_bry;
|
||||
return Bry_.Add(page, anch_spr, anch);
|
||||
}
|
||||
public byte[] To_bry_full_wo_qargs() {return To_bry(Bool_.Y, Bool_.N);}
|
||||
public byte[] To_bry(boolean full, boolean show_qargs) { // currently used for status bar; not embedded in any html
|
||||
switch (tid) {
|
||||
case Xoa_url_.Tid_unknown: // unknown; should not occur?
|
||||
return Bry_.Len_eq_0(raw) ? Bry_.Add(wiki_bry, Byte_ascii.Slash_bry, page_bry) : raw; // raw is empty when using new_();
|
||||
case Xoa_url_.Tid_inet: // protocol; embed all; EX: "http://a.org/A"; "file:///C/dir/file.txt"
|
||||
case Xoa_url_.Tid_file: // file; EX: "file:///C:/A/B.jpg"
|
||||
return raw;
|
||||
case Xoa_url_.Tid_xcmd: // xcmd; embed page only; EX: "xowa.usr.bookmarks.add"
|
||||
return page_bry;
|
||||
default:
|
||||
throw Err_.new_unhandled(tid);
|
||||
case Xoa_url_.Tid_anch:
|
||||
case Xoa_url_.Tid_page:
|
||||
break;
|
||||
}
|
||||
byte[] wiki = wiki_bry, page = page_bry, anch = anch_bry;
|
||||
byte[] wiki_spr = vnt_bry == null ? Xoh_href_.Bry__wiki : Bry_.Add(Byte_ascii.Slash_bry, vnt_bry, Byte_ascii.Slash_bry);
|
||||
byte[] anch_spr = anch == null ? null : Byte_ascii.Hash_bry;
|
||||
if (!full) {
|
||||
boolean tid_is_anch = tid == Xoa_url_.Tid_anch;
|
||||
if ( wiki_is_same // same wiki; don't show wiki; EX: "/wiki/A" -> "A" x> "en.wikipedia.org/wiki/A"
|
||||
|| tid_is_anch) { // anch never shows wiki; EX: #A
|
||||
wiki = wiki_spr = null; // don't show wiki;
|
||||
}
|
||||
if (tid_is_anch)
|
||||
page = null;
|
||||
}
|
||||
byte[] rv = Bry_.Add
|
||||
( wiki, wiki_spr // add wiki_key; EX: "en.wikipedia.org", "/wiki/"
|
||||
, page // add page; EX: "A"
|
||||
, anch_spr, anch // add anch EX: "#", "B"
|
||||
);
|
||||
if (show_qargs || qargs_ary.length > 0) {
|
||||
Bry_bfr bfr = Xoa_app_.Utl__bfr_mkr().Get_b128();
|
||||
bfr.Add(rv);
|
||||
Gfo_qarg_mgr.Concat_bfr(bfr, Xoa_app_.Utl__encoder_mgr().Href(), qargs_ary);
|
||||
return bfr.To_bry_and_rls();
|
||||
}
|
||||
else
|
||||
return rv;
|
||||
}
|
||||
public static final Xoa_url Null = null;
|
||||
public static Xoa_url blank() {return new Xoa_url();}
|
||||
public static Xoa_url new_(byte[] wiki, byte[] page) {
|
||||
Xoa_url rv = new Xoa_url();
|
||||
rv.Wiki_bry_(wiki);
|
||||
rv.Page_bry_(page);
|
||||
rv.tid = Xoa_url_.Tid_page;
|
||||
return rv;
|
||||
} Xoa_url() {}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
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.xowa; import gplx.*;
|
||||
public class Xoa_url_ {
|
||||
public static final int Tid_unknown = 0, Tid_page = 1, Tid_anch = 2, Tid_inet = 3, Tid_file = 4, Tid_xcmd = 5;
|
||||
public static boolean Tid_is_pagelike(int tid) {
|
||||
switch (tid) {
|
||||
case Tid_page: case Tid_anch: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static final byte[]
|
||||
Qarg__redirect = Bry_.new_a7("redirect")
|
||||
, Qarg__redirect__yes = Bry_.new_a7("yes")
|
||||
, Qarg__action = Bry_.new_a7("action")
|
||||
, Qarg__action__edit = Bry_.new_a7("edit")
|
||||
;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
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.xowa.apis.xowa; import gplx.*; import gplx.xowa.*; import gplx.xowa.apis.*;
|
||||
import gplx.xowa.apis.xowa.wikis.*;
|
||||
public class Xoapi_app_wiki implements GfoInvkAble {
|
||||
public Xoapi_wiki_lang Lang() {return lang;} private final Xoapi_wiki_lang lang = new Xoapi_wiki_lang();
|
||||
public void Subscribe(GfoEvObj sub) {lang.Subscribe(sub);}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_lang)) return lang;
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
}
|
||||
private static final String Invk_lang = "lang";
|
||||
public static final Xoapi_app_wiki Dflt = new Xoapi_app_wiki();
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
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.xowa.apis.xowa; import gplx.*; import gplx.xowa.*; import gplx.xowa.apis.*;
|
||||
public class Xoapi_app_wikis implements GfoInvkAble {
|
||||
private final Ordered_hash hash = Ordered_hash_.new_bry_();
|
||||
public Xoapi_app_wiki Get(byte[] domain) {
|
||||
Xoapi_app_wiki rv = (Xoapi_app_wiki)hash.Get_by(domain);
|
||||
if (rv == null) {
|
||||
rv = new Xoapi_app_wiki();
|
||||
hash.Add(domain, rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_get)) return Get(m.ReadBry("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
}
|
||||
private static final String Invk_get = "get";
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.xowa.apis.xowa.wikis; import gplx.*; import gplx.xowa.*; import gplx.xowa.apis.*; import gplx.xowa.apis.xowa.*;
|
||||
import gplx.xowa.apis.xowa.wikis.langs.*;
|
||||
public class Xoapi_wiki_lang implements GfoInvkAble {
|
||||
public Xoap_lang_variants Variants() {return variants;} private final Xoap_lang_variants variants = new Xoap_lang_variants();
|
||||
public void Subscribe(GfoEvObj sub) {variants.Subscribe(sub);}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_variants)) return variants;
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
}
|
||||
private static final String Invk_variants = "variants";
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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.xowa.apis.xowa.wikis.langs; import gplx.*; import gplx.xowa.*; import gplx.xowa.apis.*; import gplx.xowa.apis.xowa.*; import gplx.xowa.apis.xowa.wikis.*;
|
||||
public class Xoap_lang_variants implements GfoInvkAble, GfoEvMgrOwner {
|
||||
public Xoap_lang_variants() {
|
||||
this.ev_mgr = GfoEvMgr.new_(this);
|
||||
}
|
||||
public GfoEvMgr EvMgr() {return ev_mgr;} private final GfoEvMgr ev_mgr;
|
||||
public byte[] Current() {return current;} private byte[] current;
|
||||
public void Current_(byte[] v) {
|
||||
this.current = v;
|
||||
GfoEvMgr_.PubVal(this, Evt_current_changed, v);
|
||||
}
|
||||
public void Subscribe(GfoEvObj sub) {
|
||||
GfoEvMgr_.SubSame(this, Evt_current_changed, sub);
|
||||
if (current != null) GfoInvkAble_.InvkCmd_val(sub, Evt_current_changed, current);
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_current)) return String_.new_u8(current);
|
||||
else if (ctx.Match(k, Invk_current_)) Current_(m.ReadBry("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk_current = "current", Invk_current_ = "current_";
|
||||
public static final String
|
||||
Evt_current_changed = "current_changed"
|
||||
;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue