1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
/*
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.brys; import gplx.*; import gplx.core.*;
public class Bit_ {
public static String XtoBitStr(int val) {
boolean[] bits = new boolean[8];
int idx = 7;
while (val > 0) {
if ((val & 1) == 1) bits[idx] = true;
idx--;
val >>= 1;
}
byte[] rv = new byte[8];
for (int i = 0; i < 8; i++)
rv[i] = bits[i] ? Byte_ascii.Num_1 : Byte_ascii.Num_0;
return String_.new_a7(rv);
}
public static int[] Bld_pow_ary(int... seg_ary) {
int seg_ary_len = seg_ary.length;
int pow = 0;
int[] rv = new int[seg_ary_len];
for (int i = seg_ary_len - 1; i > -1; i--) {
rv[i] = Base2_ary[pow];
pow += seg_ary[i];
}
return rv;
}
public static int Xto_int(int[] pow_ary, int[] val_ary) {
int pow_ary_last = pow_ary.length - 1;
int val = 0;
for (int i = pow_ary_last; i > -1; i--)
val += pow_ary[i] * val_ary[i];
return val;
}
public static int[] Xto_intAry(int[] pow_ary, int v) {
int[] rv = new int[pow_ary.length];
Xto_intAry(rv, pow_ary, v);
return rv;
}
public static void Xto_intAry(int[] rv, int[] pow_ary, int v) {
int pow_ary_len = pow_ary.length;
int rv_len = rv.length;
for (int i = 0; i < pow_ary_len; i++) {
if (i >= rv_len) break;
rv[i] = v / pow_ary[i];
int factor = pow_ary[i] * rv[i];
v = factor == 0 ? v : (v % factor); // NOTE: if 0, do not do modulus or else div by zero
}
}
public static byte Xto_byte(byte[] pow_ary, byte... val_ary) {
int pow_ary_last = pow_ary.length - 1;
int val = 0;
for (int i = pow_ary_last; i > -1; --i)
val += pow_ary[i] * val_ary[i];
return (byte)val;
}
public static void Xto_bry(byte[] rv, byte[] pow_ary, byte val) {
int pow_ary_len = pow_ary.length;
int rv_len = rv.length;
for (int i = 0; i < pow_ary_len; i++) {
if (i >= rv_len) break;
rv[i] = (byte)(val / pow_ary[i]);
int factor = pow_ary[i] * rv[i];
val = (byte)(factor == 0 ? val : (val % factor)); // NOTE: if 0, do not do modulus or else div by zero
}
}
public static int Shift_lhs(int val, int shift) {return val << shift;}
public static int Shift_rhs(int val, int shift) {return val >> shift;}
public static int Shift_lhs_to_int(int[] shift_ary, int... val_ary) {
int val_len = val_ary.length; if (val_len > shift_ary.length) throw Exc_.new_("vals must be less than shifts", "vals", val_len, "shifts", shift_ary.length);
int rv = 0;
for (int i = 0; i < val_len; ++i) {
int val = val_ary[i];
int shift = shift_ary[i];
rv += val << shift;
}
return rv;
}
public static void Shift_rhs_to_ary(int[] rv, int[] shift_ary, int val) {
int shift_len = shift_ary.length;
for (int i = shift_len - 1; i > - 1; --i) {
int shift = shift_ary[i];
int itm = val >> shift;
rv[i] = itm;
val -= (itm << shift);
}
}
public static int Xto_int_date_short(int[] val_ary) {
val_ary[0] -= 1900;
return Xto_int(Pow_ary_date_short, val_ary);
}
public static void Xto_date_short_int_ary(int[] rv, int v) {
Xto_intAry(rv, Pow_ary_date_short, v);
rv[0] += 1900;
}
public static DateAdp Xto_date_short(int v) {
int[] rv = new int[Pow_ary_date_short.length];
Xto_date_short_int_ary(rv, v);
return DateAdp_.seg_(rv);
}
private static final int[] Pow_ary_date_short = new int[] {1048576, 65536, 2048, 64, 1}; // yndhm -> 12,4,5,5,6
private static final int[] Base2_ary = new int[]
{ 1, 2, 4, 8, 16, 32, 64, 128
, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608
, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 0
};
}

View File

@@ -0,0 +1,109 @@
/*
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.brys; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Bit__tst {
@Before public void init() {fxt.Clear();} private Bit__fxt fxt = new Bit__fxt();
@Test public void XtoBitStr() {
tst_XtoBitStr( 0, "00000000");
tst_XtoBitStr( 1, "00000001");
tst_XtoBitStr( 2, "00000010");
tst_XtoBitStr( 3, "00000011");
tst_XtoBitStr(255, "11111111");
} void tst_XtoBitStr(int val, String expd) {Tfds.Eq(expd, Bit_.XtoBitStr(val));}
@Test public void Bld_pow_ary() {
tst_Bld_pow_ary(ary_(1, 1, 1, 1), ary_(8, 4, 2, 1));
tst_Bld_pow_ary(ary_(3, 2) , ary_(4, 1));
} void tst_Bld_pow_ary(int[] seg_ary, int[] expd) {Tfds.Eq_ary_str(expd, Bit_.Bld_pow_ary(seg_ary));}
@Test public void Xto_int() {
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(1, 1, 1, 1), 15);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(0, 0, 0, 0), 0);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(1, 0, 0, 1), 9);
tst_Xto_int(ary_(1, 1, 1, 1) , ary_(0, 1, 1, 0), 6);
tst_Xto_int(ary_(3, 2) , ary_(7, 3) , 31);
tst_Xto_int(ary_(3, 2, 1) , ary_(7, 3, 1) , 63);
tst_Xto_int(ary_(11, 4, 5, 5, 6), ary_(2012, 6, 3, 23, 17), 2110135761);
tst_Xto_int(ary_(11, 4, 5, 5, 6), ary_(2012, 6, 3, 23, 18), 2110135762);
}
private void tst_Xto_int(int[] seg_ary, int[] val_ary, int expd) {
int[] pow_ary = Bit_.Bld_pow_ary(seg_ary);
Tfds.Eq(expd, Bit_.Xto_int(pow_ary, val_ary));
}
@Test public void Xto_intAry() {
tst_Xto_intAry(ary_(1, 1, 1, 1) , 15, ary_(1, 1, 1, 1));
tst_Xto_intAry(ary_(3, 2) , 31, ary_(7, 3));
tst_Xto_intAry(ary_(3, 2, 1) , 63, ary_(7, 3, 1));
tst_Xto_intAry(ary_(12, 4, 5, 5, 6), 2110135761, ary_(2012, 6, 3, 23, 17));
tst_Xto_intAry(ary_(12, 4, 5, 5, 6), 2110135762, ary_(2012, 6, 3, 23, 18));
}
private void tst_Xto_intAry(int[] seg_ary, int val, int[] expd) {
int[] pow_ary = Bit_.Bld_pow_ary(seg_ary);
Tfds.Eq_ary_str(expd, Bit_.Xto_intAry(pow_ary, val));
}
int[] ary_(int... v) {return v;}
@Test public void Xto_int_date_short() {
tst_Xto_int_date_short("20120604 2359", 117843451);
tst_Xto_int_date_short("20120604 2358", 117843450);
tst_Xto_int_date_short("20120605 0000", 117843968);
}
private void tst_Xto_int_date_short(String date_str, int expd) {
DateAdp date = DateAdp_.parse_fmt(date_str, "yyyyMMdd HHmm");
int date_int = Bit_.Xto_int_date_short(date.XtoSegAry());
Tfds.Eq(expd, date_int);
Tfds.Eq(date_str, Bit_.Xto_date_short(date_int).XtoStr_fmt("yyyyMMdd HHmm"));
}
@Test public void Shift_lhs() {// simple: shift 1 bit
fxt.Test_shift_lhs(1, 1, 2);
fxt.Test_shift_lhs(2, 1, 4);
fxt.Test_shift_lhs(3, 1, 6);
fxt.Test_shift_lhs(4, 1, 8);
}
@Test public void Shift_rhs() {
fxt.Test_shift_rhs(2, 1, 1);
fxt.Test_shift_rhs(4, 1, 2);
fxt.Test_shift_rhs(6, 1, 3);
fxt.Test_shift_rhs(8, 1, 4);
}
@Test public void Shift_lhs_to_int() {
int[] shift_ary = Int_.Ary(0, 3, 5);
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 0, 0), 0);
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(7, 0, 0), 7); // 1st 3 bits
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 3, 0), 24); // 2nd 2 bits
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(0, 0, 1), 32); // 3rd 1 bit
fxt.Test_shift_lhs_to_int(shift_ary, Int_.Ary(7, 3, 1), 63); // many bits
}
@Test public void Shift_rhs_to_ary() {
int[] shift_ary = Int_.Ary(0, 3, 5);
fxt.Test_shift_rhs_to_ary(shift_ary, 0, Int_.Ary(0, 0, 0));
fxt.Test_shift_rhs_to_ary(shift_ary, 7, Int_.Ary(7, 0, 0)); // 1st 3 bits
fxt.Test_shift_rhs_to_ary(shift_ary, 24, Int_.Ary(0, 3, 0)); // 2nd 2 bits
fxt.Test_shift_rhs_to_ary(shift_ary, 32, Int_.Ary(0, 0, 1)); // 3rd 1 bit
fxt.Test_shift_rhs_to_ary(shift_ary, 63, Int_.Ary(7, 3, 1)); // many bits
}
}
class Bit__fxt {
public void Clear() {}
public void Test_shift_lhs(int val, int shift, int expd) {Tfds.Eq(expd, Bit_.Shift_lhs(val, shift));}
public void Test_shift_rhs(int val, int shift, int expd) {Tfds.Eq(expd, Bit_.Shift_rhs(val, shift));}
public void Test_shift_lhs_to_int(int[] shift_ary, int[] val_ary, int expd) {Tfds.Eq(expd, Bit_.Shift_lhs_to_int(shift_ary, val_ary));}
public void Test_shift_rhs_to_ary(int[] shift_ary, int val, int[] expd_ary) {
int[] actl_ary = Int_.Ary(0, 0, 0);
Bit_.Shift_rhs_to_ary(actl_ary, shift_ary, val);
Tfds.Eq_ary(expd_ary, actl_ary);
}
}

View File

@@ -0,0 +1,40 @@
/*
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.brys; import gplx.*; import gplx.core.*;
public class Bry_bldr {
public byte[] Val() {return val;} private byte[] val;
public Bry_bldr New_256() {return New(256);}
public Bry_bldr New(int len) {val = new byte[len]; return this;}
public Bry_bldr Set_rng_ws(byte v) {return Set_many(v, Byte_ascii.Space, Byte_ascii.Tab, Byte_ascii.Nl, Byte_ascii.Cr);}
public Bry_bldr Set_rng_xml_identifier(byte v) {return Set_rng_alpha_lc(v).Set_rng_alpha_uc(v).Set_rng_num(v).Set_many(v, Byte_ascii.Underline, Byte_ascii.Dash);}
public Bry_bldr Set_rng_alpha(byte v) {return Set_rng_alpha_lc(v).Set_rng_alpha_uc(v);}
public Bry_bldr Set_rng_alpha_lc(byte v) {return Set_rng(v, Byte_ascii.Ltr_a, Byte_ascii.Ltr_z);}
public Bry_bldr Set_rng_alpha_uc(byte v) {return Set_rng(v, Byte_ascii.Ltr_A, Byte_ascii.Ltr_Z);}
public Bry_bldr Set_rng_num(byte v) {return Set_rng(v, Byte_ascii.Num_0, Byte_ascii.Num_9);}
public Bry_bldr Set_rng(byte v, int bgn, int end) {
for (int i = bgn; i <= end; i++)
val[i] = v;
return this;
}
public Bry_bldr Set_many(byte v, int... ary) {
int len = ary.length;
for (int i = 0; i < len; i++)
val[ary[i]] = v;
return this;
}
}

View File

@@ -0,0 +1,26 @@
/*
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.brys; import gplx.*; import gplx.core.*;
import gplx.lists.*;
public class Bry_comparer implements ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
byte[] lhs = (byte[])lhsObj, rhs = (byte[])rhsObj;
return Bry_.Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
}
public static final Bry_comparer _ = new Bry_comparer(); Bry_comparer() {}
}

View File

@@ -0,0 +1,56 @@
/*
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.brys; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Bry_rdr_tst {
@Before public void init() {fxt.Clear();} private Bry_rdr_fxt fxt = new Bry_rdr_fxt();
@Test public void Int() {
fxt.Init_src("12|3456|789");
fxt.Test_read_int(12);
fxt.Test_read_int(3456);
fxt.Test_read_int(789);
fxt.Test_read_int(Int_.MinValue);
}
@Test public void Int_negative() {
fxt.Init_src("-1|-2");
fxt.Test_read_int(-1);
fxt.Test_read_int(-2);
}
@Test public void Bry() {
fxt.Init_src("abc|d||ef");
fxt.Test_read_bry("abc");
fxt.Test_read_bry("d");
fxt.Test_read_bry("");
fxt.Test_read_bry("ef");
fxt.Test_read_bry(null);
}
}
class Bry_rdr_fxt {
private Bry_rdr rdr;
public void Clear() {rdr = new Bry_rdr();}
public Bry_rdr_fxt Init_src(String v) {rdr.Init(Bry_.new_u8(v)); return this;}
public Bry_rdr_fxt Init_pos(int v) {rdr.Pos_(v); return this;}
public void Test_read_int(int expd_val) {
Tfds.Eq(expd_val, rdr.Read_int_to_pipe());
}
public void Test_read_bry(String expd_str) {
byte[] actl_bry = rdr.Read_bry_to_pipe();
String actl_str = actl_bry == null ? null : String_.new_u8(actl_bry);
Tfds.Eq(expd_str, actl_str);
}
}

View File

@@ -0,0 +1,96 @@
/*
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.btries; import gplx.*; import gplx.core.*;
import org.junit.*;
import gplx.xowa.langs.cases.*;
public class Btrie_utf8_mgr_tst {
@Before public void init() {fxt.Clear();} private Btrie_utf8_mgr_fxt fxt = new Btrie_utf8_mgr_fxt();
@Test public void Ascii() {
fxt.Init_add(Bry_.new_a7("a") , "1");
fxt.Init_add(Bry_.new_a7("abc") , "123");
fxt.Test_match("a" , "1"); // single.exact
fxt.Test_match("abc" , "123"); // many.exact
fxt.Test_match("ab" , "1"); // single.more
fxt.Test_match("abcde" , "123"); // many.more
fxt.Test_match(" a" , null); // no_match
fxt.Test_match("aBC" , "123"); // upper
}
@Test public void Uft8() {
fxt.Init_add(Bry_.new_u8("aéi") , "1");
fxt.Test_match("aéi" , "1"); // exact
fxt.Test_match("aÉi" , "1"); // upper.utf8
fxt.Test_match("AÉI" , "1"); // upper.all
fxt.Test_match("AÉIo" , "1"); // trailing-char
fxt.Test_match("aei" , null); // no_match
}
@Test public void Uft8_match_pos() {
fxt.Init_add(Bry_.new_u8("aéi") , "1");
fxt.Test_match_pos("aAÉI" , 1, "1"); // match at 1
fxt.Test_match_pos("aAÉI" , 0, null); // no_match at 0
}
@Test public void Uft8_asymmetric() {
fxt.Init_add(Bry_.new_u8("İ") , "1");
fxt.Test_match("İ" , "1"); // exact=y; İ = Bry_.ints_(196,176)
fxt.Test_match("i" , "1"); // lower=y; i = Bry_.ints_(105)
fxt.Test_match("I" , null); // upper=n; I = Bry_.ints_( 73); see Btrie_utf8_itm and rv.asymmetric_bry
fxt.Clear();
fxt.Init_add(Bry_.new_u8("i") , "1");
fxt.Test_match("i" , "1"); // exact=y
fxt.Test_match("I" , "1"); // upper=y
fxt.Test_match("İ" , null); // utf_8=n; note that a trie with "i" doesn't match a src with "İ" even though "İ" lower-cases to "i"
}
@Test public void Utf8_asymmetric_multiple() { // PURPOSE: problems in original implementation of Hash_adp_bry and uneven source / target counts;
fxt.Init_add(Bry_.new_u8("İİ") , "1");
fxt.Test_match("İİ" , "1"); // exact
fxt.Test_match("ii" , "1"); // lower
fxt.Test_match("İi" , "1"); // mixed
fxt.Test_match("" , "1"); // mixed
}
@Test public void Utf8_asymmetric_upper() { // PURPOSE: "İ" and "I" should co-exist; see Btrie_utf8_itm and called_by_match
fxt.Init_add(Bry_.new_u8("İ") , "1");
fxt.Init_add(Bry_.new_u8("I") , "1");
fxt.Test_match("İ" , "1"); // exact
fxt.Test_match("I" , "1"); // exact
fxt.Test_match("i" , "1"); // lower
}
@Test public void Utf8_asymmetric_symbols() { // PURPOSE: test Hash_adp_bry and multi-byte syms (chars that will never be cased)
fxt.Init_add(Bry_.new_u8("a_b") , "1");
fxt.Test_match("a_b" , "1"); // exact: len=3
fxt.Test_match("a†b" , null); // diff : len=3
fxt.Test_match("a±b" , null); // diff : len=2
fxt.Test_match("a_b" , null); // diff : len=1
}
}
class Btrie_utf8_mgr_fxt {
private Btrie_utf8_mgr trie;
public void Clear() {
trie = Btrie_utf8_mgr.new_(Xol_case_mgr_.Utf8());
}
public void Init_add(byte[] key, Object val) {trie.Add_obj(key, val);}
public void Test_match_pos(String src_str, int bgn_pos, String expd) {
byte[] src = Bry_.new_u8(src_str);
Object actl = trie.Match_bgn_w_byte(src[bgn_pos], src, bgn_pos, src.length);
Tfds.Eq(expd, actl, src_str);
}
public void Test_match(String src_str, String expd) {
byte[] src = Bry_.new_u8(src_str);
Object actl = trie.Match_bgn_w_byte(src[0], src, 0, src.length);
Tfds.Eq(expd, actl, src_str);
}
}

View File

@@ -0,0 +1,54 @@
/*
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.enums; import gplx.*; import gplx.core.*;
class Gfo_enum_grp {
// private Ordered_hash itms = Ordered_hash_.new_();
public Gfo_enum_grp(Guid_adp uid, String key, int id, String name, int sort, String xtn) {
this.uid = uid; this.key = key; this.id = id; this.name = name; this.sort = sort; this.xtn = xtn;
}
public Guid_adp Uid() {return uid;} private Guid_adp uid;
public String Key() {return key;} private String key;
public int Id() {return id;} private int id;
public String Name() {return name;} private String name;
public int Sort() {return sort;} private int sort;
public String Xtn() {return xtn;} private String xtn;
}
class Gfo_enum_itm {
public Gfo_enum_itm(Guid_adp uid, String key, int id, String name, int sort, String xtn) {
this.uid = uid; this.key = key; this.id = id; this.name = name; this.sort = sort; this.xtn = xtn;
}
public Guid_adp Uid() {return uid;} private Guid_adp uid;
public String Key() {return key;} private String key;
public int Id() {return id;} private int id;
public String Name() {return name;} private String name;
public int Sort() {return sort;} private int sort;
public String Xtn() {return xtn;} private String xtn;
}
/*
enum_grps
grp_guid,grp_key,grp_int,grp_name,grp_sort,grp_xtn
0-1-2-3,xowa.wiki,0,wiki,,
enum_itms
grp_int,itm_guid,itm_key,itm_int,itm_name,itm_sort,itm_xtn
1,0-1-2-3,0,en.wikipedia.org,0,enwiki,0,''
class Gfo_enum_mgr {
// public Gui
}
*/

View File

@@ -0,0 +1,48 @@
/*
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.flds; import gplx.*; import gplx.core.*;
public class Gfo_fld_base {
public byte Row_dlm() {return row_dlm;} public Gfo_fld_base Row_dlm_(byte v) {row_dlm = v; return this;} protected byte row_dlm = Byte_ascii.Nl;
public byte Fld_dlm() {return fld_dlm;} public Gfo_fld_base Fld_dlm_(byte v) {fld_dlm = v; return this;} protected byte fld_dlm = Byte_ascii.Pipe;
public byte Escape_dlm() {return escape_dlm;} public Gfo_fld_base Escape_dlm_(byte v) {escape_dlm = v; return this;} protected byte escape_dlm = Byte_ascii.Tilde;
public byte Quote_dlm() {return quote_dlm;} public Gfo_fld_base Quote_dlm_(byte v) {quote_dlm = v; return this;} protected byte quote_dlm = Byte_ascii.Nil;
public Gfo_fld_base Escape_reg(byte b) {return Escape_reg(b, b);}
public byte[] Escape_decode() {return decode_regy;}
public Gfo_fld_base Escape_reg(byte key, byte val) {encode_regy[key] = val; decode_regy[val] = key; return this;} protected byte[] decode_regy = new byte[256]; protected byte[] encode_regy = new byte[256];
public Gfo_fld_base Escape_clear() {
for (int i = 0; i < 256; i++)
decode_regy[i] = Byte_ascii.Nil;
for (int i = 0; i < 256; i++)
encode_regy[i] = Byte_ascii.Nil;
return this;
}
Gfo_fld_base Ini_common() {
return Escape_reg(Byte_ascii.Nl, Byte_ascii.Ltr_n).Escape_reg(Byte_ascii.Tab, Byte_ascii.Ltr_t).Escape_reg(Byte_ascii.Cr, Byte_ascii.Ltr_r)
.Escape_reg(Byte_ascii.Backfeed, Byte_ascii.Ltr_b); // .Escape_reg(Byte_ascii.Nil, Byte_ascii.Num_0)
}
protected Gfo_fld_base Ctor_xdat_base() {
return Escape_clear().Ini_common()
.Fld_dlm_(Byte_ascii.Pipe).Row_dlm_(Byte_ascii.Nl).Escape_dlm_(Byte_ascii.Tilde).Quote_dlm_(Byte_ascii.Nil)
.Escape_reg(Byte_ascii.Pipe, Byte_ascii.Ltr_p).Escape_reg(Byte_ascii.Tilde);
}
protected Gfo_fld_base Ctor_sql_base() {
return Escape_clear().Ini_common()
.Fld_dlm_(Byte_ascii.Comma).Row_dlm_(Byte_ascii.Paren_end).Escape_dlm_(Byte_ascii.Backslash).Quote_dlm_(Byte_ascii.Apos)
.Escape_reg(Byte_ascii.Backslash).Escape_reg(Byte_ascii.Quote).Escape_reg(Byte_ascii.Apos); // , Escape_eof = Bry_.new_u8("\\Z")
}
}

View File

@@ -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.flds; import gplx.*; import gplx.core.*;
public class Gfo_fld_rdr extends Gfo_fld_base {
private Bry_bfr bfr = Bry_bfr.new_(); private static final byte[] Bry_nil = Bry_.new_a7("\\0");
public byte[] Data() {return data;} public Gfo_fld_rdr Data_(byte[] v) {data = v; data_len = v.length; pos = 0; return this;} private byte[] data; int data_len;
public int Pos() {return pos;} public Gfo_fld_rdr Pos_(int v) {pos = v; return this;} private int pos;
public int Fld_bgn() {return fld_bgn;} public Gfo_fld_rdr Fld_bgn_(int v) {fld_bgn = v; return this;} private int fld_bgn;
public int Fld_end() {return fld_end;} public Gfo_fld_rdr Fld_end_(int v) {fld_end = v; return this;} private int fld_end;
public int Fld_idx() {return fld_idx;} private int fld_idx;
public int Row_idx() {return row_idx;} private int row_idx;
public void Ini(byte[] data, int pos) {this.data = data; this.data_len = data.length; this.pos = pos;}
public String Read_str_simple() {Move_next_simple(); return String_.new_u8(data, fld_bgn, fld_end);}
public byte[] Read_bry_simple() {Move_next_simple(); return Bry_.Mid(data, fld_bgn, fld_end);} // was Mid_by_len???; 20120915
public int Read_int_base85_lenN(int len) {fld_bgn = pos; fld_end = pos + len - 1 ; pos = pos + len + 1 ; return Base85_utl.XtoIntByAry(data, fld_bgn, fld_end);}
public int Read_int_base85_len5() {fld_bgn = pos; fld_end = pos + 4 ; pos = pos + 6 ; return Base85_utl.XtoIntByAry(data, fld_bgn, fld_end);}
public int Read_int() {Move_next_simple(); return Bry_.Xto_int_or(data, fld_bgn, fld_end, -1);}
public byte Read_int_as_byte() {Move_next_simple(); return (byte)Bry_.Xto_int_or(data, fld_bgn, fld_end, -1);}
public byte Read_byte() {Move_next_simple(); return data[fld_bgn];}
public double Read_double() {Move_next_simple(); return Bry_.XtoDoubleByPos(data, fld_bgn, fld_end);}
public DateAdp Read_dte() {// NOTE: fmt = yyyyMMdd HHmmss.fff
int y = 0, M = 0, d = 0, H = 0, m = 0, s = 0, f = 0;
if (pos < data_len && data[pos] == row_dlm) {++pos; ++row_idx; fld_idx = 0;} fld_bgn = pos;
y += (data[fld_bgn + 0] - Byte_ascii.Num_0) * 1000;
y += (data[fld_bgn + 1] - Byte_ascii.Num_0) * 100;
y += (data[fld_bgn + 2] - Byte_ascii.Num_0) * 10;
y += (data[fld_bgn + 3] - Byte_ascii.Num_0);
M += (data[fld_bgn + 4] - Byte_ascii.Num_0) * 10;
M += (data[fld_bgn + 5] - Byte_ascii.Num_0);
d += (data[fld_bgn + 6] - Byte_ascii.Num_0) * 10;
d += (data[fld_bgn + 7] - Byte_ascii.Num_0);
H += (data[fld_bgn + 9] - Byte_ascii.Num_0) * 10;
H += (data[fld_bgn + 10] - Byte_ascii.Num_0);
m += (data[fld_bgn + 11] - Byte_ascii.Num_0) * 10;
m += (data[fld_bgn + 12] - Byte_ascii.Num_0);
s += (data[fld_bgn + 13] - Byte_ascii.Num_0) * 10;
s += (data[fld_bgn + 14] - Byte_ascii.Num_0);
f += (data[fld_bgn + 16] - Byte_ascii.Num_0) * 100;
f += (data[fld_bgn + 17] - Byte_ascii.Num_0) * 10;
f += (data[fld_bgn + 18] - Byte_ascii.Num_0);
if (data[fld_bgn + 19] != fld_dlm) throw Exc_.new_("csv date is invalid", "txt", String_.new_u8_by_len(data, fld_bgn, 20));
fld_end = pos + 20;
pos = fld_end + 1; ++fld_idx;
return DateAdp_.new_(y, M, d, H, m, s, f);
}
public void Move_next_simple() {
if (pos < data_len) {
byte b_cur = data[pos];
if (b_cur == row_dlm) {
fld_bgn = fld_end = pos;
++pos; ++row_idx;
fld_idx = 0;
return;
}
}
fld_bgn = pos;
if (fld_bgn == data_len) {fld_end = data_len; return;}
for (int i = fld_bgn; i < data_len; i++) {
byte b = data[i];
if (b == fld_dlm || b == row_dlm) {
fld_end = i; pos = i + 1; ++fld_idx; // position after dlm
return;
}
}
throw Exc_.new_("fld_dlm failed", "fld_dlm", (char)fld_dlm, "bgn", fld_bgn);
}
public String Read_str_escape() {Move_next_escaped(bfr); return String_.new_u8(bfr.Xto_bry_and_clear());}
public byte[] Read_bry_escape() {Move_next_escaped(bfr); return bfr.Xto_bry_and_clear();}
public void Move_1() {++pos;}
public void Move_next_escaped() {Move_next_escaped(bfr); bfr.Clear();}
public int Move_next_simple_fld() {
Move_next_simple();
return fld_end;
}
public int Move_next_escaped(Bry_bfr trg) {
//if (pos < data_len && data[pos] == row_dlm) {++pos; ++row_idx; fld_idx = 0;} // REMOVE:20120919: this will fail for empty fields at end of line; EX: "a|\n"; intent was probably to auto-advance to new row, but this intent should be explicit
fld_bgn = pos;
boolean quote_on = false;
for (int i = fld_bgn; i < data_len; i++) {
byte b = data[i];
if ((b == fld_dlm || b == row_dlm) && !quote_on) {
fld_end = i; pos = i + 1; ++fld_idx; // position after dlm
return pos;
}
else if (b == escape_dlm) {
++i;
// if (i == data_len) throw Err_.new_("escape char at end of String");
b = data[i];
byte escape_val = decode_regy[b];
if (escape_val == Byte_ascii.Nil) {trg.Add_byte(escape_dlm).Add_byte(b);} //throw Err_.new_fmt_("unknown escape key: key={0}", data[i]);
else trg.Add_byte(escape_val);
}
else if (b == Byte_ascii.Nil) {
trg.Add(Bry_nil);
}
else if (b == quote_dlm) {
quote_on = !quote_on;
}
else
trg.Add_byte(b);
}
return -1;
}
public Gfo_fld_rdr Ctor_xdat() {return (Gfo_fld_rdr)super.Ctor_xdat_base();}
public Gfo_fld_rdr Ctor_sql() {return (Gfo_fld_rdr)super.Ctor_sql_base();}
public static Gfo_fld_rdr xowa_() {return new Gfo_fld_rdr().Ctor_xdat();}
public static Gfo_fld_rdr sql_() {return new Gfo_fld_rdr().Ctor_sql();}
}

View File

@@ -0,0 +1,56 @@
/*
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.flds; import gplx.*; import gplx.core.*;
import org.junit.*;
import gplx.ios.*;
public class Gfo_fld_rdr_tst {
Gfo_fld_rdr_fxt fxt = new Gfo_fld_rdr_fxt();
@Test public void Read_int() {fxt.ini_xdat().Raw_("123|") .tst_Read_int(123);}
@Test public void Read_double() {fxt.ini_xdat().Raw_("1.23|") .tst_Read_double(1.23);}
@Test public void Read_str_simple() {fxt.ini_xdat().Raw_("ab|") .tst_Read_str_simple("ab");}
@Test public void Read_str_escape_pipe() {fxt.ini_xdat().Raw_("a~pb|") .tst_Read_str_escape("a|b");}
@Test public void Read_str_escape_tilde() {fxt.ini_xdat().Raw_("a~~b|") .tst_Read_str_escape("a~b");}
@Test public void Read_str_escape_nl() {fxt.ini_xdat().Raw_("a~nb|") .tst_Read_str_escape("a\nb");}
@Test public void Read_str_escape_tab() {fxt.ini_xdat().Raw_("a~tb|") .tst_Read_str_escape("a\tb");}
@Test public void Write_str_escape_pipe() {fxt.ini_xdat().tst_Write_str_escape("a|b", "a~pb|");}
@Test public void Read_str_quoted_comma() {fxt.ini_sql ().Raw_("'a,b',") .tst_Read_str_escape("a,b");}
@Test public void Read_str_quoted_apos() {fxt.ini_sql ().Raw_("'a\\'b',") .tst_Read_str_escape("a'b");}
@Test public void Read_multiple() {
fxt.ini_xdat().Raw_("ab|1|.9|\n")
.tst_Read_str_escape("ab").tst_Read_int(1).tst_Read_double(.9)
;
}
@Test public void Read_dlm_nl() {fxt.ini_xdat().Raw_("123\n") .tst_Read_int(123);}
}
class Gfo_fld_rdr_fxt {
Gfo_fld_rdr rdr = new Gfo_fld_rdr(); Gfo_fld_wtr wtr = Gfo_fld_wtr.xowa_();
public Gfo_fld_rdr_fxt Raw_(String v) {rdr.Data_(Bry_.new_u8(v)); return this;}
public Gfo_fld_rdr_fxt ini_xdat() {rdr.Ctor_xdat(); return this;}
public Gfo_fld_rdr_fxt ini_sql() {rdr.Ctor_sql(); return this;}
public Gfo_fld_rdr_fxt tst_Read_int(int expd) {Tfds.Eq(expd, rdr.Read_int()); return this;}
public Gfo_fld_rdr_fxt tst_Read_double(double expd) {Tfds.Eq(expd, rdr.Read_double()); return this;}
public Gfo_fld_rdr_fxt tst_Read_str_simple(String expd) {Tfds.Eq(expd, rdr.Read_str_simple()); return this;}
public Gfo_fld_rdr_fxt tst_Read_str_escape(String expd) {Tfds.Eq(expd, rdr.Read_str_escape()); return this;}
public Gfo_fld_rdr_fxt tst_Write_str_escape(String val, String expd) {
byte[] bry = Bry_.new_u8(val);
wtr.Bfr_(bfr);
wtr.Write_bry_escape_fld(bry);
Tfds.Eq(expd, bfr.Xto_str());
return this;
} private Bry_bfr bfr = Bry_bfr.new_();
}

View File

@@ -0,0 +1,59 @@
/*
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.flds; import gplx.*; import gplx.core.*;
import gplx.ios.*;
public class Gfo_fld_wtr extends Gfo_fld_base {
public Bry_bfr Bfr() {return bfr;} public Gfo_fld_wtr Bfr_(Bry_bfr v) {bfr = v; return this;} Bry_bfr bfr;
public Gfo_fld_wtr() {this.bfr = Bry_bfr.new_();}
public Gfo_fld_wtr Write_int_base85_len5_fld(int v) {bfr.Add_base85(v, Base85_utl.Len_int); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_lenN_fld(int v, int len) {bfr.Add_base85(v, len); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_variable_fld(int v) {bfr.Add_int_variable(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_fixed_fld(int v, int len) {bfr.Add_int_fixed(v, len); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_double_fld(double v) {bfr.Add_double(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_byte_fld(byte v) {bfr.Add_byte(v); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_fld(byte[] val) {Write_bry_escape(val, 0, val.length); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_fld(byte[] val, int bgn, int end) {Write_bry_escape(val, bgn, end); bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_dlm_row() { bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_dlm_fld() { bfr.Add_byte(fld_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_lenN_row(int v, int len) {bfr.Add_base85(v, len); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_int_base85_len5_row(int v) {bfr.Add_base85(v, Base85_utl.Len_int); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_row(byte[] val) {Write_bry_escape(val, 0, val.length); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_bry_escape_row(byte[] val, int bgn, int end) {Write_bry_escape(val, bgn, end); bfr.Add_byte(row_dlm); return this;}
public Gfo_fld_wtr Write_double_row(double v) {bfr.Add_double(v); bfr.Add_byte(row_dlm); return this;}
Gfo_fld_wtr Write_bry_escape(byte[] val, int bgn, int end) {
for (int i = bgn; i < end; i++) {
byte b = val[i];
byte escape_val = encode_regy[b & 0xFF]; // PATCH.JAVA:need to convert to unsigned byte
if (escape_val == Byte_ascii.Nil) bfr.Add_byte(b);
else {bfr.Add_byte(escape_dlm); bfr.Add_byte(escape_val);}
}
return this;
}
public Gfo_fld_wtr Rls() {bfr.Rls(); return this;}
public Io_url_gen Fil_gen() {return fil_gen;} public Gfo_fld_wtr Fil_gen_(Io_url_gen v) {fil_gen = v; return this;} Io_url_gen fil_gen;
public int Bfr_max() {return bfr_max;} public Gfo_fld_wtr Bfr_max_(int v) {bfr_max = v; return this;} private int bfr_max = Io_mgr.Len_mb;
public boolean Flush_needed(int v) {return bfr.Len() + v > bfr_max;}
public void Flush() {
if (Fil_gen().Cur_url() == null) fil_gen.Nxt_url();
Io_mgr.I.AppendFilBfr(fil_gen.Cur_url(), bfr);
}
public void Flush_nxt() {Flush(); fil_gen.Nxt_url();}
public Gfo_fld_wtr Ctor_xdat() {return (Gfo_fld_wtr)super.Ctor_xdat_base();}
public static Gfo_fld_wtr xowa_() {return new Gfo_fld_wtr().Ctor_xdat();}
}

View File

@@ -0,0 +1,24 @@
/*
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.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
class Gfo_html_node {
public Gfo_html_node(byte[] src, int bgn, int end) {this.src = src; this.bgn = bgn; this.end = end;}
public byte[] Src() {return src;} private final byte[] src;
public int Bgn() {return bgn;} private final int bgn;
public int End() {return end;} private final int end;
}

View File

@@ -0,0 +1,68 @@
/*
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.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
import gplx.core.btries.*; import gplx.core.primitives.*;
import gplx.xowa.*;
class Gfo_html_parser {
private final Gfo_msg_log msg_log = Gfo_msg_log.Test();
private final Xop_xatr_parser xatr_parser = new Xop_xatr_parser();
public void Parse(Gfo_html_wkr handler, byte[] src, int bgn, int end) {
// int src_len = src.length;
// int prv_pos = 0;
// int css_find_bgn_len = Css_find_bgn.length;
// byte[] protocol_prefix_bry = Bry_.new_u8(protocol_prefix);
// while (true) {
// int url_bgn = Bry_finder.Find_fwd(src, Css_find_bgn, prv_pos); if (url_bgn == Bry_.NotFound) break; // nothing left; stop
// url_bgn += css_find_bgn_len;
// int url_end = Bry_finder.Find_fwd(src, Byte_ascii.Quote, url_bgn, src_len); if (url_end == Bry_.NotFound) {usr_dlg.Warn_many("", "main_page.css_parse", "could not find css; pos='~{0}' text='~{1}'", url_bgn, String_.new_u8_by_len(src, url_bgn, url_bgn + 32)); break;}
// byte[] css_url_bry = Bry_.Mid(src, url_bgn, url_end);
// css_url_bry = Bry_.Replace(css_url_bry, Css_amp_find, Css_amp_repl); // &amp; -> &
// css_url_bry = url_encoder.Decode(css_url_bry); // %2C -> %7C -> |
// css_url_bry = Bry_.Add(protocol_prefix_bry, css_url_bry);
// rv.Add(String_.new_u8(css_url_bry));
// prv_pos = url_end;
// }
// return rv.XtoStrAry();
int src_len = src.length; int pos = 0;
while (pos < src_len) {
byte b = src[pos];
switch (b) {
case Byte_ascii.Angle_bgn:
pos = Parse_node(handler, src, end, pos, pos + 1);
break;
default:
++pos;
break;
}
}
}
private int Parse_node(Gfo_html_wkr handler, byte[] src, int end, int tkn_bgn, int tkn_end) {
int name_bgn = tkn_end;
int name_end = Bry_finder.Find_fwd_until_ws(src, name_bgn, end);
if (name_end == Bry_finder.Not_found) return end; // EOS; EX: "<abcEOS"
if (name_bgn == name_end) return tkn_end; // ws; EX: "< "
Object o = handler.Get_or_null(src, name_bgn, name_end);
if (o == null) return name_end; // unknown name: EX: "<unknown >"
int node_end = Bry_finder.Find_fwd(src, Byte_ascii.Angle_end, name_end, end);
if (node_end == Bry_finder.Not_found) return end; // EOS; EX: "<name lots_of_text_but_no_gt EOS"
Xop_xatr_itm[] xatr_ary = xatr_parser.Parse(msg_log, src, name_end, node_end);
Gfo_html_tkn tkn = (Gfo_html_tkn)o;
tkn.Process(src, Xop_xatr_hash.new_ary(src, xatr_ary));
return node_end;
}
}

View File

@@ -0,0 +1,22 @@
/*
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.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
interface Gfo_html_wkr {
Gfo_html_tkn Get_or_null(byte[] src, int bgn, int end);
void Process(Gfo_html_node node);
}

View File

@@ -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.core.html.parsers; import gplx.*; import gplx.core.*; import gplx.core.html.*;
import gplx.xowa.*;
interface Gfo_html_tkn {
int Tid();
byte[] Key();
void Process(byte[] src, Xop_xatr_hash hash);
}
class Gfo_html_tkn_ {
public static final int Tid_link = 1;
public static final byte[] Key_link = Bry_.new_a7("link");
}
class Gfo_html_tkn__link implements Gfo_html_tkn {
public int Tid() {return Gfo_html_tkn_.Tid_link;}
public byte[] Key() {return Gfo_html_tkn_.Key_link;}
@gplx.Virtual public void Process(byte[] src, Xop_xatr_hash hash) {}
}

View File

@@ -0,0 +1,23 @@
/*
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.ints; import gplx.*; import gplx.core.*;
public class Int_ary_bldr {
public Int_ary_bldr(int len) {ary = new int[len];}
public Int_ary_bldr Set(int idx, int val) {ary[idx] = val; return this;}
public int[] Xto_int_ary() {return ary;} private int[] ary;
}

View File

@@ -0,0 +1,52 @@
/*
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.lists; import gplx.*; import gplx.core.*;
public class Binary_search_ {
public static int Search(CompareAble[] ary, int ary_len, CompareAble val) {
if (ary_len == 1) return 0;
int interval = ary_len / 2;
int pos = interval - List_adp_.Base1;
int pos_last = ary_len - 1;
int pos_prv = -1;
int loop_count = 0;
while (loop_count++ < 32) { // 32 bit integer
CompareAble lo = ary[pos];
CompareAble hi = pos + 1 == ary_len ? null : ary[pos + 1];
int adj = 0;
int lo_comp = val.compareTo(lo);
if (lo_comp == CompareAble_.Less) // val is < lo; search slots below
adj = -1;
else {
if (hi == null) return pos; // hi is null when at last slot in ary
int hi_comp = val.compareTo(hi);
if (hi_comp == CompareAble_.More) // val is > hi; search slots above
adj = 1;
else
return pos; // val is > lo and < hi; return slot
}
interval /= 2;
if (interval == 0) interval = 1; // do not allow 0 intervals; pos must always change;
pos += (interval * adj);
if (pos == 0 && pos_prv == 0) break; // NOTE: this will only happen when 1st member is not ""
if (pos < 0) pos = 0;
else if (pos > pos_last) pos = pos_last;
pos_prv = pos;
}
return Int_.MinValue; // should only occur if (a) ary's 0th slot is not ""; or (b) some unknown error
}
}

View File

@@ -0,0 +1,47 @@
/*
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.lists; import gplx.*; import gplx.core.*;
import org.junit.*; import gplx.core.primitives.*;
public class Binary_search__tst {
private Binary_search__fxt fxt = new Binary_search__fxt();
@Test public void Basic() {
fxt.Init_ary("", "e", "j", "o", "t", "y");
fxt.Test_binary_search("a", 0);
fxt.Test_binary_search("f", 1);
fxt.Test_binary_search("k", 2);
fxt.Test_binary_search("p", 3);
fxt.Test_binary_search("u", 4);
fxt.Test_binary_search("z", 5);
}
@Test public void One() {
fxt.Init_ary("");
fxt.Test_binary_search("a", 0);
}
}
class Binary_search__fxt {
public void Init_ary(String... v) {
int ary_len = v.length;
ary = new String_obj_val[ary_len];
for (int i = 0; i < ary_len; i++)
ary[i] = String_obj_val.new_(v[i]);
} private String_obj_val[] ary;
public void Test_binary_search(String val, int expd) {
int actl = Binary_search_.Search(ary, ary.length, String_obj_val.new_(val));
Tfds.Eq(expd, actl, val);
}
}

View File

@@ -0,0 +1,24 @@
/*
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 interface Http_client_rdr {
void Stream_(Object o);
String Read_line();
byte[] Read_line_as_bry();
void Rls();
}

View File

@@ -0,0 +1,35 @@
/*
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 Http_client_rdr_ {
public static Http_client_rdr new_stream() {return new Http_client_rdr__stream();}
public static Http_client_rdr new_mem() {return new Http_client_rdr__mem();}
}
class Http_client_rdr__mem implements Http_client_rdr {
private String[] ary; private int ary_len; private int idx;
public void Stream_(Object o) {
this.ary = (String[])o;
this.ary_len = ary.length;
this.idx = 0;
}
public String Read_line() {
return idx == ary_len ? null : ary[idx++];
}
public byte[] Read_line_as_bry() {return Bry_.new_u8(Read_line());}
public void Rls() {}
}

View File

@@ -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.core.net; import gplx.*; import gplx.core.*;
import java.io.*;
class Http_client_rdr__stream implements Http_client_rdr {
private BufferedReader br;
public void Stream_(Object o) {
this.br = new BufferedReader(new InputStreamReader((InputStream)o, java.nio.charset.Charset.forName("UTF-8")));
}
public String Read_line() {
try {return br.readLine();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Read_line failed");}
}
public byte[] Read_line_as_bry() {return Bry_.new_u8(Read_line());}
public void Rls() {
try {br.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

@@ -0,0 +1,27 @@
/*
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.ios.*;
public interface Http_client_wtr {
void Stream_(Object o);
void Write_bry(byte[] bry);
void Write_str(String s);
void Write_mid(byte[] bry, int bgn, int end);
void Write_stream(Io_stream_rdr stream_rdr);
void Rls();
}

View File

@@ -0,0 +1,21 @@
/*
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 Http_client_wtr_ {
public static Http_client_wtr new_stream() {return new Http_client_wtr__stream();}
}

View File

@@ -0,0 +1,53 @@
/*
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.ios.*;
import java.io.*;
class Http_client_wtr__stream implements Http_client_wtr {
private final byte[] tmp_stream_bry = new byte[1024];
private DataOutputStream stream;
public void Stream_(Object o) {
this.stream = new DataOutputStream((OutputStream)o);
}
public void Write_bry(byte[] bry) {
try {stream.write(bry);}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Write_bry failed");}
}
public void Write_str(String s) {
try {stream.writeBytes(s);}
catch (Exception e) {throw Exc_.new_exc(e, "net", "Write_str failed");}
}
public void Write_mid(byte[] bry, int bgn, int end) {
try {stream.write(bry, bgn, end - bgn);}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Write_mid failed");}
}
public void Write_stream(Io_stream_rdr stream_rdr) {
synchronized (tmp_stream_bry) {
int read = 0;
while (true) {
read = stream_rdr.Read(tmp_stream_bry, 0, 1024);
if (read == -1) break;
Write_mid(tmp_stream_bry, 0, read);
}
}
}
public void Rls() {
try {stream.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

@@ -0,0 +1,27 @@
/*
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 Http_post_data_hash {
private final Ordered_hash hash = Ordered_hash_.new_bry_();
public int Len() {return hash.Count();}
public Http_post_data_itm Get_at(int i) {return (Http_post_data_itm)hash.Get_at(i);}
public Http_post_data_itm Get_by(byte[] k) {return (Http_post_data_itm)hash.Get_by(k);}
public void Add(byte[] key, byte[] val) {
hash.Add(key, new Http_post_data_itm(key, val));
}
}

View File

@@ -0,0 +1,23 @@
/*
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 Http_post_data_itm {
public Http_post_data_itm(byte[] key, byte[] val) {this.key = key; this.val = val;}
public byte[] Key() {return key;} private final byte[] key;
public byte[] Val() {return val;} private final byte[] val;
}

View File

@@ -0,0 +1,81 @@
/*
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 Http_request_itm {
public Http_request_itm(int type, byte[] url, byte[] protocol, byte[] host, byte[] user_agent
, byte[] accept, byte[] accept_language, byte[] accept_encoding, boolean dnt, byte[] x_requested_with, byte[] cookie, byte[] referer
, int content_length, byte[] content_type, byte[] content_type_boundary
, byte[] connection, byte[] pragma, byte[] cache_control
, Http_post_data_hash post_data_hash
) {
this.type = type; this.url = url; this.protocol = protocol; this.host = host; this.user_agent = user_agent;
this.accept = accept; this.accept_language = accept_language; this.accept_encoding = accept_encoding; this.dnt = dnt; this.x_requested_with = x_requested_with; this.cookie = cookie; this.referer = referer;
this.content_length = content_length; this.content_type = content_type; this.content_type_boundary = content_type_boundary;
this.connection = connection; this.pragma = pragma; this.cache_control = cache_control;
this.post_data_hash = post_data_hash;
}
public int Type() {return type;} private final int type;
public byte[] Url() {return url;} private final byte[] url;
public byte[] Protocol() {return protocol;} private final byte[] protocol;
public byte[] Host() {return host;} private final byte[] host;
public byte[] User_agent() {return user_agent;} private final byte[] user_agent;
public byte[] Accept() {return accept;} private final byte[] accept;
public byte[] Accept_language() {return accept_language;} private final byte[] accept_language;
public byte[] Accept_encoding() {return accept_encoding;} private final byte[] accept_encoding;
public boolean Dnt() {return dnt;} private final boolean dnt;
public byte[] X_requested_with() {return x_requested_with;} private byte[] x_requested_with;
public byte[] Cookie() {return cookie;} private final byte[] cookie;
public byte[] Referer() {return referer;} private final byte[] referer;
public int Content_length() {return content_length;} private final int content_length;
public byte[] Content_type() {return content_type;} private final byte[] content_type;
public byte[] Content_type_boundary() {return content_type_boundary;} private final byte[] content_type_boundary;
public byte[] Connection() {return connection;} private final byte[] connection;
public byte[] Pragma() {return pragma;} private final byte[] pragma;
public byte[] Cache_control() {return cache_control;} private final byte[] cache_control;
public Http_post_data_hash Post_data_hash() {return post_data_hash;} private final Http_post_data_hash post_data_hash;
public String To_str(Bry_bfr bfr) {
bfr .Add_kv_line("type" , type == Type_get ? "GET" : "POST")
.Add_kv_line("url" , url)
.Add_kv_line("protocol" , protocol)
.Add_kv_line("host" , host)
.Add_kv_line("user_agent" , user_agent)
.Add_kv_line("accept" , accept)
.Add_kv_line("accept_encoding" , accept_encoding)
.Add_kv_line("dnt" , dnt)
.Add_kv_line("x_requested_with" , x_requested_with)
.Add_kv_line("cookie" , cookie)
.Add_kv_line("referer" , referer)
.Add_kv_line("content_length" , content_length)
.Add_kv_line("content_type" , content_type)
.Add_kv_line("content_type_boundary" , content_type_boundary)
.Add_kv_line("connection" , connection)
.Add_kv_line("pragma" , pragma)
.Add_kv_line("cache_control" , cache_control)
;
if (post_data_hash != null) {
int len = post_data_hash.Len();
for (int i = 0; i < len; ++i) {
Http_post_data_itm itm = post_data_hash.Get_at(i);
bfr.Add_byte_repeat(Byte_ascii.Space, 2);
bfr.Add_kv_line(String_.new_u8(itm.Key()), itm.Val());
}
}
return bfr.Xto_str_and_clear();
}
public static final int Type_get = 1, Type_post = 2;
}

View File

@@ -0,0 +1,168 @@
/*
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 Http_request_parser {
private boolean dnt;
private int type, content_length;
private byte[] url, protocol, host, user_agent, accept, accept_language, accept_encoding, x_requested_with, cookie, referer, content_type, content_type_boundary, connection, pragma, cache_control;
private Http_post_data_hash post_data_hash;
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
private final Http_server_wtr server_wtr; private final boolean log;
public Http_request_parser(Http_server_wtr server_wtr, boolean log) {this.server_wtr = server_wtr; this.log = log;}
public void Clear() {
this.dnt = false;
this.type = this.content_length = 0;
this.url = this.protocol = this.host = this.user_agent = this.accept = this.accept_language = this.accept_encoding = this.x_requested_with = this.cookie
= this.referer = this.content_type = this.content_type_boundary = this.connection = this.pragma = this.cache_control = null;
this.post_data_hash = null;
}
public Http_request_itm Parse(Http_client_rdr rdr) {
this.Clear();
boolean reading_post_data = false; boolean post_nl_seen = false;
while (true) {
String line_str = rdr.Read_line(); if (line_str == null) break; // needed for TEST
if (log) server_wtr.Write_str_w_nl(line_str);
byte[] line = Bry_.new_u8(line_str);
int line_len = line.length;
if (line_len == 0) {
switch (type) {
case Http_request_itm.Type_get: break;
case Http_request_itm.Type_post:
if (reading_post_data || post_nl_seen) throw Exc_.new_("http.request.parser;invalid new line during post", "request", To_str());
post_nl_seen = true; // only allow one \n per POST
continue; // ignore line and get next
default: throw Exc_.new_unimplemented();
}
break; // only GET will reach this line; GET requests always end with blank line; stop;
}
if (content_type_boundary != null && Bry_.Has_at_bgn(line, content_type_boundary)) {
while (true) {
if (Bry_.Has_at_end(line, Tkn_content_type_boundary_end)) break; // last form_data pair will end with "--"; stop
line = Parse_content_type_boundary(rdr);
}
break; // assume form_data ends POST request
}
Object o = trie.Match_bgn(line, 0, line_len);
if (o == null) {
server_wtr.Write_str_w_nl(String_.Format("http.request.parser; unknown line; line={0} request={1}", line_str, To_str()));
continue;
}
int val_bgn = Bry_finder.Find_fwd_while_ws(line, trie.Match_pos(), line_len); // skip ws after key; EX: "Host: "
int tid = ((Int_obj_val)o).Val();
switch (tid) {
case Tid_get:
case Tid_post: Parse_type(tid, val_bgn, line, line_len); break;
case Tid_host: this.host = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_user_agent: this.user_agent = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept: this.accept = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept_language: this.accept_language = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_accept_encoding: this.accept_encoding = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_dnt: this.dnt = line[val_bgn] == Byte_ascii.Num_1; break;
case Tid_x_requested_with: this.x_requested_with = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_cookie: this.cookie = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_referer: this.referer = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_content_length: this.content_length = Bry_.Xto_int_or(line, val_bgn, line_len, -1); break;
case Tid_content_type: Parse_content_type(val_bgn, line, line_len); break;
case Tid_connection: this.connection = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_pragma: this.pragma = Bry_.Mid(line, val_bgn, line_len); break;
case Tid_cache_control: this.cache_control = Bry_.Mid(line, val_bgn, line_len); break;
default: throw Exc_.new_unhandled(tid);
}
}
return Make_request_itm();
}
private void Parse_type(int tid, int val_bgn, byte[] line, int line_len) { // EX: "POST /xowa-cmd:exec_as_json HTTP/1.1"
int url_end = Bry_finder.Find_bwd(line, Byte_ascii.Space, line_len); if (url_end == Bry_finder.Not_found) throw Exc_.new_("invalid protocol", "line", line, "request", To_str());
switch (tid) {
case Tid_get : this.type = Http_request_itm.Type_get; break;
case Tid_post : this.type = Http_request_itm.Type_post; break;
default : throw Exc_.new_unimplemented();
}
this.url = Bry_.Mid(line, val_bgn, url_end);
this.protocol = Bry_.Mid(line, url_end + 1, line_len);
}
private void Parse_content_type(int val_bgn, byte[] line, int line_len) { // EX: Content-Type: multipart/form-data; boundary=---------------------------72432484930026
int boundary_bgn = Bry_finder.Find_fwd(line, Tkn_boundary, val_bgn, line_len); if (boundary_bgn == Bry_finder.Not_found) throw Exc_.new_("invalid content_type", "line", line, "request", To_str());
int content_type_end = Bry_finder.Find_bwd(line, Byte_ascii.Semic, boundary_bgn);
this.content_type = Bry_.Mid(line, val_bgn, content_type_end);
this.content_type_boundary = Bry_.Add(Tkn_content_type_boundary_end, Bry_.Mid(line, boundary_bgn += Tkn_boundary.length, line_len));
}
private Http_request_itm Make_request_itm() {
return new Http_request_itm(type, url, protocol, host, user_agent, accept, accept_language, accept_encoding, dnt, x_requested_with, cookie, referer, content_length, content_type, content_type_boundary, connection, pragma, cache_control, post_data_hash);
}
private byte[] Parse_content_type_boundary(Http_client_rdr rdr) {
if (post_data_hash == null) post_data_hash = new Http_post_data_hash();
byte[] line = Bry_.new_u8(rdr.Read_line()); // cur line is already known to be content_type_boundary; skip it
byte[] key = Parse_post_data_name(line);
String line_str = rdr.Read_line(); // blank-line
if (String_.Len_gt_0(line_str)) {throw Exc_.new_("http.request.parser; blank_line should follow content_type_boundary", "request", To_str());}
while (true) {
line = Bry_.new_u8(rdr.Read_line());
if (Bry_.Has_at_bgn(line, content_type_boundary)) break;
tmp_bfr.Add(line);
}
byte[] val = tmp_bfr.Xto_bry_and_clear();
post_data_hash.Add(key, val);
return line;
}
private byte[] Parse_post_data_name(byte[] line) { // EX: Content-Disposition: form-data; name="data"
int line_len = line.length;
int pos = Assert_tkn(line, 0, line_len, Tkn_content_disposition);
pos = Assert_tkn(line, pos, line_len, Tkn_form_data);
pos = Assert_tkn(line, pos, line_len, Tkn_name);
int name_end = line_len;
if (line[pos] == Byte_ascii.Quote) {
if (line[name_end - 1] != Byte_ascii.Quote) throw Exc_.new_("http.request.parser; invalid form at end", "line", line, "request", To_str());
++pos;
--name_end;
}
return Bry_.Mid(line, pos, name_end);
}
private int Assert_tkn(byte[] src, int src_pos, int src_len, byte[] tkn) {
int tkn_len = tkn.length;
if (!Bry_.Match(src, src_pos, src_pos + tkn_len, tkn)) throw Exc_.new_("http.request.parser; invalid form_data line", "tkn", tkn, "line", src, "request", To_str());
int rv = src_pos += tkn_len;
return Bry_finder.Find_fwd_while_ws(src, rv, src_len);
}
private String To_str() {return Make_request_itm().To_str(tmp_bfr);}
private static final int Tid_get = 1, Tid_post = 2, Tid_host = 3, Tid_user_agent = 4, Tid_accept = 5, Tid_accept_language = 6, Tid_accept_encoding = 7, Tid_dnt = 8
, Tid_x_requested_with = 9, Tid_cookie = 10, Tid_referer = 11, Tid_content_length = 12, Tid_content_type = 13, Tid_connection = 14, Tid_pragma = 15, Tid_cache_control = 16;
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_ascii_()
.Add_str_int("GET" , Tid_get)
.Add_str_int("POST" , Tid_post)
.Add_str_int("Host:" , Tid_host)
.Add_str_int("User-Agent:" , Tid_user_agent)
.Add_str_int("Accept:" , Tid_accept)
.Add_str_int("Accept-Language:" , Tid_accept_language)
.Add_str_int("Accept-Encoding:" , Tid_accept_encoding)
.Add_str_int("DNT:" , Tid_dnt)
.Add_str_int("X-Requested-With:" , Tid_x_requested_with)
.Add_str_int("Cookie:" , Tid_cookie)
.Add_str_int("Referer:" , Tid_referer)
.Add_str_int("Content-length:" , Tid_content_length)
.Add_str_int("Content-Type:" , Tid_content_type)
.Add_str_int("Connection:" , Tid_connection)
.Add_str_int("Pragma:" , Tid_pragma)
.Add_str_int("Cache-Control:" , Tid_cache_control)
;
private static final byte[] Tkn_boundary = Bry_.new_a7("boundary="), Tkn_content_type_boundary_end = Bry_.new_a7("--")
, Tkn_content_disposition = Bry_.new_a7("Content-Disposition:"), Tkn_form_data = Bry_.new_a7("form-data;")
, Tkn_name = Bry_.new_a7("name=")
;
}

View File

@@ -0,0 +1,82 @@
/*
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 Http_request_parser_tst {
@Before public void init() {fxt.Clear();} private final Http_request_parser_fxt fxt = new Http_request_parser_fxt();
@Test public void Type_post() {
fxt.Test_type_post("POST /url HTTP/1.1", Http_request_itm.Type_post, "/url", "HTTP/1.1");
}
@Test public void Type_content_type() {
fxt.Test_content_type("Content-Type: multipart/form-data; boundary=---------------------------72432484930026", "multipart/form-data", "-----------------------------72432484930026");
}
@Test public void Type_form_data() {
fxt.Test_form_data(String_.Ary
( "POST /url HTTP/1.1"
, "Content-Type: multipart/form-data; boundary=---------------------------12345678901234"
, ""
, "-----------------------------12345678901234"
, "Content-Disposition: form-data; name=\"key0\""
, ""
, "val0"
, "-----------------------------12345678901234"
, "Content-Disposition: form-data; name=\"key1\""
, ""
, "val1"
, "-----------------------------12345678901234--"
)
, fxt.Make_post_data_itm("key0", "val0")
, fxt.Make_post_data_itm("key1", "val1")
);
}
}
class Http_request_parser_fxt {
private final Http_request_parser parser;
private final Http_client_rdr client_rdr = Http_client_rdr_.new_mem();
public Http_request_parser_fxt() {
this.parser = new Http_request_parser(Http_server_wtr_.Noop, false);
}
public void Clear() {
parser.Clear();
}
public Http_post_data_itm Make_post_data_itm(String key, String val) {return new Http_post_data_itm(Bry_.new_u8(key), Bry_.new_u8(val));}
public void Test_type_post(String line, int expd_type, String expd_url, String expd_protocol) {
client_rdr.Stream_(String_.Ary(line));
Http_request_itm req = parser.Parse(client_rdr);
Tfds.Eq(expd_type , req.Type());
Tfds.Eq(expd_url , String_.new_u8(req.Url()));
Tfds.Eq(expd_protocol , String_.new_u8(req.Protocol()));
}
public void Test_content_type(String line, String expd_content_type, String expd_content_boundary) {
client_rdr.Stream_(String_.Ary(line));
Http_request_itm req = parser.Parse(client_rdr);
Tfds.Eq(expd_content_type , String_.new_u8(req.Content_type()));
Tfds.Eq(expd_content_boundary , String_.new_u8(req.Content_type_boundary()));
}
public void Test_form_data(String[] ary, Http_post_data_itm... expd) {
client_rdr.Stream_(ary);
Http_request_itm req = parser.Parse(client_rdr);
Http_post_data_hash hash = req.Post_data_hash();
int len = hash.Len();
for (int i = 0; i < len; ++i) {
Http_post_data_itm itm = hash.Get_at(i);
Tfds.Eq_bry(itm.Key(), expd[i].Key());
Tfds.Eq_bry(itm.Val(), expd[i].Val());
}
}
}

View File

@@ -0,0 +1,24 @@
/*
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 interface Http_server_wtr {
void Write_str_w_nl(String s);
}
class Http_server_wtr__noop implements Http_server_wtr {
public void Write_str_w_nl(String s) {}
}

View File

@@ -0,0 +1,22 @@
/*
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 Http_server_wtr_ {
public static Http_server_wtr new_console() {return new Http_server_wtr__console();}
public static final Http_server_wtr Noop = new Http_server_wtr__noop();
}

View File

@@ -0,0 +1,21 @@
/*
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 Http_server_wtr__console implements Http_server_wtr {
public void Write_str_w_nl(String s) {ConsoleAdp._.WriteLine(s);}
}

View File

@@ -0,0 +1,23 @@
/*
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 interface Socket_adp {
Object Get_input_stream();
Object Get_output_stream();
void Rls();
}

View File

@@ -0,0 +1,36 @@
/*
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 java.io.IOException;
import java.net.*;
public class Socket_adp__base implements Socket_adp {
private final Socket socket;
public Socket_adp__base(Socket socket) {this.socket = socket;}
public Object Get_input_stream() {
try {return socket.getInputStream();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Get_input_stream failed");}
}
public Object Get_output_stream() {
try {return socket.getOutputStream();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Get_output_stream failed");}
}
public void Rls() {
try {socket.close();}
catch (IOException e) {throw Exc_.new_exc(e, "net", "Rls failed");}
}
}

View File

@@ -0,0 +1,50 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern {
private final Gfo_pattern_itm[] itms; private final int itms_len;
private final Gfo_pattern_ctx ctx = new Gfo_pattern_ctx();
public Gfo_pattern(byte[] raw) {
this.raw = raw;
itms = Gfo_pattern_itm_.Compile(raw);
itms_len = itms.length;
}
public byte[] Raw() {return raw;} private byte[] raw;
public boolean Match(byte[] val) {
int val_len = val.length;
int val_pos = 0;
ctx.Init(itms_len);
for (int i = 0; i < itms_len; ++i) {
Gfo_pattern_itm itm = itms[i];
ctx.Itm_idx_(i);
val_pos = itm.Match(ctx, val, val_len, val_pos);
if (!ctx.Rslt_pass()) return false;
}
return ctx.Rslt_pass() && val_pos == val_len;
}
public static Gfo_pattern[] Parse_to_ary(byte[] raw) {
byte[][] patterns = Bry_.Split(raw, Byte_ascii.Semic, true);
int patterns_len = patterns.length;
Gfo_pattern[] rv = new Gfo_pattern[patterns_len];
for (int i = 0; i < patterns_len; ++i) {
byte[] pattern = patterns[i];
rv[i] = new Gfo_pattern(pattern);
}
return rv;
}
}

View File

@@ -0,0 +1,31 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern_ctx {
public boolean Rslt_pass() {return rslt;} private boolean rslt;
public void Rslt_fail_() {rslt = false;}
public boolean Prv_was_wild() {return prv_was_wild;} public void Prv_was_wild_(boolean v) {prv_was_wild = v;} private boolean prv_was_wild;
private int itm_len;
public int Itm_idx() {return itm_idx;} public void Itm_idx_(int v) {itm_idx = v;} private int itm_idx;
public boolean Itm_idx_is_last() {return itm_idx == itm_len - 1;}
public void Init(int itm_len) {
this.rslt = true;
this.itm_len = itm_len;
this.prv_was_wild = false;
}
}

View File

@@ -0,0 +1,64 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
import gplx.core.strings.*;
public interface Gfo_pattern_itm {
byte Tid();
void Compile(byte[] src, int bgn, int end);
int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos);
void Xto_str(String_bldr sb);
}
class Gfo_pattern_itm_text implements Gfo_pattern_itm {
public Gfo_pattern_itm_text() {}
public byte Tid() {return Gfo_pattern_itm_.Tid_text;}
public byte[] Text() {return text;} private byte[] text; private int text_len;
public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|" + String_.new_u8(text));}
public void Compile(byte[] src, int bgn, int end) {
this.text = Bry_.Mid(src, bgn, end);
this.text_len = end - bgn;
}
public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) {
boolean pass = false;
int text_end = pos + text_len;
if (text_end > src_len) text_end = src_len;
if (ctx.Prv_was_wild()) {
int text_bgn = Bry_finder.Find_fwd(src, text, pos);
pass = text_bgn != Bry_finder.Not_found;
if (pass)
pos = text_bgn + text_len;
}
else {
pass = Bry_.Match(src, pos, text_end, text);
if (pass)
pos = text_end;
}
if (!pass) ctx.Rslt_fail_();
ctx.Prv_was_wild_(false);
return pos;
}
}
class Gfo_pattern_itm_wild implements Gfo_pattern_itm {
public byte Tid() {return Gfo_pattern_itm_.Tid_wild;}
public void Compile(byte[] src, int bgn, int end) {}
public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) {
ctx.Prv_was_wild_(true);
return ctx.Itm_idx_is_last() ? src_len : pos;
}
public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|*");}
public static final Gfo_pattern_itm_wild _ = new Gfo_pattern_itm_wild(); Gfo_pattern_itm_wild() {}
}

View File

@@ -0,0 +1,51 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
public class Gfo_pattern_itm_ {
public static final byte Tid_text = 0, Tid_wild = 1;
public static Gfo_pattern_itm[] Compile(byte[] raw) {
List_adp rv = List_adp_.new_();
int raw_len = raw.length;
int itm_bgn = -1;
Gfo_pattern_itm itm = null;
int pos = 0;
while (true) {
boolean last = pos == raw_len;
byte b = last ? Byte_ascii.Nil : raw[pos];
switch (b) {
case Byte_ascii.Nil:
if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null; itm_bgn = -1;}
break;
case Byte_ascii.Star:
if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null; itm_bgn = -1;}
rv.Add(Gfo_pattern_itm_wild._);
break;
default:
if (itm_bgn == -1) {
itm_bgn = pos;
itm = new Gfo_pattern_itm_text();
rv.Add(itm);
}
break;
}
++pos;
if (last) break;
}
return (Gfo_pattern_itm[])rv.To_ary_and_clear(Gfo_pattern_itm.class);
}
}

View File

@@ -0,0 +1,93 @@
/*
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.regxs; import gplx.*; import gplx.core.*;
import org.junit.*; import gplx.core.strings.*;
public class Gfo_pattern_tst {
@Before public void init() {fxt.Clear();} private Gfo_pattern_itm_fxt fxt = new Gfo_pattern_itm_fxt();
@Test public void Compile() {
fxt.Test_Compile("a" , fxt.itm_text_("a"));
fxt.Test_Compile("*" , fxt.itm_wild_());
fxt.Test_Compile("a*" , fxt.itm_text_("a"), fxt.itm_wild_());
fxt.Test_Compile("*a" , fxt.itm_wild_(), fxt.itm_text_("a"));
fxt.Test_Compile("*ab*" , fxt.itm_wild_(), fxt.itm_text_("ab"), fxt.itm_wild_());
fxt.Test_Compile("" );
}
@Test public void Match() {
Gfo_pattern pattern = fxt.pattern_("abc");
fxt.Test_Match_y(pattern, "abc");
fxt.Test_Match_n(pattern, "ab", "a", "bc", "Abc", "");
}
@Test public void Match_all() {
Gfo_pattern pattern = fxt.pattern_("*");
fxt.Test_Match_y(pattern, "a", "abc", "");
}
@Test public void Match_bgn() {
Gfo_pattern pattern = fxt.pattern_("abc*");
fxt.Test_Match_y(pattern, "abc", "abcdef");
fxt.Test_Match_n(pattern, "abd", "aabc", "");
}
@Test public void Match_end() {
Gfo_pattern pattern = fxt.pattern_("*abc");
fxt.Test_Match_y(pattern, "abc", "xyzabc");
fxt.Test_Match_n(pattern, "abcd", "");
}
@Test public void Match_mid() {
Gfo_pattern pattern = fxt.pattern_("a*c*e");
fxt.Test_Match_y(pattern, "ace", "abcde");
fxt.Test_Match_n(pattern, "abc", "");
}
@Test public void Bug_ctx() { // PURPOSE.fix: cb was true b/c ctx was not reset correctly
Gfo_pattern pattern = fxt.pattern_("b*");
fxt.Test_Match_y(pattern, "bc");
fxt.Test_Match_n(pattern, "cb");
}
}
class Gfo_pattern_itm_fxt {
public void Clear() {}
public Gfo_pattern pattern_(String raw) {return new Gfo_pattern(Bry_.new_u8(raw));}
public void Test_Match_y(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.Y);}
public void Test_Match_n(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.N);}
private void Test_Match(Gfo_pattern pattern, String[] itms, boolean expd) {
int len = itms.length;
for (int i = 0; i < len; i++) {
String itm = itms[i];
Tfds.Eq(expd, pattern.Match(Bry_.new_u8(itm)), "pattern={0} itm={1} expd={2}", String_.new_u8(pattern.Raw()), itm, expd);
}
}
public Gfo_pattern_itm_wild itm_wild_() {return Gfo_pattern_itm_wild._;}
public Gfo_pattern_itm_text itm_text_(String raw) {
Gfo_pattern_itm_text rv = new Gfo_pattern_itm_text();
byte[] bry = Bry_.new_u8(raw);
rv.Compile(bry, 0, bry.length);
return rv;
}
public void Test_Compile(String raw, Gfo_pattern_itm... expd) {
Gfo_pattern_itm[] actl = Gfo_pattern_itm_.Compile(Bry_.new_u8(raw));
Tfds.Eq(Ary_xto_str(expd), Ary_xto_str(actl));
}
private static String Ary_xto_str(Gfo_pattern_itm[] ary) {
int len = ary.length;
String_bldr sb = String_bldr_.new_();
for (int i = 0; i < len; i++) {
if (i != 0) sb.Add_char_nl();
Gfo_pattern_itm itm = ary[i];
itm.Xto_str(sb);
}
return sb.Xto_str_and_clear();
}
}

View File

@@ -0,0 +1,42 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public class Gfo_async_cmd_itm implements GfoInvkAble {
private GfoInvkAble invk; private String invk_key; private GfoMsg msg = GfoMsg_.new_cast_("");
public Gfo_async_cmd_itm Init(GfoInvkAble invk, String invk_key, Object... args) {
this.invk = invk; this.invk_key = invk_key;
msg.Args_reset();
msg.Clear();
int len = args.length;
for (int i = 0; i < len; i += 2) {
String key = (String)args[i];
Object val = args[i + 1];
msg.Add(key, val);
}
return this;
}
public void Exec() {
GfoInvkAble_.InvkCmd_msg(invk, invk_key, msg);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_exec)) Exec();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_exec = "exec";
public static final Gfo_async_cmd_itm[] Ary_empty = new Gfo_async_cmd_itm[0];
}

View File

@@ -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.core.threads; import gplx.*; import gplx.core.*;
class Gfo_async_cmd_mkr {
// private Gfo_async_cmd_itm[] free = Gfo_async_cmd_itm.Ary_empty, used = Gfo_async_cmd_itm.Ary_empty;
// private int free_bgn = 0, free_end = 0, ary_len = 0;
// public void Resize(int v) {
// free = (Gfo_async_cmd_itm[])Array_.Resize(free, v);
// used = (Gfo_async_cmd_itm[])Array_.Resize(used, v);
// ary_len = v;
// }
public Gfo_async_cmd_itm Get(GfoInvkAble invk, String invk_key, Object... args) {
Gfo_async_cmd_itm rv = new Gfo_async_cmd_itm();
rv.Init(invk, invk_key, args);
return rv;
}
public void Rls(Gfo_async_cmd_itm cmd) {
}
}

View File

@@ -0,0 +1,58 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.core.primitives.*;
public class Gfo_async_mgr implements GfoInvkAble {
private List_adp queue = List_adp_.new_();
private Bool_obj_ref running = Bool_obj_ref.n_();
private Gfo_async_cmd_mkr cmd_mkr = new Gfo_async_cmd_mkr();
public void Queue(GfoInvkAble invk, String invk_key, Object... args) {
Gfo_async_cmd_itm cmd = cmd_mkr.Get(invk, invk_key, args);
synchronized (queue) {
queue.Add(cmd);
}
synchronized (running) {
if (running.Val_n()) {
running.Val_y_();
gplx.core.threads.Thread_adp_.invk_(Invk_run, this, Invk_run).Start();
}
}
}
public void Run() {
Gfo_async_cmd_itm cmd = null;
try {
while (true) {
synchronized (queue) {
if (queue.Count() == 0) break;
cmd = (Gfo_async_cmd_itm)List_adp_.Pop(queue);
cmd.Exec();
}
}
}
finally {
synchronized (running) {
running.Val_n_();
}
}
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run)) Run();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_run = "run";
}

View File

@@ -0,0 +1,30 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public interface Gfo_thread_cmd extends GfoInvkAble {
void Cmd_ctor();
String Async_key();
int Async_sleep_interval();
boolean Async_prog_enabled();
void Async_prog_run(int async_sleep_sum);
byte Async_init();
boolean Async_term();
void Async_run();
boolean Async_running();
Gfo_thread_cmd Async_next_cmd(); void Async_next_cmd_(Gfo_thread_cmd next);
}

View File

@@ -0,0 +1,22 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public class Gfo_thread_cmd_ {
public static final int Async_sleep_interval_1_second = 1000;
public static final byte Init_ok = 0, Init_cancel_step = 1, Init_cancel_all = 2;
}

View File

@@ -0,0 +1,41 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_base implements Gfo_thread_cmd {
@gplx.Virtual public String Async_key() {return "undefined";}
public void Cmd_ctor() {}
public Gfo_thread_cmd_base Ctor(Gfo_usr_dlg usr_dlg, Gfui_kit kit) {this.usr_dlg = usr_dlg; this.kit = kit; return this;} protected Gfo_usr_dlg usr_dlg; protected Gfui_kit kit;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_base Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_base Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
@gplx.Virtual public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
@gplx.Virtual public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {return Gfo_thread_cmd_.Init_ok;}
@gplx.Virtual public boolean Async_term() {return true;}
@gplx.Virtual public void Async_prog_run(int async_sleep_sum) {}
@gplx.Virtual public void Async_bgn() {}
@gplx.Virtual public boolean Async_running() {return false;}
@gplx.Virtual public void Async_run() {}
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_async_bgn)) Async_bgn();
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_owner = "owner", Invk_async_bgn = "async_bgn";
}

View File

@@ -0,0 +1,73 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_download implements Gfo_thread_cmd {
public Gfo_thread_cmd Ctor(Gfo_usr_dlg usr_dlg, Gfui_kit kit) {this.usr_dlg = usr_dlg; this.kit = kit; xrg.Prog_dlg_(usr_dlg); return this;}
public Gfo_thread_cmd_download Init(String prog_fmt_hdr, String src, Io_url trg) {
this.src = src; this.trg = trg;
xrg.Prog_fmt_hdr_(prog_fmt_hdr).Init(src, trg);
return this;
} String src; protected Gfui_kit kit; Gfo_usr_dlg usr_dlg; Io_url trg;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_download Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_download Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public void Cmd_ctor() {}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
@gplx.Virtual public String Async_key() {return KEY;}
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {
if (Io_mgr.I.ExistsFil(trg)) {
int rslt = kit.Ask_yes_no_cancel(GRP_KEY, "target_exists", "Target file already exists: '~{0}'.\nDo you want to delete it?", trg.Raw());
switch (rslt) {
case Gfui_dlg_msg_.Btn_yes: Io_mgr.I.DeleteFil(trg); break;
case Gfui_dlg_msg_.Btn_no: return Gfo_thread_cmd_.Init_cancel_step;
case Gfui_dlg_msg_.Btn_cancel: return Gfo_thread_cmd_.Init_cancel_all;
default: throw Exc_.new_unhandled(rslt);
}
}
usr_dlg.Prog_many(GRP_KEY, "download.bgn", "contacting web server: '~{0}'", src); // update progress; some servers (like WMF dump servers) are slow to respond
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_term() {
usr_dlg.Prog_many(GRP_KEY, "clear", "");
return download_pass;
}
public void Async_prog_run(int async_sleep_sum) {}
public boolean Async_running() {return xrg.Prog_running();}
public void Async_run() {Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_bldr_download, this, Invk_async_bgn).Start();}
private void Download() {
download_pass = true;
if (!xrg.Exec()) {
xrg.Prog_running_(false);
download_pass = false;
kit.Ask_ok(GRP_KEY, "download.fail", "download failed. Please select 'read from file' if you've already downloaded a dump: url=~{0} error=~{1}", src, xrg.Rslt_err_str());
}
} boolean download_pass = true;
protected gplx.ios.IoEngine_xrg_downloadFil xrg = Io_mgr.I.DownloadFil_args("", Io_url_.Empty);
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_async_bgn)) Download();
else if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_src_)) src = m.ReadStr("v");
else if (ctx.Match(k, Invk_trg_)) trg = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_async_bgn = "async_bgn", Invk_owner = "owner", Invk_src_ = "src_", Invk_trg_ = "trg_";
static final String GRP_KEY = "gfo.thread.file.download";
public static final String KEY = "file.download";
}

View File

@@ -0,0 +1,61 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*;
public class Gfo_thread_cmd_replace implements Gfo_thread_cmd {
public Gfo_thread_cmd Init(Gfo_usr_dlg usr_dlg, Gfui_kit kit, Io_url fil) {
this.usr_dlg = usr_dlg; this.kit = kit; this.fil = fil;
return this;
} Gfui_kit kit; Gfo_usr_dlg usr_dlg; Io_url fil;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_replace Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_replace Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public String Async_key() {return KEY;}
public void Cmd_ctor() {}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return false;}
@gplx.Virtual public byte Async_init() {
if (!Io_mgr.I.ExistsFil(fil)) {kit.Ask_ok(GRP_KEY, "file_missing", "File does not exist: '~{0}'", fil.Raw()); return Gfo_thread_cmd_.Init_cancel_step;}
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_term() {return true;}
public void Async_prog_run(int async_sleep_sum) {}
public boolean Async_running() {return false;}
@gplx.Virtual public void Async_run() {Exec_find_replace();} // NOTE: do not run async; if multiple commands for same file then they will not always work
public void Exec_find_replace() {
String raw = Io_mgr.I.LoadFilStr(fil);
int pairs_len = pairs.Count();
for (int i = 0; i < pairs_len; i++) {
KeyVal kv = (KeyVal)pairs.Get_at(i);
raw = String_.Replace(raw, kv.Key(), kv.Val_to_str_or_null());
}
Io_mgr.I.SaveFilStr(fil, raw);
usr_dlg.Prog_many(GRP_KEY, "done", "replace completed: ~{0} ~{1}", fil.Raw(), pairs_len);
}
public List_adp pairs = List_adp_.new_();
@gplx.Virtual public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_async_bgn)) Exec_find_replace();
else if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_fil_)) fil = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_add)) pairs.Add(KeyVal_.new_(m.ReadStr("find"), m.ReadStr("replace")));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_async_bgn = "async_bgn", Invk_owner = "owner", Invk_fil_ = "fil_", Invk_add = "add";
static final String GRP_KEY = "gfo.thread.file.download";
public static final String KEY = "text.replace";
}

View File

@@ -0,0 +1,115 @@
/*
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.threads; import gplx.*; import gplx.core.*;
import gplx.gfui.*; import gplx.xowa.bldrs.cmds.utils.*;
public class Gfo_thread_cmd_unzip implements Gfo_thread_cmd {
public Gfo_thread_cmd_unzip Init(Gfo_usr_dlg usr_dlg, Gfui_kit kit, ProcessAdp bzip2_process, ProcessAdp zip_process, ProcessAdp gz_process, Io_url src, Io_url trg) {
this.src = src; this.trg = trg; this.kit = kit; this.usr_dlg = usr_dlg;
unzip_wkr = new Xob_unzip_wkr().Init(bzip2_process, zip_process, gz_process).Process_run_mode_(ProcessAdp.Run_mode_async);
return this;
} private Io_url src, trg; private Gfui_kit kit; private Gfo_usr_dlg usr_dlg; private Xob_unzip_wkr unzip_wkr;
public GfoInvkAble Owner() {return owner;} public Gfo_thread_cmd_unzip Owner_(GfoInvkAble v) {owner = v; return this;} GfoInvkAble owner;
public void Cmd_ctor() {}
@gplx.Virtual public String Async_key() {return KEY;}
public Gfo_thread_cmd Async_next_cmd() {return next_cmd;} public void Async_next_cmd_(Gfo_thread_cmd v) {next_cmd = v;} Gfo_thread_cmd next_cmd;
public Bry_fmtr_eval_mgr Url_eval_mgr() {return url_eval_mgr;} public Gfo_thread_cmd_unzip Url_eval_mgr_(Bry_fmtr_eval_mgr v) {url_eval_mgr = v; return this;} Bry_fmtr_eval_mgr url_eval_mgr;
public int Async_sleep_interval() {return Gfo_thread_cmd_.Async_sleep_interval_1_second;}
public boolean Async_prog_enabled() {return true;}
public void Async_prog_run(int async_sleep_sum) {
String size_str = " please wait...";
if (trg.Type_fil()) size_str = gplx.ios.Io_size_.To_str(Io_mgr.I.QueryFil(trg).Size());
usr_dlg.Prog_many(GRP_KEY, "unzip", "unzipping: ~{0}", size_str);
}
@gplx.Virtual public byte Async_init() {
if (!Io_mgr.I.ExistsFil(src)) {
kit.Ask_ok(GRP_KEY, "source_missing", "Source file does not exist: '~{0}'", src.Raw());
return Gfo_thread_cmd_.Init_cancel_step;
}
trg_is_dir = trg.Type_dir();
if (delete_trg_if_exists
&& (( trg_is_dir && Io_mgr.I.ExistsDir(trg))
|| (!trg_is_dir && Io_mgr.I.ExistsFil(trg)))
) {
int rslt = kit.Ask_yes_no_cancel(GRP_KEY, "target_exists", "Target file already exists: '~{0}'.\nDo you want to delete it?", trg.Raw());
switch (rslt) {
case Gfui_dlg_msg_.Btn_yes: if (trg_is_dir) Io_mgr.I.DeleteDirDeep(trg); else Io_mgr.I.DeleteFil(trg); break;
case Gfui_dlg_msg_.Btn_no: return Gfo_thread_cmd_.Init_cancel_step;
case Gfui_dlg_msg_.Btn_cancel: return Gfo_thread_cmd_.Init_cancel_all;
}
}
return Gfo_thread_cmd_.Init_ok;
}
public boolean Async_running() {return unzip_wkr.Process_exit_code() == ProcessAdp.Exit_init;}
public void Async_run() {
usr_dlg.Prog_many(GRP_KEY, "bgn", "unzipping");
unzip_wkr.Decompress(src, trg);
}
public boolean Async_term() {
if (rename_dir) {
Io_url[] dirs = Io_mgr.I.QueryDir_args(trg.OwnerDir()).DirOnly_().Recur_(false).ExecAsUrlAry();
int dirs_len = dirs.length;
Io_url zip_dir = Io_url_.Empty;
for (int i = 0; i < dirs_len; i++) {
Io_url dir = dirs[i];
if (String_.Has_at_bgn(String_.Lower(dir.NameOnly()), String_.Lower(trg.NameOnly()))) { // HACK: check that directory starts with archive name; DATE:2013-12-22
zip_dir = dir;
break;
}
}
if (zip_dir == Io_url_.Empty) {
kit.Ask_ok(GRP_KEY, "rename.fail", "unable to find directory: trg=~{0}", trg.Raw());
return false;
}
if (!String_.Eq(String_.Lower(zip_dir.Raw()), String_.Lower(trg.Raw()))) // HACK: inkscape is itself
Io_mgr.I.MoveDirDeep(zip_dir, trg);
}
switch (term_cmd_for_src) {
case Term_cmd_for_src_noop: break;
case Term_cmd_for_src_delete: Io_mgr.I.DeleteFil(src); break;
case Term_cmd_for_src_move:
if (term_cmd_for_src_url == Io_url_.Empty) throw Exc_.new_("move specified, but no url");
Io_mgr.I.MoveFil_args(src, term_cmd_for_src_url, true).Exec();
break;
default: throw Exc_.new_unhandled(term_cmd_for_src);
}
usr_dlg.Prog_many(GRP_KEY, "done", "");
return true;
}
public static final byte Term_cmd_for_src_noop = 0, Term_cmd_for_src_delete = 1, Term_cmd_for_src_move = 2;
boolean rename_dir = false, trg_is_dir = false, delete_trg_if_exists = true;
public byte Term_cmd_for_src() {return term_cmd_for_src;} public void Term_cmd_for_src_(byte v) {term_cmd_for_src = v;} private byte term_cmd_for_src = Term_cmd_for_src_delete;
public Io_url Term_cmd_for_src_url() {return term_cmd_for_src_url;} public void Term_cmd_for_src_url_(Io_url v) {this.term_cmd_for_src_url = v;} Io_url term_cmd_for_src_url = Io_url_.Empty;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_owner)) return owner;
else if (ctx.Match(k, Invk_src_)) src = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_trg_)) trg = Bry_fmtr_eval_mgr_.Eval_url(url_eval_mgr, m.ReadBry("v"));
else if (ctx.Match(k, Invk_rename_dir_)) rename_dir = m.ReadYn("v");
else if (ctx.Match(k, Invk_delete_trg_if_exists_)) delete_trg_if_exists = m.ReadYn("v");
else if (ctx.Match(k, Invk_term_cmd_for_src_)) term_cmd_for_src = Term_cmd_for_src_parse_(m.ReadStr("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_owner = "owner", Invk_src_ = "src_", Invk_trg_ = "trg_", Invk_rename_dir_ = "rename_dir_", Invk_delete_trg_if_exists_ = "delete_trg_if_exists_", Invk_term_cmd_for_src_ = "term_cmd_for_src_";
private static byte Term_cmd_for_src_parse_(String s) {
if (String_.Eq(s, "noop")) return Term_cmd_for_src_noop;
else if (String_.Eq(s, "delete")) return Term_cmd_for_src_delete;
else if (String_.Eq(s, "move")) return Term_cmd_for_src_move;
else throw Exc_.new_unhandled(s);
}
static final String GRP_KEY = "xowa.thread.file.unzip";
public static final String KEY = "file.unzip";
}

View File

@@ -0,0 +1,62 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public class Gfo_thread_pool implements GfoInvkAble {
private Object thread_lock = new Object();
private List_adp queue = List_adp_.new_();
private GfoMsg run_msg = GfoMsg_.new_cast_(Invk_run_wkr);
private boolean running = false;
public Gfo_usr_dlg Usr_dlg() {return usr_dlg;} public Gfo_thread_pool Usr_dlg_(Gfo_usr_dlg v) {usr_dlg = v; return this;} private Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.Noop;
public void Clear() {synchronized (thread_lock) {queue.Clear(); running = false;}}
public Gfo_thread_pool Add_at_end(Gfo_thread_wkr wkr) {
synchronized (thread_lock) {queue.Add(wkr);}
return this;
}
public void Resume() {
synchronized (thread_lock) {
running = false;
}
this.Run();
}
public void Run() {
Gfo_thread_wkr wkr = null;
synchronized (thread_lock) {
if (running) return; // already running; discard run request and rely on running-wkr to call Run when done
int len = queue.Count(); if (len == 0) return; // nothing in list; occurs when last item calls Run when done
running = true;
wkr = (Gfo_thread_wkr)List_adp_.Pop_first(queue);
}
Thread_adp_.Run_invk_msg(wkr.Name(), this, run_msg.Clear().Add("v", wkr));
}
private void Run_wkr(Gfo_thread_wkr wkr) {
try {wkr.Exec();}
catch (Exception e) {
usr_dlg.Warn_many("", "", "uncaught exception while running thread; name=~{0} err=~{1}", wkr.Name(), Err_.Message_gplx_brief(e));
}
finally {
if (wkr.Resume())
this.Resume();
}
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_run_wkr)) Run_wkr((Gfo_thread_wkr)m.ReadObj("v"));
else return GfoInvkAble_.Rv_unhandled;
return this;
}
private static final String Invk_run_wkr = "run_wkr";
}

View File

@@ -0,0 +1,23 @@
/*
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.threads; import gplx.*; import gplx.core.*;
public interface Gfo_thread_wkr {
String Name();
void Exec();
boolean Resume();
}

View File

@@ -0,0 +1,151 @@
/*
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.xmls; import gplx.*; import gplx.core.*;
public class Gfo_xml_wtr {
private final Bry_bfr bfr = Bry_bfr.reset_(255), txt_bfr = Bry_bfr.reset_(32);
private byte quote_byte = Byte_ascii.Apos;
private byte[] quote_escape = Bry_quote_1_escape;
private List_adp nde_stack = List_adp_.new_();
private Gfo_xml_nde nde_cur = null;
private int indent = 0;
public void Quote_(boolean apos) {
if (apos) {
this.quote_byte = Byte_ascii.Apos;
this.quote_escape = Bry_quote_1_escape;
}
else {
this.quote_byte = Byte_ascii.Quote;
this.quote_escape = Bry_quote_2_escape;
}
}
public Gfo_xml_wtr Nde_lhs_bgn_grp(String v) {return Nde_lhs_bgn(Bool_.Y, v);}
public Gfo_xml_wtr Nde_lhs_bgn_itm(String v) {return Nde_lhs_bgn(Bool_.N, v);}
private Gfo_xml_wtr Nde_lhs_bgn(boolean grp, String v) {
nde_cur = new Gfo_xml_nde(grp, v);
nde_stack.Add(nde_cur);
bfr.Add_byte_repeat(Byte_ascii.Space, indent);
bfr.Add_byte(Byte_ascii.Angle_bgn).Add_str_u8(v);
indent += 2;
return this;
}
public Gfo_xml_wtr Nde_lhs_end() {
bfr.Add_byte(Byte_ascii.Angle_end);
if (nde_cur.Grp()) bfr.Add_byte_nl();
return this;
}
public Gfo_xml_wtr Nde_lhs(String v) {return Nde_lhs(Bool_.Y, v);}
private Gfo_xml_wtr Nde_lhs(boolean grp, String v) {
this.Nde_lhs_bgn(grp, v);
this.Nde_lhs_end();
return this;
}
public Gfo_xml_wtr Nde_rhs() {
Gfo_xml_nde nde = (Gfo_xml_nde)List_adp_.Pop(nde_stack);
indent -= 2;
if (nde.Grp()) bfr.Add_byte_repeat(Byte_ascii.Space, indent);
bfr.Add(Bry_nde_rhs_bgn).Add_str_u8(nde.Name()).Add_byte(Byte_ascii.Angle_end); // EX: </node>
bfr.Add_byte_nl();
return this;
}
public Gfo_xml_wtr Nde_txt_str(String name, String text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_str_u8(text);
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Nde_txt_bry(String name, byte[] text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_bry(text);
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Nde_txt_int(String name, int text) {
this.Nde_lhs(Bool_.N, name);
this.Txt_bry(Int_.Xto_bry(text));
this.Nde_rhs();
return this;
}
public Gfo_xml_wtr Atr_bgn(String key) {
bfr.Add_byte_space().Add_str_u8(key).Add_byte(Byte_ascii.Eq).Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Atr_val_str_a7(String v) {bfr.Add_str_a7(v); return this;}
public Gfo_xml_wtr Atr_val_str_u8(String v) {bfr.Add_str_u8 (v); return this;}
public Gfo_xml_wtr Atr_val_bry (byte[] v) {bfr.Add(v); return this;}
public Gfo_xml_wtr Atr_val_int (int v) {bfr.Add_int_variable(v); return this;}
public Gfo_xml_wtr Atr_end() {
bfr.Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Atr_kv_int(String key, int val) {return Atr_kv_bry(key, Int_.Xto_bry(val));}
public Gfo_xml_wtr Atr_kv_str_a7(String key, String val) {return Atr_kv_bry(key, Bry_.new_a7(val));}
public Gfo_xml_wtr Atr_kv_str_u8(String key, String val) {return Atr_kv_bry(key, Bry_.new_u8(val));}
public Gfo_xml_wtr Atr_kv_bry(String key, byte[] val) {
bfr.Add_byte_space().Add_str_u8(key);
bfr.Add_byte(Byte_ascii.Eq);
Atr_val_quote(val);
return this;
}
private Gfo_xml_wtr Atr_val_quote(byte[] val_bry) {
bfr.Add_byte(quote_byte);
bfr.Add_bry_escape(quote_byte, quote_escape, val_bry, 0, val_bry.length);
bfr.Add_byte(quote_byte);
return this;
}
public Gfo_xml_wtr Txt_bry(byte[] txt) {
int len = txt.length;
boolean dirty = false;
for (int i = 0; i < len; ++i) {
byte[] escape = null;
byte b = txt[i];
switch (b) {
case Byte_ascii.Lt: escape = Bry_escape_lt; break;
case Byte_ascii.Gt: escape = Bry_escape_gt; break;
case Byte_ascii.Amp: escape = Bry_escape_amp; break;
default: break;
}
if (escape != null && !dirty) {
bfr.Add_mid(txt, 0, i);
dirty = true;
}
if (dirty) {
if (escape == null) bfr.Add_byte(b);
else bfr.Add(escape);
}
}
if (dirty) bfr.Add_bfr_and_clear(txt_bfr);
else bfr.Add(txt);
return this;
}
public Gfo_xml_wtr Txt_str_u8(String txt) {return Txt_bry(Bry_.new_u8(txt));}
public String Bld_str() {return bfr.Xto_str_and_clear();}
private static final byte[]
Bry_nde_rhs_bgn = Bry_.new_a7("</")
// , Bry_nde_inline = Bry_.new_a7("/>")
, Bry_quote_1_escape = Bry_.new_a7("&apos;")
, Bry_quote_2_escape = Bry_.new_a7("&quot;")
, Bry_escape_lt = Bry_.new_a7("&lt;")
, Bry_escape_gt = Bry_.new_a7("&gt;")
, Bry_escape_amp = Bry_.new_a7("&amp;")
;
}
class Gfo_xml_nde {
public Gfo_xml_nde(boolean grp, String name) {this.grp = grp; this.name = name;}
public boolean Grp() {return grp;} private final boolean grp;
public String Name() {return name;} private final String name;
}

View File

@@ -0,0 +1,81 @@
/*
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.xmls; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Gfo_xml_wtr_tst {
private final Gfo_xml_wtr_fxt fxt = new Gfo_xml_wtr_fxt();
@Before public void init() {}
@Test public void Root() {
fxt.Wtr().Nde_lhs("a").Nde_rhs();
fxt.Test_bld("<a>", "</a>");
}
@Test public void Nest() {
fxt.Wtr()
.Nde_lhs("a")
. Nde_lhs("a_a")
. Nde_lhs("a_a_a")
. Nde_rhs()
. Nde_rhs()
.Nde_rhs()
;
fxt.Test_bld
( "<a>"
, " <a_a>"
, " <a_a_a>"
, " </a_a_a>"
, " </a_a>"
, "</a>"
);
}
@Test public void Atrs() {
fxt.Wtr()
.Nde_lhs_bgn_itm("a")
.Atr_kv_str_a7("b", "b1")
.Nde_lhs_end()
.Nde_rhs()
;
fxt.Test_bld("<a b='b1'></a>");
}
@Test public void Atrs_escape() {
fxt.Wtr()
.Nde_lhs_bgn_itm("a")
.Atr_kv_str_a7("b", "'\"<>&")
.Nde_lhs_end()
.Nde_rhs()
;
fxt.Test_bld("<a b='&apos;\"<>&'></a>");
}
@Test public void Nde_txt() {
fxt.Wtr()
.Nde_txt_str("a", "a123")
;
fxt.Test_bld("<a>a123</a>");
}
@Test public void Nde_txt_escape() {
fxt.Wtr()
.Nde_txt_str("a", "'\"<>&x")
;
fxt.Test_bld("<a>'\"&lt;&gt;&amp;x</a>");
}
}
class Gfo_xml_wtr_fxt {
public Gfo_xml_wtr Wtr() {return wtr;} private final Gfo_xml_wtr wtr = new Gfo_xml_wtr();
public void Test_bld(String... lines) {
Tfds.Eq_str_lines(String_.Concat_lines_nl_skip_last(lines), wtr.Bld_str());
}
}