mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.7.2.1
This commit is contained in:
113
400_xowa/src_060_utl/gplx/App_cmd_arg.java
Normal file
113
400_xowa/src_060_utl/gplx/App_cmd_arg.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class App_cmd_arg {
|
||||
App_cmd_arg(byte tid, byte val_tid, String key, boolean reqd) {this.tid = tid; this.val_tid = val_tid; this.key = key; this.reqd = reqd;}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
public byte Val_tid() {return val_tid;} public App_cmd_arg Val_tid_(byte v) {val_tid = v; return this;} private byte val_tid;
|
||||
public String Val_tid_str() {
|
||||
switch (val_tid) {
|
||||
case Val_tid_string: return "string";
|
||||
case Val_tid_yn: return "yes_no";
|
||||
case Val_tid_url: return "path";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
public String Key() {return key;} private String key;
|
||||
public boolean Reqd() {return reqd;} private boolean reqd;
|
||||
public String Reqd_str() {return reqd ? "required" : "optional";}
|
||||
public boolean Dirty() {return dirty;} public App_cmd_arg Dirty_(boolean v) {this.dirty = v; return this;} private boolean dirty;
|
||||
public String Note() {return note;} public App_cmd_arg Note_(String v) {note = v; return this;} private String note;
|
||||
public String Example() {return example;}
|
||||
public App_cmd_arg Example_(String v) {example = v; return this;} private String example;
|
||||
public App_cmd_arg Example_url_(String v) {
|
||||
Example_(v);
|
||||
val_tid = Val_tid_url;
|
||||
return this;
|
||||
}
|
||||
public App_cmd_arg Example_list_str_(String v) {
|
||||
example = String_.ConcatWith_any(" ", v);
|
||||
val_tid = Val_tid_list_string;
|
||||
return this;
|
||||
}
|
||||
public Object Val() {return val;} public App_cmd_arg Val_(Object v) {this.val = v; return this;} Object val;
|
||||
public Object Dflt() {return dflt;} public App_cmd_arg Dflt_(Object v) {dflt = v; return this;} Object dflt;
|
||||
public boolean Val_as_bool() {return Bool_.cast_(val);}
|
||||
public String Val_as_str_or(String or) {return val == null ? or : (String)val;}
|
||||
public String Val_as_str() {return (String)val;}
|
||||
public int Val_as_int_or(int or) {return val == null ? or : Int_.parse_or_((String)val, or);}
|
||||
public Io_url Val_as_url_rel_dir_or(Io_url owner_dir, Io_url or) {return Val_as_url_rel_url_or(owner_dir, or, true);}
|
||||
public Io_url Val_as_url_rel_fil_or(Io_url owner_dir, Io_url or) {return Val_as_url_rel_url_or(owner_dir, or, false);}
|
||||
public Io_url Val_as_url_rel_url_or(Io_url owner_dir, Io_url or, boolean dir) {return Val_as_url_rel_url_or(Val_as_str(), owner_dir, or, dir);}
|
||||
public boolean Parse(App_cmd_mgr mgr, String[] s_ary) {
|
||||
dirty = true;
|
||||
String s = s_ary.length == 0 ? "" : s_ary[0];
|
||||
switch (val_tid) {
|
||||
case Val_tid_string:
|
||||
val = s;
|
||||
break;
|
||||
case Val_tid_url: // NOTE: do not parse urls as it can either be absolute (C:\dir\fil.txt) or relative (fil.txt). relative cannot be parsed without knowing owner dir
|
||||
val = s;
|
||||
break;
|
||||
case Val_tid_yn:
|
||||
int v_int = Yn.parse_as_int(s);
|
||||
if (v_int == Bool_.__int) {return mgr.Errs_add(Err_parse_yn, "value must be either y or n: ~{0}", s);}
|
||||
val = v_int == Bool_.Y_int;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} public static final String Err_parse_yn = "parse_yn";
|
||||
public App_cmd_arg Clone() {
|
||||
App_cmd_arg rv = new App_cmd_arg(tid, val_tid, key, reqd);
|
||||
rv.val = val;
|
||||
rv.dflt = dflt;
|
||||
rv.note = note;
|
||||
rv.example = example;
|
||||
return rv;
|
||||
}
|
||||
public static App_cmd_arg req_(String key) {return new App_cmd_arg(Tid_general, Val_tid_string, key, true);}
|
||||
public static App_cmd_arg opt_(String key) {return new App_cmd_arg(Tid_general, Val_tid_string, key, false);}
|
||||
public static App_cmd_arg new_(String key, boolean reqd) {return new App_cmd_arg(Tid_general, Val_tid_string, key, reqd);}
|
||||
public static App_cmd_arg sys_help_() {return sys_help_("help");}
|
||||
public static App_cmd_arg sys_help_(String key) {return new App_cmd_arg(Tid_help, Val_tid_string, key, false);}
|
||||
public static App_cmd_arg sys_header_(String key) {return new App_cmd_arg(Tid_header, Val_tid_yn, key, false);}
|
||||
public static App_cmd_arg sys_args_(String key) {return new App_cmd_arg(Tid_args, Val_tid_yn, key, false);}
|
||||
public static final byte Tid_general = 0, Tid_help = 1, Tid_header = 2, Tid_args = 3;
|
||||
public static final byte Val_tid_string = 0, Val_tid_yn = 1, Val_tid_url = 2, Val_tid_list_string = 3;
|
||||
|
||||
public static Io_url Val_as_url_rel_url_or(String val_str, Io_url owner_dir, Io_url or, boolean dir) {
|
||||
if (val_str == null) return or;
|
||||
byte val_has_dir = Op_sys.Tid_nil; // if val_str is dir, use it literally (only checking for closing dir_spr); if it's just a name, assume a simple relative path
|
||||
if (String_.Has(val_str, Op_sys.Lnx.Fsys_dir_spr_str()))
|
||||
val_has_dir = Op_sys.Tid_lnx;
|
||||
else if (String_.Has(val_str, Op_sys.Wnt.Fsys_dir_spr_str()))
|
||||
val_has_dir = Op_sys.Tid_wnt;
|
||||
if (val_has_dir != Op_sys.Tid_nil) {
|
||||
if (dir) { // NOTE: need to do extra logic to guarantee trailing "/"; JAVA:7 apparently strips "/dir/" to "/dir" when passed in as argument; DATE:2013-03-20
|
||||
String val_dir_spr = val_has_dir == Op_sys.Tid_lnx ? Op_sys.Lnx.Fsys_dir_spr_str() : Op_sys.Wnt.Fsys_dir_spr_str();
|
||||
if (!String_.Has_at_end(val_str, val_dir_spr))
|
||||
val_str += val_dir_spr;
|
||||
return Io_url_.new_dir_(val_str);
|
||||
}
|
||||
else
|
||||
return Io_url_.new_fil_(val_str);
|
||||
}
|
||||
else
|
||||
return dir ? owner_dir.GenSubDir(val_str) : owner_dir.GenSubFil(val_str);
|
||||
}
|
||||
}
|
||||
162
400_xowa/src_060_utl/gplx/App_cmd_mgr.java
Normal file
162
400_xowa/src_060_utl/gplx/App_cmd_mgr.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*;
|
||||
public class App_cmd_mgr {
|
||||
private Ordered_hash expd_args = Ordered_hash_.new_(), actl_args = Ordered_hash_.new_();
|
||||
private List_adp tmp_vals = List_adp_.new_(); private String[] orig_ary;
|
||||
public App_cmd_mgr Msg_root_(Gfo_msg_root v) {msg_root = v; return this;} private Gfo_msg_root msg_root = Gfo_msg_root._;
|
||||
public String Arg_prefix() {return arg_prefix;} public App_cmd_mgr Arg_prefix_(String v) {arg_prefix = v; prefix_len = String_.Len(v); return this;} private String arg_prefix = "--"; int prefix_len = 2;
|
||||
public void Clear() {expd_args.Clear(); actl_args.Clear(); errs.Clear(); key_help = key_header = null;}
|
||||
public int Actl_len() {return actl_args.Count();}
|
||||
public App_cmd_arg[] Actl_ary() {return (App_cmd_arg[])actl_args.To_ary(App_cmd_arg.class);}
|
||||
public App_cmd_mgr Expd_add_many(App_cmd_arg... ary) {for (App_cmd_arg o : ary) Expd_add(o); return this;}
|
||||
public App_cmd_mgr Expd_add(App_cmd_arg prm) {
|
||||
expd_args.Add(prm.Key(), prm);
|
||||
switch (prm.Tid()) {
|
||||
case App_cmd_arg.Tid_help: key_help = prm.Key(); break;
|
||||
case App_cmd_arg.Tid_header: key_header = prm.Key(); break;
|
||||
case App_cmd_arg.Tid_args: key_args = prm.Key(); break;
|
||||
}
|
||||
return this;
|
||||
} String key_help, key_header, key_args;
|
||||
public boolean Args_process(String[] ary) {Args_parse(ary); return errs.Count() == 0;}
|
||||
private void Args_parse(String[] ary) {
|
||||
this.orig_ary = ary;
|
||||
App_cmd_arg arg = null;
|
||||
int ary_len = ary.length;
|
||||
actl_args = Expd_copy();
|
||||
errs.Clear(); tmp_vals.Clear();
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
String itm = ary[i];
|
||||
if (String_.Has_at_bgn(itm, arg_prefix)) { // key
|
||||
if (arg != null) {
|
||||
String[] tmp_ary = tmp_vals.To_str_ary();
|
||||
if (!arg.Parse(this, tmp_ary)) {continue;}
|
||||
tmp_vals.Clear();
|
||||
}
|
||||
String key = String_.Mid(itm, prefix_len);
|
||||
Object o = actl_args.Get_by(key);
|
||||
if (o == null) {Errs_add(Err_argument_is_unknown, "unknown argument: '~{0}'", key); continue;}
|
||||
arg = (App_cmd_arg)o;
|
||||
if (arg.Dirty()) {Errs_add(Err_argument_is_duplicate, "duplicate argument: '~{0}'", key); continue;}
|
||||
arg.Dirty_(true);
|
||||
}
|
||||
else {
|
||||
if (arg == null) {Errs_add(Err_argument_is_invalid_key, "argument key must be prefixed with '~{0}'; EX: '~{0}~{1}'", arg_prefix, itm); continue;} // should only happen if 1st itm is not "--%"
|
||||
// if (arg.Val() != null) return Errs_add("argument_is_already_valued", "argument can only take one value: '{0}'", itm);
|
||||
tmp_vals.Add(itm);
|
||||
}
|
||||
}
|
||||
if (arg != null) {
|
||||
String[] tmp_ary = tmp_vals.To_str_ary();
|
||||
arg.Parse(this, tmp_ary);
|
||||
tmp_vals.Clear();
|
||||
}
|
||||
int len = actl_args.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
arg = (App_cmd_arg)actl_args.Get_at(i);
|
||||
if (arg.Reqd() && !arg.Dirty()) {Errs_add(Err_argument_is_required, "argument is required: '~{0}'", arg.Key()); continue;}
|
||||
if (!arg.Dirty() && arg.Dflt() != null) arg.Val_(arg.Dflt());
|
||||
}
|
||||
} public static final String Err_argument_is_duplicate = "argument_is_duplicate", Err_argument_is_required = "argument_is_required", Err_argument_is_unknown = "argument_is_unknown", Err_argument_is_invalid_key = "argument_is_invalid_key";
|
||||
public String Fmt_hdr() {return fmt_hdr;} public App_cmd_mgr Fmt_hdr_(String v) {fmt_hdr = v; return this;} private String fmt_hdr = "";
|
||||
public App_cmd_arg Args_get(String key) {return (App_cmd_arg)actl_args.Get_by(key);}
|
||||
public boolean Args_has_help() {
|
||||
App_cmd_arg arg = (App_cmd_arg)actl_args.Get_by(key_help);
|
||||
return arg != null && arg.Dirty();
|
||||
}
|
||||
public App_cmd_mgr Print_header(Gfo_usr_dlg usr_dlg) {
|
||||
App_cmd_arg arg_hdr = (App_cmd_arg)actl_args.Get_by(key_header);
|
||||
if (arg_hdr == null) return this; // no key_header specified; assume header shouldn't be printed
|
||||
if (!arg_hdr.Val_as_bool()) return this; // key_header specified as false; return;
|
||||
usr_dlg.Note_gui_none(GRP_KEY, "print.header", fmt_hdr);
|
||||
return this;
|
||||
}
|
||||
public void Print_args(Gfo_usr_dlg usr_dlg) {
|
||||
sb.Add_char_crlf();
|
||||
sb.Add_str_w_crlf("arguments:");
|
||||
int len = orig_ary.length;
|
||||
if (len == 0) {
|
||||
sb.Add_fmt_line(" **** NONE ****");
|
||||
sb.Add_fmt_line(" use --help to show help");
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++)
|
||||
sb.Add_fmt_line(" [{0}] = '{1}'", i, orig_ary[i]);
|
||||
}
|
||||
usr_dlg.Note_none(GRP_KEY, "print.args", sb.Xto_str_and_clear());
|
||||
} String_bldr sb = String_bldr_.new_();
|
||||
public void Print_fail(Gfo_usr_dlg usr_dlg) {
|
||||
sb.Add("** error: ").Add_char_crlf();
|
||||
int len = errs.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_msg_data data = (Gfo_msg_data)errs.Get_at(i);
|
||||
sb.Add_fmt_line(" " + data.Gen_str_ary());
|
||||
}
|
||||
sb.Add_char_crlf();
|
||||
sb.Add_str_w_crlf(String_.Repeat("-", 80));
|
||||
usr_dlg.Note_none(GRP_KEY, "print.fail", sb.Xto_str_and_clear());
|
||||
}
|
||||
public void Print_help(Gfo_usr_dlg usr_dlg, String app_name) {
|
||||
sb.Add_str_w_crlf("example:");
|
||||
sb.Add_fmt(" java -jar {0}.jar", app_name);
|
||||
int key_max = 0, tid_max = 0;
|
||||
int len = expd_args.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
App_cmd_arg arg = (App_cmd_arg)expd_args.Get_at(i);
|
||||
if (arg.Tid() != App_cmd_arg.Tid_general) continue; // skip header, help
|
||||
sb.Add(" ").Add(arg_prefix).Add(arg.Key()).Add(" ").Add(arg.Example());
|
||||
int key_len = String_.Len(arg.Key()); if (key_len > key_max) key_max = key_len;
|
||||
int tid_len = String_.Len(String_.Format("[{0}:{1}]", arg.Reqd_str(), arg.Val_tid_str())); if (tid_len > tid_max) tid_max = tid_len;
|
||||
} sb.Add_char_crlf();
|
||||
sb.Add_char_crlf();
|
||||
sb.Add_str_w_crlf("detail:");
|
||||
for (int i = 0; i < len; i++) {
|
||||
App_cmd_arg arg = (App_cmd_arg)expd_args.Get_at(i);
|
||||
// if (arg.Tid() != App_cmd_arg.Tid_general) continue; // skip header, help
|
||||
sb.Add(" ").Add(arg_prefix).Add(String_.PadEnd(arg.Key(), key_max + 1, " ")).Add(String_.PadEnd(String_.Format("[{0}:{1}]", arg.Reqd_str(), arg.Val_tid_str()), tid_max, " "));
|
||||
if (arg.Dflt() != null)
|
||||
sb.Add_fmt(" default={0}", arg.Dflt());
|
||||
sb.Add_char_crlf();
|
||||
if (arg.Note() != null)
|
||||
sb.Add(" ").Add(arg.Note()).Add_char_crlf();
|
||||
// for (int j = 0; j < arg.Itms().Count(); j++) {
|
||||
// App_arg_info expdInf = (App_arg_info)arg.Itms().Get_at(j);
|
||||
// sb.Add(" ").Add(String_.PadEnd(expdInf.Key(), key_max + 1, " ")).Add_str_w_crlf(expdInf.Descrip());
|
||||
// }
|
||||
}
|
||||
usr_dlg.Note_gui_none(GRP_KEY, "print.info", sb.Xto_str_and_clear());
|
||||
}
|
||||
private Ordered_hash Expd_copy() {
|
||||
Ordered_hash rv = Ordered_hash_.new_();
|
||||
int expd_len = expd_args.Count();
|
||||
for (int i = 0 ; i < expd_len; i++) {
|
||||
App_cmd_arg arg = (App_cmd_arg)expd_args.Get_at(i);
|
||||
rv.Add(arg.Key(), arg.Clone());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public boolean Errs_add(String key, String fmt, Object... vals) {
|
||||
errs.Add(msg_root.Data_new_many(Gfo_msg_itm_.Cmd_warn, GRP_KEY, key, fmt, vals));
|
||||
return false;
|
||||
}
|
||||
public int Errs_len() {return errs.Count();} private List_adp errs = List_adp_.new_();
|
||||
public Gfo_msg_data Errs_get(int i) {return (Gfo_msg_data)errs.Get_at(i);}
|
||||
private static final String GRP_KEY = "gplx.app.app_cmd_mgr";
|
||||
}
|
||||
142
400_xowa/src_060_utl/gplx/App_cmd_mgr_tst.java
Normal file
142
400_xowa/src_060_utl/gplx/App_cmd_mgr_tst.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class App_cmd_mgr_tst {
|
||||
App_cmd_mgr_fxt fxt = new App_cmd_mgr_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
@Test public void Basic() {
|
||||
fxt .Expd_(fxt.arg_("a"), fxt.arg_("b"))
|
||||
.Args_process("--a", "0", "--b", "1")
|
||||
.Tst_errs_none()
|
||||
.Tst_actl(fxt.chkr_("a", "0"), fxt.chkr_("b", "1"));
|
||||
;
|
||||
}
|
||||
@Test public void Dflt() {
|
||||
fxt .Expd_(fxt.arg_("a").Val_tid_(App_cmd_arg.Val_tid_yn).Dflt_(true));
|
||||
fxt .Args_process("--a", "n").Tst_actl(fxt.chkr_("a", false)); // if val, use it
|
||||
fxt .Args_process().Tst_actl(fxt.chkr_("a", true)); // if no val, use default
|
||||
}
|
||||
@Test public void Header_y() {
|
||||
fxt.Expd_(App_cmd_arg.sys_header_("print_license")).Args_process("--print_license", "y");
|
||||
fxt.Mgr().Fmt_hdr_("test_hdr").Print_header(fxt.Usr_dlg());
|
||||
fxt.tst_write("test_hdr");
|
||||
fxt.Clear();
|
||||
}
|
||||
@Test public void Header_n() {
|
||||
fxt.Expd_(App_cmd_arg.sys_header_("print_license")).Args_process("--print_license", "n");
|
||||
fxt.Mgr().Fmt_hdr_("test_hdr").Print_header(fxt.Usr_dlg());
|
||||
fxt.tst_write();
|
||||
}
|
||||
// @Test public void Help_y() {
|
||||
// fxt.Expd_(App_cmd_arg.sys_header_("help")).Args_process("--help");
|
||||
//// fxt.Mgr().Fmt_help_grp("bgn ~{args} end").Fmt_help_itm_("~{0} ~{1}").Print_header(fxt.Status_mgr());
|
||||
//// fxt.Tst_write("test_hdr");
|
||||
// fxt.Clear();
|
||||
// }
|
||||
@Test public void Err_parse_yn() {
|
||||
fxt .Expd_(fxt.arg_("a").Val_tid_(App_cmd_arg.Val_tid_yn))
|
||||
.Args_process("--a", "x")
|
||||
.Tst_errs(App_cmd_arg.Err_parse_yn);
|
||||
;
|
||||
}
|
||||
@Test public void Err_reqd() {
|
||||
fxt .Expd_(fxt.arg_("a", true), fxt.arg_("b", false))
|
||||
.Args_process("--b", "1")
|
||||
.Tst_errs(App_cmd_mgr.Err_argument_is_required);
|
||||
;
|
||||
}
|
||||
@Test public void Err_dupe() {
|
||||
fxt .Expd_(fxt.arg_("a"))
|
||||
.Args_process("--a", "0", "--a", "0")
|
||||
.Tst_errs(App_cmd_mgr.Err_argument_is_duplicate);
|
||||
;
|
||||
}
|
||||
@Test public void Err_unknown() {
|
||||
fxt .Expd_(fxt.arg_("a"))
|
||||
.Args_process("--b")
|
||||
.Tst_errs(App_cmd_mgr.Err_argument_is_unknown);
|
||||
;
|
||||
}
|
||||
@Test public void Err_key_invalid() {
|
||||
fxt .Expd_(fxt.arg_("a"))
|
||||
.Args_process("a")
|
||||
.Tst_errs(App_cmd_mgr.Err_argument_is_invalid_key);
|
||||
;
|
||||
}
|
||||
@Test public void Val_as_url_rel_dir_or() { // PURPOSE: "/xowa" -> "/xowa/"
|
||||
String root_dir = Op_sys.Cur().Tid_is_wnt() ? "C:\\" : "/", dir_spr = Op_sys.Cur().Fsys_dir_spr_str();
|
||||
Tst_val_as_url_rel_dir_or(root_dir, dir_spr, root_dir + "sub" , root_dir + "sub" + dir_spr); // /sub -> /sub/
|
||||
Tst_val_as_url_rel_dir_or(root_dir, dir_spr, root_dir + "sub" + dir_spr , root_dir + "sub" + dir_spr); // /sub/ -> /sub/
|
||||
Tst_val_as_url_rel_dir_or(root_dir, dir_spr, "sub" , root_dir + "dir" + dir_spr + "sub" + dir_spr); // sub -> /dir/sub/
|
||||
}
|
||||
private void Tst_val_as_url_rel_dir_or(String root_dir, String dir_spr, String val, String expd) {
|
||||
Io_url actl = fxt.arg_("key").Val_(val).Val_as_url_rel_dir_or(Io_url_.new_dir_(root_dir).GenSubDir("dir"), null);
|
||||
Tfds.Eq(expd, actl.Raw());
|
||||
}
|
||||
}
|
||||
class App_cmd_mgr_fxt {
|
||||
public Gfo_usr_dlg Usr_dlg() {return usr_dlg;} Gfo_usr_dlg usr_dlg;
|
||||
public App_cmd_mgr Mgr() {return mgr;} App_cmd_mgr mgr = new App_cmd_mgr(); Tst_mgr tst_mgr = new Tst_mgr();
|
||||
public App_cmd_mgr_fxt Clear() {
|
||||
if (usr_dlg == null) {
|
||||
usr_dlg = Gfo_usr_dlg_.Test();
|
||||
}
|
||||
mgr.Clear();
|
||||
usr_dlg.Gui_wkr().Clear();
|
||||
return this;
|
||||
}
|
||||
public App_cmd_arg arg_(String key) {return arg_(key, false);}
|
||||
public App_cmd_arg arg_(String key, boolean reqd) {return App_cmd_arg.new_(key, reqd);}
|
||||
public App_cmd_arg_chkr chkr_(String key, Object val) {return new App_cmd_arg_chkr(key, val);}
|
||||
public App_cmd_mgr_fxt Expd_(App_cmd_arg... v) {mgr.Expd_add_many(v); return this;}
|
||||
public App_cmd_mgr_fxt Args_process(String... v) {mgr.Args_process(v); return this;}
|
||||
public App_cmd_mgr_fxt Tst_actl_len(int v) {Tfds.Eq(v, mgr.Actl_len()); return this;}
|
||||
public App_cmd_mgr_fxt Tst_actl(App_cmd_arg_chkr... expd) {
|
||||
App_cmd_arg[] actl = mgr.Actl_ary();
|
||||
tst_mgr.Tst_ary("", expd, actl);
|
||||
return this;
|
||||
}
|
||||
public App_cmd_mgr_fxt Tst_errs_none() {return Tst_errs(String_.Ary_empty);}
|
||||
public App_cmd_mgr_fxt Tst_errs(String... expd) {
|
||||
int len = mgr.Errs_len();
|
||||
String[] actl = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_msg_data data = mgr.Errs_get(i);
|
||||
actl[i] = data.Item().Key_str();
|
||||
}
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
return this;
|
||||
}
|
||||
public App_cmd_mgr_fxt tst_write(String... expd) {
|
||||
String[] actl = ((Gfo_usr_dlg__gui_test)usr_dlg.Gui_wkr()).Xto_str_ary();
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class App_cmd_arg_chkr implements Tst_chkr {
|
||||
public App_cmd_arg_chkr(String key, Object val) {this.key = key; this.val = val;} private String key; Object val;
|
||||
public Class<?> TypeOf() {return App_cmd_arg.class;}
|
||||
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
|
||||
App_cmd_arg actl = (App_cmd_arg)actl_obj;
|
||||
int err = 0;
|
||||
err += mgr.Tst_val(false, path, "key", key, actl.Key());
|
||||
err += mgr.Tst_val(false, path, "val", val, actl.Val());
|
||||
return err;
|
||||
}
|
||||
}
|
||||
35
400_xowa/src_060_utl/gplx/Bry_cache.java
Normal file
35
400_xowa/src_060_utl/gplx/Bry_cache.java
Normal 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;
|
||||
import gplx.core.primitives.*;
|
||||
public class Bry_cache {
|
||||
public byte[] Get_or_new(String v) {return Get_or_new(Bry_.new_u8(v));}
|
||||
public byte[] Get_or_new(byte[] v) {
|
||||
if (v.length == 0) return Bry_.Empty;
|
||||
Object rv = hash.Get_by(hash_ref.Val_(v));
|
||||
if (rv == null) {
|
||||
Bry_obj_ref bry = Bry_obj_ref.new_(v);
|
||||
hash.Add_as_key_and_val(bry);
|
||||
return v;
|
||||
}
|
||||
else
|
||||
return ((Bry_obj_ref)rv).Val();
|
||||
}
|
||||
Hash_adp hash = Hash_adp_.new_(); Bry_obj_ref hash_ref = Bry_obj_ref.null_();
|
||||
public static final Bry_cache _ = new Bry_cache(); Bry_cache() {}
|
||||
}
|
||||
34
400_xowa/src_060_utl/gplx/ByteAryAry_chkr.java
Normal file
34
400_xowa/src_060_utl/gplx/ByteAryAry_chkr.java
Normal 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;
|
||||
public class ByteAryAry_chkr implements Tst_chkr {
|
||||
public Class<?> TypeOf() {return byte[][].class;}
|
||||
public ByteAryAry_chkr Val_(byte[][] v) {ary = v; return this;} byte[][] ary;
|
||||
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
|
||||
byte[][] actl = (byte[][])actl_obj;
|
||||
int actl_len = actl.length;
|
||||
int expd_len = ary.length;
|
||||
int err = 0;
|
||||
err += mgr.Tst_val(true, path, "len", ary.length, actl_len);
|
||||
for (int i = 0; i < expd_len; i++) {
|
||||
byte[] actl_itm = i >= actl_len ? null : actl[i];
|
||||
err += mgr.Tst_val(false, path, "ary:" + Int_.Xto_str(i), String_.new_u8(ary[i]), String_.new_u8(actl_itm));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
66
400_xowa/src_060_utl/gplx/GfoCacheMgr_tst.java
Normal file
66
400_xowa/src_060_utl/gplx/GfoCacheMgr_tst.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class GfoCacheMgr_tst {
|
||||
@Before public void init() {fxt = new GfoCacheMgr_fxt();} GfoCacheMgr_fxt fxt;
|
||||
@Test public void teardown() {Env_.TickCount_Test = -1;}
|
||||
@Test public void Basic() {fxt.run_Add("a").Expd_curSize_(1).Expd_itms_("a").tst();}
|
||||
// @Test public void Reduce() {fxt.run_Add("a", "b", "c", "d", "e").Expd_curSize_(3).Expd_itms_("c", "d", "e").tst();}
|
||||
// @Test public void Access() {fxt.run_Add("a", "b", "c", "d").run_Get("b", "a").run_Add("e").Expd_curSize_(3).Expd_itms_("b", "a", "e").tst();}
|
||||
// @Test public void Sizes() {fxt.run_Add("abc", "d", "e").Expd_curSize_(2).Expd_itms_("d", "e").tst();}
|
||||
}
|
||||
class GfoCacheMgr_fxt {
|
||||
Gfo_cache_mgr mgr = new Gfo_cache_mgr().Max_size_(4).Reduce_by_(2);
|
||||
public GfoCacheMgr_fxt() {
|
||||
Env_.TickCount_Test = 1;
|
||||
}
|
||||
public GfoCacheMgr_fxt run_Add(String... ary) {
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
String s = ary[i];
|
||||
mgr.Add(Bry_.new_u8(s), new GfoCacheItm_mock(s), String_.Len(s));
|
||||
Env_.TickCount_Test++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoCacheMgr_fxt run_Get(String... ary) {
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
String s = ary[i];
|
||||
mgr.Get_by_key(Bry_.new_u8(s));
|
||||
Env_.TickCount_Test++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoCacheMgr_fxt Expd_curSize_(int v) {expd_curSize = v; return this;} private int expd_curSize = -1;
|
||||
public GfoCacheMgr_fxt Expd_itms_(String... v) {expd_itms = v; return this;} private String[] expd_itms;
|
||||
public GfoCacheMgr_fxt tst() {
|
||||
if (expd_curSize != -1) Tfds.Eq(expd_curSize, mgr.Cur_size(), "curSize");
|
||||
if (expd_itms != null) {
|
||||
String[] actl = new String[mgr.Count()];
|
||||
for (int i = 0; i < actl.length; i++)
|
||||
actl[i] = ((GfoCacheItm_mock)mgr.Get_at(i)).S();
|
||||
Tfds.Eq_ary_str(expd_itms, actl, "itms");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class GfoCacheItm_mock implements RlsAble {
|
||||
public void Rls() {}
|
||||
public String S() {return s;} private String s;
|
||||
public GfoCacheItm_mock(String s) {this.s = s;}
|
||||
}
|
||||
122
400_xowa/src_060_utl/gplx/Gfo_cache_mgr.java
Normal file
122
400_xowa/src_060_utl/gplx/Gfo_cache_mgr.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class Gfo_cache_mgr {
|
||||
private Ordered_hash hash = Ordered_hash_.new_bry_();
|
||||
private Ordered_hash recent = Ordered_hash_.new_bry_();
|
||||
public int Max_size() {return max_size;} public Gfo_cache_mgr Max_size_(int v) {max_size = v; return this;} private int max_size;
|
||||
public int Reduce_by() {return reduce_by;} public Gfo_cache_mgr Reduce_by_(int v) {reduce_by = v; return this;} private int reduce_by;
|
||||
public int Cur_size() {return cur_size;} private int cur_size;
|
||||
public int Count() {return hash.Count();}
|
||||
public void Clear() {hash.Clear(); recent.Clear(); cur_size = 0;}
|
||||
@gplx.Internal protected Object Get_at(int i) {
|
||||
Gfo_cache_itm rv = (Gfo_cache_itm)hash.Get_at(i);
|
||||
return rv.Val();
|
||||
}
|
||||
public Object Get_by_key(byte[] key) {
|
||||
Object o = hash.Get_by(key); if (o == null) return null;
|
||||
Gfo_cache_itm rv = (Gfo_cache_itm)o;
|
||||
rv.Timestamp_update();
|
||||
Object recent_itm = recent.Get_by(key);
|
||||
if (recent_itm == null) recent.Add(key, rv);
|
||||
return rv.Val();
|
||||
}
|
||||
public void Del(byte[] key) {
|
||||
Object o = hash.Get_by(key); if (o == null) return;
|
||||
Gfo_cache_itm itm = (Gfo_cache_itm)o;
|
||||
cur_size -= itm.Size();
|
||||
hash.Del(itm.Key());
|
||||
itm.Rls();
|
||||
}
|
||||
public void Add_replace(byte[] key, RlsAble val, int size) {
|
||||
// Del(key);
|
||||
// Add(key, val, size);
|
||||
Object o = hash.Get_by(key);
|
||||
if (o == null)
|
||||
Add(key, val, size);
|
||||
else {
|
||||
Gfo_cache_itm itm = (Gfo_cache_itm)o;
|
||||
cur_size -= itm.Size();
|
||||
cur_size += size;
|
||||
itm.Replace(val, size);
|
||||
}
|
||||
}
|
||||
public void Add(byte[] key, RlsAble val, int size) {
|
||||
// if (cur_size + size > 600000000) ReduceCache();
|
||||
cur_size += size;
|
||||
// ++cur_size;
|
||||
Gfo_cache_itm itm = new Gfo_cache_itm(key, val, size);
|
||||
hash.Add(key, itm);
|
||||
}
|
||||
public void Reduce_recent() {
|
||||
// ConsoleAdp._.WriteLine("reducing");
|
||||
int len = recent.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_cache_itm itm = (Gfo_cache_itm)recent.Get_at(i);
|
||||
itm.Rls(); // releases root
|
||||
}
|
||||
recent.Clear();
|
||||
}
|
||||
public void Reduce_cache() {
|
||||
ConsoleAdp._.WriteLine("compacting:");
|
||||
// hash.Sort();
|
||||
// int len = hash.Count();
|
||||
// List_adp deleted = List_adp_.new_();
|
||||
// int deleted_size = 0, deleted_count = 0;
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Gfo_cache_itm itm = (Gfo_cache_itm)hash.Get_at(i);
|
||||
// int new_deleted_size = deleted_size + 1;//itm.Size();
|
||||
// if (new_deleted_size > 4000 && deleted_count > 0) break;
|
||||
// deleted.Add(itm);
|
||||
// deleted_count++;
|
||||
// deleted_size = new_deleted_size;
|
||||
// }
|
||||
// len = deleted.Count();
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// Gfo_cache_itm itm = (Gfo_cache_itm)deleted.Get_at(i);
|
||||
// cur_size --;
|
||||
// hash.Del(bry_ref.Val_(itm.Key()));
|
||||
// itm.Rls();
|
||||
// }
|
||||
// deleted.Clear();
|
||||
|
||||
int len = hash.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_cache_itm itm = (Gfo_cache_itm)hash.Get_at(i);
|
||||
// hash.Del(bry_ref.Val_(itm.Key()));
|
||||
itm.Rls();
|
||||
}
|
||||
}
|
||||
}
|
||||
class Gfo_cache_itm implements gplx.CompareAble, RlsAble {
|
||||
public Gfo_cache_itm(byte[] key, RlsAble val, int size) {this.key = key; this.val = val; this.size = size; this.timestamp = Env_.TickCount();}
|
||||
public byte[] Key() {return key;} private byte[] key;
|
||||
public RlsAble Val() {return val;} private RlsAble val;
|
||||
public int Size() {return size;} private int size;
|
||||
public void Replace(RlsAble val, int size) {this.val = val; this.size = size;}
|
||||
public long Timestamp() {return timestamp;} public void Timestamp_update() {timestamp = Env_.TickCount();} private long timestamp;
|
||||
public int compareTo(Object obj) {
|
||||
Gfo_cache_itm comp = (Gfo_cache_itm)obj;
|
||||
return Long_.Compare(timestamp, comp.timestamp);
|
||||
}
|
||||
public void Rls() {
|
||||
val.Rls();
|
||||
// val = null;
|
||||
// key = null;
|
||||
}
|
||||
}
|
||||
46
400_xowa/src_060_utl/gplx/Gfo_url.java
Normal file
46
400_xowa/src_060_utl/gplx/Gfo_url.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.xowa.net.*;
|
||||
public class Gfo_url {
|
||||
public byte[] Raw() {return raw;} private byte[] raw;
|
||||
public boolean Protocol_is_relative() {return protocol_is_relative;} public Gfo_url Protocol_is_relative_(boolean v) {protocol_is_relative = v; return this;} private boolean protocol_is_relative;
|
||||
public byte Protocol_tid() {return protocol_tid;} public Gfo_url Protocol_tid_(byte v) {protocol_tid = v; return this;} private byte protocol_tid;
|
||||
public byte[] Protocol_bry() {return protocol_bry;} public Gfo_url Protocol_bry_(byte[] v) {protocol_bry = v; return this;} private byte[] protocol_bry;
|
||||
public byte[] Site() {return site;} public Gfo_url Site_(byte[] v) {site = v; return this;} private byte[] site;
|
||||
public byte[] Site_sub() {return site_sub;} public Gfo_url Site_sub_(byte[] v) {site_sub = v; return this;} private byte[] site_sub;
|
||||
public byte[] Site_name() {return site_name;} public Gfo_url Site_name_(byte[] v) {site_name = v; return this;} private byte[] site_name;
|
||||
public byte[] Site_domain() {return site_domain;} public Gfo_url Site_domain_(byte[] v) {site_domain = v; return this;} private byte[] site_domain;
|
||||
public byte[] Page() {return page;} public Gfo_url Page_(byte[] v) {page = v; return this;} private byte[] page;
|
||||
public byte[] Anchor() {return anchor;} public Gfo_url Anchor_(byte[] v) {anchor = v; return this;} private byte[] anchor;
|
||||
public byte[][] Segs() {return segs;} public Gfo_url Segs_(byte[][] v) {segs = v; return this;} private byte[][] segs;
|
||||
public Gfo_url_arg[] Args() {return args;} public Gfo_url Args_(Gfo_url_arg[] v) {args = v; return this;} Gfo_url_arg[] args;
|
||||
public int Args_bgn() {return args_bgn;} public Gfo_url Args_bgn_(int v) {args_bgn = v; return this;} private int args_bgn = -1;
|
||||
public byte Err() {return err;} public Gfo_url Err_(byte v) {err = v; return this;} private byte err;
|
||||
public Gfo_url Ini_(byte[] v) {
|
||||
raw = v;
|
||||
protocol_tid = Xoo_protocol_itm.Tid_null; protocol_is_relative = false;
|
||||
protocol_bry = site = site_sub = site_name = site_domain = page = anchor = null;
|
||||
segs = Bry_.Ary_empty;
|
||||
args = Gfo_url_arg.Ary_empty;
|
||||
err = Err_none;
|
||||
args_bgn = -1;
|
||||
return this;
|
||||
}
|
||||
public static final byte Err_none = 0, Err_protocol_missing = 1, Err_site_missing = 2;
|
||||
}
|
||||
41
400_xowa/src_060_utl/gplx/Gfo_url_arg.java
Normal file
41
400_xowa/src_060_utl/gplx/Gfo_url_arg.java
Normal 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;
|
||||
public class Gfo_url_arg {
|
||||
public Gfo_url_arg(byte[] key_bry, byte[] val_bry) {this.key_bry = key_bry; this.val_bry = val_bry;}
|
||||
public byte[] Key_bry() {return key_bry;} private byte[] key_bry;
|
||||
public byte[] Val_bry() {return val_bry;} private byte[] val_bry;
|
||||
public Gfo_url_arg Val_bry_(byte[] v) {val_bry = v; return this;}
|
||||
public static final Gfo_url_arg[] Ary_empty = new Gfo_url_arg[0];
|
||||
public static Gfo_url_arg new_key_(String key) {
|
||||
return new Gfo_url_arg(Bry_.new_u8(key), Bry_.Empty);
|
||||
}
|
||||
public static Gfo_url_arg[] Ary(String... kvs) {
|
||||
int len = kvs.length;
|
||||
Gfo_url_arg[] rv = new Gfo_url_arg[len / 2];
|
||||
String key = null;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String s = kvs[i];
|
||||
if (i % 2 == 0)
|
||||
key = s;
|
||||
else
|
||||
rv[i / 2] = new Gfo_url_arg(Bry_.new_u8(key), Bry_.new_u8(s));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
312
400_xowa/src_060_utl/gplx/Gfo_url_parser.java
Normal file
312
400_xowa/src_060_utl/gplx/Gfo_url_parser.java
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.xowa.net.*;
|
||||
public class Gfo_url_parser {
|
||||
private boolean pass = true;
|
||||
private Gfo_url url;
|
||||
private List_adp segs = List_adp_.new_(), args = List_adp_.new_();
|
||||
private Url_encoder encoder = Url_encoder.new_html_href_mw_().Itms_raw_same_many(Byte_ascii.Underline); private Hash_adp_bry protocols = Hash_adp_bry.ci_ascii_(); // ASCII:url_protocol; EX:"http:", "ftp:", etc
|
||||
public Gfo_url_parser() {
|
||||
Init_protocols(Xoo_protocol_itm.Ary());
|
||||
Init_protocol(Xoo_protocol_itm.Tid_file, Xoo_protocol_itm.Str_file);
|
||||
}
|
||||
public void Init_protocol(byte tid, String protocol) {Init_protocols(new Xoo_protocol_itm(tid, protocol));}
|
||||
public void Init_protocols(Xoo_protocol_itm... itms) {
|
||||
int len = itms.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xoo_protocol_itm itm = itms[i];
|
||||
byte[] key = itm.Key_w_colon_bry();
|
||||
if (protocols.Has(key)) continue; // NOTE: must check if protocol exists, else test will fail
|
||||
protocols.Add(key, itm);
|
||||
}
|
||||
}
|
||||
public byte Relative_url_protocol() {return relative_url_protocol;} public Gfo_url_parser Relative_url_protocol_(byte v) {relative_url_protocol = v; return this;} private byte relative_url_protocol = Xoo_protocol_itm.Tid_http;
|
||||
public byte[] Relative_url_protocol_bry() {return Xoo_protocol_itm.Ary()[relative_url_protocol].Key_w_colon_bry();}
|
||||
public void Parse_site_fast(Gfo_url_site_data site_data, byte[] src, int bgn, int end) {
|
||||
int pos = bgn; boolean rel = false;
|
||||
if (pos + 1 < end && src[pos] == Byte_ascii.Slash && src[pos + 1] == Byte_ascii.Slash) { // starts with "//"
|
||||
pos += 2;
|
||||
rel = true;
|
||||
}
|
||||
if (!rel) { // search for ":"; NOTE: only search if not rel; i.e.: "//"
|
||||
int colon_pos = Bry_finder.Find_fwd(src, Byte_ascii.Colon, pos, end); // no colon found; EX: "//a.org/b"; "a.org/b"
|
||||
if (colon_pos != Bry_.NotFound) // colon found; EX: "http://" or "https://"
|
||||
pos = colon_pos + Int_.Const_dlm_len;
|
||||
if (pos < end && src[pos] == Byte_ascii.Slash) { // skip slash after colon
|
||||
pos += 1;
|
||||
if (pos < end && src[pos] == Byte_ascii.Slash) // skip 2nd slash after colon
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
int slash_pos = Bry_finder.Find_fwd(src, Byte_ascii.Slash, pos, end);
|
||||
if (slash_pos == Bry_.NotFound) // no terminating slash; EX: http://a.org
|
||||
slash_pos = end;
|
||||
slash_pos = Bry_.Trim_end_pos(src, slash_pos);
|
||||
site_data.Atrs_set(rel, pos, slash_pos);
|
||||
}
|
||||
public Gfo_url Parse(byte[] src) {Gfo_url rv = new Gfo_url(); this.Parse(rv, src, 0, src.length); return rv;}
|
||||
public boolean Parse(Gfo_url url, byte[] src, int bgn, int end) {
|
||||
this.url = url;
|
||||
url.Ini_(src);
|
||||
pass = true;
|
||||
segs.Clear();
|
||||
args.Clear();
|
||||
int colon_pos = Bry_finder.Find_fwd(src, Byte_ascii.Colon, bgn, end);
|
||||
Object protocol_obj = colon_pos == Bry_.NotFound ? null : protocols.Get_by_mid(src, bgn, colon_pos + 1); // +1 to include colon
|
||||
if (protocol_obj != null) {
|
||||
Xoo_protocol_itm protocol_itm = (Xoo_protocol_itm)protocol_obj;
|
||||
url.Protocol_bry_(protocol_itm.Key_w_colon_bry());
|
||||
url.Protocol_tid_(protocol_itm.Tid());
|
||||
Parse_site(src, protocol_itm.Key_w_colon_bry().length, end);
|
||||
}
|
||||
else {
|
||||
int pos = bgn;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (pos == end) {
|
||||
encoder.Decode(src, bgn, end, tmp_bfr, false);
|
||||
url.Site_(tmp_bfr.Xto_bry_and_clear());
|
||||
url.Err_(Gfo_url.Err_protocol_missing); pass = false;
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Colon:
|
||||
// Segs_add(src, bgn, end);
|
||||
Parse_segs(src, bgn, end);
|
||||
loop = false;
|
||||
url.Err_(Gfo_url.Err_protocol_missing); pass = false;
|
||||
loop = false;
|
||||
break;
|
||||
case Byte_ascii.Question:
|
||||
Segs_add(src, bgn, pos);
|
||||
Parse_args(src, pos + 1, end);
|
||||
loop = false;
|
||||
url.Err_(Gfo_url.Err_protocol_missing); pass = false;
|
||||
break;
|
||||
case Byte_ascii.Hash:
|
||||
Segs_add(src, bgn, pos);
|
||||
Parse_anchor(src, pos + 1, end);
|
||||
slash_prv = pos;
|
||||
loop = false;
|
||||
url.Err_(Gfo_url.Err_protocol_missing); pass = false;
|
||||
break;
|
||||
case Byte_ascii.Slash:
|
||||
if (pos == 0 && pos + 1 < end && src[pos + 1] == Byte_ascii.Slash) { // starts with "//"
|
||||
encoder.Decode(src, bgn, pos, tmp_bfr, false);
|
||||
url.Site_(tmp_bfr.Xto_bry_and_clear());
|
||||
url.Protocol_is_relative_(true);
|
||||
url.Protocol_tid_(relative_url_protocol);
|
||||
byte[] protocol_bry = Xoo_protocol_itm.Ary()[relative_url_protocol].Key_w_colon_bry();
|
||||
url.Protocol_bry_(protocol_bry);
|
||||
Parse_site(src, 2, end); // 2=//
|
||||
loop = false;
|
||||
}
|
||||
else { // has "/"
|
||||
encoder.Decode(src, bgn, pos, tmp_bfr, false);
|
||||
url.Site_(tmp_bfr.Xto_bry_and_clear());
|
||||
Parse_segs(src, pos + 1, end);
|
||||
loop = false;
|
||||
url.Err_(Gfo_url.Err_protocol_missing); pass = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
private void Parse_site(byte[] src, int bgn, int end) {
|
||||
int dot_count = 0, dot_pos_0 = -1, dot_pos_1 = -1;
|
||||
boolean loop = true;
|
||||
byte b = Byte_ascii.Nil;
|
||||
while (loop) {
|
||||
if (bgn == end) {
|
||||
url.Err_(Gfo_url.Err_site_missing);
|
||||
break;
|
||||
}
|
||||
b = src[bgn];
|
||||
if (b == Byte_ascii.Slash)
|
||||
++bgn;
|
||||
else
|
||||
break;
|
||||
}
|
||||
int pos = bgn;
|
||||
while (loop) {
|
||||
switch (b) {
|
||||
case Byte_ascii.Dot:
|
||||
switch (dot_count) {
|
||||
case 0: dot_pos_0 = pos; break;
|
||||
case 1: dot_pos_1 = pos; break;
|
||||
}
|
||||
++dot_count;
|
||||
break;
|
||||
case Byte_ascii.Slash:
|
||||
Site_set(src, bgn, pos, dot_count, dot_pos_0, dot_pos_1);
|
||||
Parse_segs(src, pos + 1, end);
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!loop) break;
|
||||
++pos;
|
||||
if (pos >= end) { // NOTE: >= needed b/c sometimes "xowa-cmd:", 5 passed in
|
||||
Site_set(src, bgn, end, dot_count, dot_pos_0, dot_pos_1);
|
||||
break;
|
||||
}
|
||||
b = src[pos];
|
||||
}
|
||||
}
|
||||
int slash_prv;
|
||||
private void Parse_segs(byte[] src, int bgn, int end) {
|
||||
if (bgn == end) return;
|
||||
int pos = bgn;
|
||||
slash_prv = bgn;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (pos == end) {
|
||||
if (slash_prv < pos) Segs_add(src, slash_prv, end);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Question:
|
||||
Segs_add(src, slash_prv, pos);
|
||||
Parse_args(src, pos + 1, end);
|
||||
loop = false;
|
||||
break;
|
||||
case Byte_ascii.Hash:
|
||||
Segs_add(src, slash_prv, pos);
|
||||
Parse_anchor(src, pos + 1, end);
|
||||
slash_prv = pos;
|
||||
loop = false;
|
||||
break;
|
||||
case Byte_ascii.Slash:
|
||||
if (slash_prv != pos) // HACK: handles urls of form "/wiki//A"; treat 2nd / as part of "/A"
|
||||
Segs_add(src, slash_prv, pos);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
url.Segs_((byte[][])segs.To_ary(byte[].class));
|
||||
}
|
||||
private void Parse_anchor(byte[] src, int bgn, int end) {
|
||||
if (bgn == end) return;
|
||||
int pos = bgn;
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
if (pos == end) {
|
||||
Anchor_set(src, bgn, pos);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Question:
|
||||
Anchor_set(src, bgn, pos);
|
||||
Parse_args(src, pos + 1, end);
|
||||
loop = false;
|
||||
break;
|
||||
//case Byte_ascii.Slash: // NOTE: do not handle slash (by trying to parse segs); will cause anchor to fail; EX:A/b#c/d
|
||||
// case Byte_ascii.Slash:
|
||||
// Anchor_set(src, bgn, pos);
|
||||
// Parse_segs(src, pos + 1, end);
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
private void Parse_args(byte[] src, int bgn, int end) {
|
||||
// if (bgn == end) return; // make "A?" -> "A" DATE:2014-01-19
|
||||
int pos = bgn;
|
||||
boolean loop = true;
|
||||
int key_bgn = pos, key_end = pos, val_bgn = pos;
|
||||
while (loop) {
|
||||
if (pos == end) {
|
||||
Args_add(src, key_bgn, key_end, val_bgn, pos);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Amp:
|
||||
Args_add(src, key_bgn, key_end, val_bgn, pos);
|
||||
key_bgn = pos + 1;
|
||||
break;
|
||||
case Byte_ascii.Eq:
|
||||
key_end = pos;
|
||||
val_bgn = pos + 1; // +1 to set after eq
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
url.Args_bgn_(bgn - 1); // NOTE: bgn is 1st char after ?; -1 to place at ?
|
||||
url.Args_((Gfo_url_arg[])args.To_ary(Gfo_url_arg.class));
|
||||
}
|
||||
private void Args_add(byte[] src, int key_bgn, int key_end, int val_bgn, int val_end) {
|
||||
encoder.Decode(src, key_bgn, key_end, tmp_bfr, false);
|
||||
byte[] key = tmp_bfr.Xto_bry_and_clear();
|
||||
encoder.Decode(src, val_bgn, val_end, tmp_bfr, false);
|
||||
byte[] val = tmp_bfr.Xto_bry_and_clear();
|
||||
Gfo_url_arg arg = new Gfo_url_arg(key, val);
|
||||
args.Add(arg);
|
||||
}
|
||||
private void Site_set(byte[] src, int bgn, int end, int dot_count, int dot_pos_0, int dot_pos_1) {
|
||||
encoder.Decode(src, bgn, end, tmp_bfr, false);
|
||||
url.Site_(tmp_bfr.Xto_bry_and_clear());
|
||||
switch (dot_count) {
|
||||
default:
|
||||
case 2:
|
||||
encoder.Decode(src, bgn, dot_pos_0, tmp_bfr, false);
|
||||
url.Site_sub_(tmp_bfr.Xto_bry_and_clear());
|
||||
encoder.Decode(src, dot_pos_0 + 1, dot_pos_1, tmp_bfr, false);
|
||||
url.Site_name_(tmp_bfr.Xto_bry_and_clear());
|
||||
encoder.Decode(src, dot_pos_1 + 1, end, tmp_bfr, false);
|
||||
url.Site_domain_(tmp_bfr.Xto_bry_and_clear());
|
||||
break;
|
||||
case 1:
|
||||
encoder.Decode(src, bgn, dot_pos_0, tmp_bfr, false);
|
||||
url.Site_name_(tmp_bfr.Xto_bry_and_clear());
|
||||
encoder.Decode(src, dot_pos_0 + 1, end, tmp_bfr, false);
|
||||
url.Site_domain_(tmp_bfr.Xto_bry_and_clear());
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void Segs_add(byte[] src, int bgn, int end) {
|
||||
encoder.Decode(src, bgn, end, tmp_bfr, false);
|
||||
byte[] seg = tmp_bfr.Xto_bry_and_clear();
|
||||
if (url.Page() != null)
|
||||
segs.Add(url.Page());
|
||||
url.Page_(seg);
|
||||
slash_prv = end + 1; // +1 to position after /
|
||||
}
|
||||
private void Anchor_set(byte[] src, int bgn, int end) {
|
||||
encoder.Decode(src, bgn, end, tmp_bfr, false);
|
||||
url.Anchor_(tmp_bfr.Xto_bry_and_clear());
|
||||
}
|
||||
private static final Bry_bfr tmp_bfr = Bry_bfr.reset_(500);
|
||||
public static final byte[] Bry_double_slash = new byte[] {Byte_ascii.Slash, Byte_ascii.Slash};
|
||||
}
|
||||
153
400_xowa/src_060_utl/gplx/Gfo_url_parser_tst.java
Normal file
153
400_xowa/src_060_utl/gplx/Gfo_url_parser_tst.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
import gplx.xowa.net.*;
|
||||
public class Gfo_url_parser_tst {
|
||||
Gfo_url_parser_chkr fxt = new Gfo_url_parser_chkr();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void All() {
|
||||
fxt.Raw_("http://en.wikipedia.org/wiki/mock/Page 0#a?b=c&d=e")
|
||||
.Protocol_tid_(Xoo_protocol_itm.Tid_http)
|
||||
.Site_("en.wikipedia.org")
|
||||
.Site_sub_("en")
|
||||
.Site_name_("wikipedia")
|
||||
.Site_domain_("org")
|
||||
.Segs_("wiki")
|
||||
.Segs_("mock")
|
||||
.Page_("Page 0")
|
||||
.Anchor_("a")
|
||||
.Args_("b", "c")
|
||||
.Args_("d", "e")
|
||||
.tst_();
|
||||
}
|
||||
@Test public void Site_slash_none() {
|
||||
fxt.Raw_("http:en.wikipedia.org").Protocol_tid_(Xoo_protocol_itm.Tid_http).Site_("en.wikipedia.org").tst_();
|
||||
}
|
||||
@Test public void Site_slash_many() {
|
||||
fxt.Raw_("http:////en.wikipedia.org").Protocol_tid_(Xoo_protocol_itm.Tid_http).Site_("en.wikipedia.org").tst_();
|
||||
}
|
||||
@Test public void Site_slash_trailing() {
|
||||
fxt.Raw_("http://en.wikipedia.org/").Protocol_tid_(Xoo_protocol_itm.Tid_http).Site_("en.wikipedia.org").tst_();
|
||||
}
|
||||
@Test public void Site_dot_1() {
|
||||
fxt.Raw_("http://wikipedia.org").Site_("wikipedia.org").Site_name_("wikipedia").Site_domain_("org").tst_();
|
||||
}
|
||||
@Test public void Page_encoded() {
|
||||
fxt.Raw_("http://site/A%27s").Site_("site").Page_("A's").tst_();
|
||||
}
|
||||
@Test public void Args() {
|
||||
fxt.Raw_("http://site/page?a=b").Site_("site").Args_("a", "b").tst_();
|
||||
}
|
||||
@Test public void Args_protocol_less() {
|
||||
fxt.Raw_("Special:Search/Earth?fulltext=yes").Segs_("Special:Search").Page_("Earth").Args_("fulltext", "yes").tst_();
|
||||
}
|
||||
@Test public void Err_protocol_missing() {
|
||||
fxt.Raw_("httpen.wikipedia.org").Err_(Gfo_url.Err_protocol_missing).tst_();
|
||||
}
|
||||
@Test public void Err_protocol_missing__site_only() {
|
||||
fxt.Raw_("site").Site_("site").Err_(Gfo_url.Err_protocol_missing).tst_();
|
||||
}
|
||||
@Test public void Err_protocol_missing__site_and_page() {
|
||||
fxt.Raw_("site/page").Site_("site").Page_("page").Err_(Gfo_url.Err_protocol_missing).tst_();
|
||||
}
|
||||
@Test public void Err_protocol_missing__page_anchor() {
|
||||
fxt.Raw_("page#a").Page_("page").Anchor_("a").Err_(Gfo_url.Err_protocol_missing).tst_();
|
||||
}
|
||||
@Test public void Legacy() {
|
||||
fxt.Reset().Raw_("http://en.wikipedia.org/wiki/A" ).Page_("A").tst_();
|
||||
fxt.Reset().Raw_("http://en.wikipedia.org/wiki/A?").Page_("A").Args_("", "").tst_();
|
||||
fxt.Reset().Raw_("http://en.wikipedia.org/wiki/A#").Page_("A").tst_();
|
||||
fxt.Reset().Raw_("http://en.wikipedia.org/wiki/A%27s").Page_("A's").tst_();
|
||||
fxt.Reset().Raw_("https://en.wikipedia.org/wiki/A").Page_("A").tst_();
|
||||
fxt.Reset().Raw_("http://en.m.wikipedia.org/wiki/A").Page_("A").tst_();
|
||||
fxt.Reset().Raw_("http://en.wikipedia.org/w/index.php?title=A").Args_("title", "A").tst_();
|
||||
}
|
||||
@Test public void Relative() {
|
||||
fxt.Raw_("//en.wikipedia.org").Protocol_tid_(Xoo_protocol_itm.Tid_http).Site_("en.wikipedia.org").tst_();
|
||||
}
|
||||
@Test public void Parse_site_fast() {
|
||||
fxt.Parse_site_fast_tst("http://a.org/B" , "a.org");
|
||||
fxt.Parse_site_fast_tst("http://a.org" , "a.org");
|
||||
fxt.Parse_site_fast_tst("//a.org/B" , "a.org");
|
||||
fxt.Parse_site_fast_tst("//a.org/B:C" , "a.org");
|
||||
}
|
||||
}
|
||||
class Gfo_url_parser_chkr implements Tst_chkr {
|
||||
public Class<?> TypeOf() {return Gfo_url.class;}
|
||||
public Gfo_url_parser_chkr Protocol_tid_(byte v) {this.protocol_tid = v; return this;} private byte protocol_tid;
|
||||
public Gfo_url_parser_chkr Site_(String v) {this.site = v; return this;} private String site;
|
||||
public Gfo_url_parser_chkr Site_sub_(String v) {this.site_sub = v; return this;} private String site_sub;
|
||||
public Gfo_url_parser_chkr Site_name_(String v) {this.site_name = v; return this;} private String site_name;
|
||||
public Gfo_url_parser_chkr Site_domain_(String v) {this.site_domain = v; return this;} private String site_domain;
|
||||
public Gfo_url_parser_chkr Segs_(String v) {segs.Add(v); return this;} List_adp segs = List_adp_.new_();
|
||||
public Gfo_url_parser_chkr Page_(String v) {this.page = v; return this;} private String page;
|
||||
public Gfo_url_parser_chkr Anchor_(String v) {this.anchor = v; return this;} private String anchor;
|
||||
public Gfo_url_parser_chkr Args_(String k, String v) {args.Add(new Gfo_url_arg_chkr(k, v)); return this;} List_adp args = List_adp_.new_();
|
||||
public Gfo_url_parser_chkr Err_(byte v) {err = v; return this;} private byte err;
|
||||
public Gfo_url_parser_chkr Reset() {
|
||||
protocol_tid = Xoo_protocol_itm.Tid_null;
|
||||
site = site_sub = site_name = site_domain = page = anchor = null;
|
||||
err = Gfo_url.Err_none;
|
||||
segs.Clear();
|
||||
args.Clear();
|
||||
return this;
|
||||
}
|
||||
ByteAryAry_chkr bry_ary_chkr = new ByteAryAry_chkr();
|
||||
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
|
||||
Gfo_url actl = (Gfo_url)actl_obj;
|
||||
int rv = 0;
|
||||
rv += mgr.Tst_val(err == Gfo_url.Err_none, path, "err", err, actl.Err());
|
||||
rv += mgr.Tst_val(protocol_tid == Xoo_protocol_itm.Tid_null, path, "protocol_tid", protocol_tid, actl.Protocol_tid());
|
||||
rv += mgr.Tst_val(site == null, path, "site", site, String_.new_u8(actl.Site()));
|
||||
rv += mgr.Tst_val(site_sub == null, path, "site_sub", site_sub, String_.new_u8(actl.Site_sub()));
|
||||
rv += mgr.Tst_val(site_name == null, path, "site_name", site_name, String_.new_u8(actl.Site_name()));
|
||||
rv += mgr.Tst_val(site_domain == null, path, "site_domain", site_domain, String_.new_u8(actl.Site_domain()));
|
||||
bry_ary_chkr.Val_(Bry_.Ary(segs.To_str_ary()));
|
||||
rv += bry_ary_chkr.Chk(mgr, "segs", actl.Segs());
|
||||
rv += mgr.Tst_val(page == null, path, "page", page, String_.new_u8(actl.Page()));
|
||||
rv += mgr.Tst_val(anchor == null, path, "anchor", anchor, String_.new_u8(actl.Anchor()));
|
||||
mgr.Tst_sub_ary((Gfo_url_arg_chkr[])args.To_ary(Gfo_url_arg_chkr.class), actl.Args(), "args", rv);
|
||||
return rv;
|
||||
}
|
||||
public Gfo_url_parser_chkr Raw_(String v) {this.raw = v; return this;} private String raw;
|
||||
public void tst_() {
|
||||
byte[] bry = Bry_.new_u8(raw);
|
||||
Gfo_url url = new Gfo_url();
|
||||
parser.Parse(url, bry, 0, bry.length);
|
||||
Tst_mgr tst_mgr = new Tst_mgr();
|
||||
tst_mgr.Tst_obj(this, url);
|
||||
} Gfo_url_parser parser = new Gfo_url_parser();
|
||||
public void Parse_site_fast_tst(String raw, String expd) {
|
||||
byte[] raw_bry = Bry_.new_u8(raw);
|
||||
parser.Parse_site_fast(site_data, raw_bry, 0, raw_bry.length);
|
||||
String actl = String_.new_u8(raw_bry, site_data.Site_bgn(), site_data.Site_end());
|
||||
Tfds.Eq(expd, actl);
|
||||
} Gfo_url_site_data site_data = new Gfo_url_site_data();
|
||||
}
|
||||
class Gfo_url_arg_chkr implements Tst_chkr {
|
||||
public Gfo_url_arg_chkr(String key, String val) {this.key = key; this.val = val;} private String key; String val;
|
||||
public Class<?> TypeOf() {return Gfo_url_arg.class;}
|
||||
public int Chk(Tst_mgr mgr, String path, Object actl_obj) {
|
||||
Gfo_url_arg actl = (Gfo_url_arg)actl_obj;
|
||||
int rv = 0;
|
||||
rv += mgr.Tst_val(key == null, path, "key", key, String_.new_u8(actl.Key_bry()));
|
||||
rv += mgr.Tst_val(val == null, path, "val", val, String_.new_u8(actl.Val_bry()));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
24
400_xowa/src_060_utl/gplx/Gfo_url_site_data.java
Normal file
24
400_xowa/src_060_utl/gplx/Gfo_url_site_data.java
Normal 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;
|
||||
public class Gfo_url_site_data {
|
||||
public boolean Rel() {return rel;} private boolean rel;
|
||||
public int Site_bgn() {return site_bgn;} private int site_bgn;
|
||||
public int Site_end() {return site_end;} private int site_end;
|
||||
public void Atrs_set(boolean rel, int bgn, int end) {this.rel = rel; this.site_bgn = bgn; this.site_end = end;}
|
||||
}
|
||||
22
400_xowa/src_060_utl/gplx/Gfo_usr_dlg__gui__opt.java
Normal file
22
400_xowa/src_060_utl/gplx/Gfo_usr_dlg__gui__opt.java
Normal 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;
|
||||
public interface Gfo_usr_dlg__gui__opt {
|
||||
boolean Warn_enabled();
|
||||
boolean Note_enabled();
|
||||
}
|
||||
50
400_xowa/src_060_utl/gplx/Gfo_usr_dlg__gui__swt.java
Normal file
50
400_xowa/src_060_utl/gplx/Gfo_usr_dlg__gui__swt.java
Normal 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;
|
||||
import gplx.core.strings.*; import gplx.gfui.*;
|
||||
public class Gfo_usr_dlg__gui__swt implements Gfo_usr_dlg__gui, GfoInvkAble {
|
||||
private final GfuiInvkCmd cmd_sync; private final GfuiTextBox prog_box, info_box; private final Gfo_usr_dlg__gui__opt opt;
|
||||
public Gfo_usr_dlg__gui__swt(Gfui_kit kit, GfuiTextBox prog_box, GfuiTextBox info_box, GfuiTextBox warn_box, Gfo_usr_dlg__gui__opt opt) {
|
||||
this.cmd_sync = kit.New_cmd_sync(this); // NOTE: cmd_sync needed else progress messages may be sent out of order
|
||||
this.prog_box = prog_box; this.info_box = info_box;
|
||||
this.opt = opt;
|
||||
}
|
||||
public void Clear() {Write(Invk_write_prog, ""); info_box.Text_(""); info_box.ForeColor_(ColorAdp_.Black); info_box.BackColor_(ColorAdp_.White); info_box.Redraw(); info_box_is_warn = false;}
|
||||
public String_ring Prog_msgs() {return prog_msgs;} String_ring prog_msgs = new String_ring().Max_(128);
|
||||
public void Write_prog(String text) {Write(Invk_write_prog, text);}
|
||||
public void Write_note(String text) {if (opt.Note_enabled()) Write(Invk_write_note, text);}
|
||||
public void Write_warn(String text) {if (opt.Warn_enabled()) Write(Invk_write_warn, text);}
|
||||
public void Write_stop(String text) {Write(Invk_write_stop, text);}
|
||||
private void Write(String invk, String text) {
|
||||
GfoMsg m = GfoMsg_.new_cast_(invk).Add("v", text);
|
||||
GfoInvkAble_.InvkCmd_msg(cmd_sync, invk, m);
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_write_prog)) {String v = m.ReadStr("v"); prog_box.Text_(v); prog_box.Redraw(); if (!String_.Eq(v, "")) prog_msgs.Push(v);}
|
||||
else if (ctx.Match(k, Invk_write_note)) {Info_box_write(m.ReadStr("v"), false); info_box.Redraw();}
|
||||
else if (ctx.Match(k, Invk_write_warn)) {Info_box_write(m.ReadStr("v"), true); info_box.ForeColor_(ColorAdp_.White); info_box.BackColor_(ColorAdp_.Red); info_box.Redraw();}
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private void Info_box_write(String v, boolean warn) {
|
||||
if (info_box_is_warn) return;
|
||||
info_box.Text_(v);
|
||||
info_box_is_warn = warn;
|
||||
} boolean info_box_is_warn;
|
||||
static final String Invk_write_prog = "write_prog", Invk_write_note = "write_note", Invk_write_warn = "write_warn", Invk_write_stop = "write_stop";
|
||||
}
|
||||
34
400_xowa/src_060_utl/gplx/Gfo_usr_dlg_fmt.java
Normal file
34
400_xowa/src_060_utl/gplx/Gfo_usr_dlg_fmt.java
Normal 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;
|
||||
public class Gfo_usr_dlg_fmt {
|
||||
public boolean Write_prog_cur(int cur, Gfo_usr_dlg usr_dlg) {
|
||||
if (cur < prog_prv + prog_interval) return usr_dlg.Canceled();
|
||||
prog_prv = cur;
|
||||
String pct = DecimalAdp_.CalcPctStr(cur + List_adp_.Base1, end, "00.00");
|
||||
usr_dlg.Prog_many(grp_key, msg_key, fmt, Int_.Xto_str_pad_bgn_zero(cur + List_adp_.Base1, endLen), end, pct);
|
||||
return usr_dlg.Canceled();
|
||||
} String fmt; int end, endLen;
|
||||
public static Gfo_usr_dlg_fmt fmt_(String grp_key, String msg_key, String fmt, int end, float pct) {
|
||||
Gfo_usr_dlg_fmt rv = new Gfo_usr_dlg_fmt();
|
||||
rv.grp_key = grp_key; rv.msg_key = msg_key;
|
||||
rv.fmt = fmt; rv.end = end; rv.endLen = Int_.DigitCount(end); rv.prog_interval = (int)((float)end * (float)(pct / (float)100));;
|
||||
return rv;
|
||||
} String grp_key, msg_key;
|
||||
int prog_interval; int prog_prv = Int_.MinValue;
|
||||
}
|
||||
61
400_xowa/src_060_utl/gplx/HierPosAryBldr.java
Normal file
61
400_xowa/src_060_utl/gplx/HierPosAryBldr.java
Normal 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;
|
||||
import gplx.core.strings.*;
|
||||
public class HierPosAryBldr {
|
||||
public void Init() {
|
||||
int ary_max = ary.length;
|
||||
for (int i = 0; i < ary_max; i++)
|
||||
ary[i] = 0;
|
||||
aryIdx = -1;
|
||||
root = 0;
|
||||
}
|
||||
public void MoveDown() {
|
||||
aryIdx += 1;
|
||||
if (aryIdx == 0)
|
||||
ary[aryIdx] = root;
|
||||
else
|
||||
ary[aryIdx] = 0;
|
||||
}
|
||||
public void MoveUp() {
|
||||
aryIdx -= 1;
|
||||
MoveNext();
|
||||
}
|
||||
public void MoveNext() {
|
||||
if (aryIdx == -1)
|
||||
root += 1;
|
||||
else
|
||||
ary[aryIdx] += 1;
|
||||
}
|
||||
public boolean Dirty() {return aryIdx > -1 || root > 0;}
|
||||
public int[] XtoIntAry() {
|
||||
if (aryIdx == -1) return Int_.Ary_empty;
|
||||
int[] rv = new int[aryIdx + 1];
|
||||
for (int i = 0; i < aryIdx + 1; i++)
|
||||
rv[i] = ary[i];
|
||||
return rv;
|
||||
}
|
||||
public String XtoStr() {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < aryIdx; i++)
|
||||
sb.Add_spr_unless_first(Int_.Xto_str(ary[i]), " ", i);
|
||||
return sb.XtoStr();
|
||||
}
|
||||
int[] ary; int aryIdx = -1; int root = -1;
|
||||
public HierPosAryBldr(int ary_max) {ary = new int[ary_max]; this.Init();}
|
||||
}
|
||||
65
400_xowa/src_060_utl/gplx/HierPosAryBldr_tst.java
Normal file
65
400_xowa/src_060_utl/gplx/HierPosAryBldr_tst.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class HierPosAryBldr_tst {
|
||||
@Before public void init() {bldr.Init();} HierPosAryBldr bldr = new HierPosAryBldr(256);
|
||||
@Test public void Basic() {
|
||||
tst_ary(Int_.Ary_empty);
|
||||
}
|
||||
@Test public void Move_d() {
|
||||
bldr.MoveDown();
|
||||
tst_ary(0);
|
||||
}
|
||||
@Test public void Move_dd() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveDown();
|
||||
tst_ary(0, 0);
|
||||
}
|
||||
@Test public void Move_ddu() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveDown();
|
||||
bldr.MoveUp();
|
||||
tst_ary(1);
|
||||
}
|
||||
@Test public void Move_ddud() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveDown();
|
||||
bldr.MoveUp();
|
||||
bldr.MoveDown();
|
||||
tst_ary(1, 0);
|
||||
}
|
||||
@Test public void Move_dud() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveUp();
|
||||
bldr.MoveDown();
|
||||
tst_ary(1);
|
||||
}
|
||||
@Test public void Move_dn() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveNext();
|
||||
tst_ary(1);
|
||||
}
|
||||
@Test public void Move_ddn() {
|
||||
bldr.MoveDown();
|
||||
bldr.MoveDown();
|
||||
bldr.MoveNext();
|
||||
tst_ary(0, 1);
|
||||
}
|
||||
private void tst_ary(int... expd) {Tfds.Eq_ary(expd, bldr.XtoIntAry());}
|
||||
}
|
||||
58
400_xowa/src_060_utl/gplx/Int_2_ref.java
Normal file
58
400_xowa/src_060_utl/gplx/Int_2_ref.java
Normal 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;
|
||||
public class Int_2_ref {
|
||||
public Int_2_ref() {}
|
||||
public Int_2_ref(int v0, int v1) {Val_all_(v0, v1);}
|
||||
public int Val_0() {return val_0;} public Int_2_ref Val_0_(int v) {val_0 = v; return this;} private int val_0;
|
||||
public int Val_1() {return val_1;} public Int_2_ref Val_1_(int v) {val_1 = v; return this;} private int val_1;
|
||||
public Int_2_ref Val_all_(int v0, int v1) {val_0 = v0; val_1 = v1; return this;}
|
||||
@Override public int hashCode() {
|
||||
int hash = 23;
|
||||
hash = (hash * 31) + val_0;
|
||||
hash = (hash * 31) + val_1;
|
||||
return hash;
|
||||
}
|
||||
@Override public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
Int_2_ref comp = (Int_2_ref)obj;
|
||||
return val_0 == comp.val_0 && val_1 == comp.val_1;
|
||||
}
|
||||
public static Int_2_ref parse_(String raw) {
|
||||
try {
|
||||
String[] itms = String_.Split(raw, ",");
|
||||
int v0 = Int_.parse_(itms[0]);
|
||||
int v1 = Int_.parse_(itms[1]);
|
||||
return new Int_2_ref(v0, v1);
|
||||
} catch (Exception e) {Exc_.Noop(e); throw Exc_.new_parse("Int_2_ref", raw);}
|
||||
}
|
||||
public static Int_2_ref[] parse_ary_(String raw) {
|
||||
try {
|
||||
String[] itms = String_.Split(raw, ";");
|
||||
int itms_len = itms.length;
|
||||
Int_2_ref[] rv = new Int_2_ref[itms_len];
|
||||
for (int i = 0; i < itms_len; i++) {
|
||||
String[] vals = String_.Split(itms[i], ",");
|
||||
int v0 = Int_.parse_(vals[0]);
|
||||
int v1 = Int_.parse_(vals[1]);
|
||||
rv[i] = new Int_2_ref(v0, v1);
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {Exc_.Noop(e); throw Exc_.new_parse("Int_2_ref[]", raw);}
|
||||
}
|
||||
}
|
||||
33
400_xowa/src_060_utl/gplx/Int_2_val.java
Normal file
33
400_xowa/src_060_utl/gplx/Int_2_val.java
Normal 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;
|
||||
public class Int_2_val {
|
||||
public Int_2_val(int v0, int v1) {val_0 = v0; val_1 = v1;}
|
||||
public int Val_0() {return val_0;} final int val_0;
|
||||
public int Val_1() {return val_1;} final int val_1;
|
||||
public String Xto_str(Bry_bfr bfr) {return Xto_str(bfr, val_0, val_1);}
|
||||
public static final Int_2_val Null_ptr = null;
|
||||
public static Int_2_val parse_(String raw) {
|
||||
String[] itms = String_.Split(raw, ',');
|
||||
if (itms.length != 2) return Null_ptr;
|
||||
int v0 = Int_.parse_or_(itms[0], Int_.MinValue); if (v0 == Int_.MinValue) return Null_ptr;
|
||||
int v1 = Int_.parse_or_(itms[1], Int_.MinValue); if (v1 == Int_.MinValue) return Null_ptr;
|
||||
return new Int_2_val(v0, v1);
|
||||
}
|
||||
public static String Xto_str(Bry_bfr bfr, int x, int y) {return bfr.Add_int_variable(x).Add_byte_comma().Add_int_variable(y).Xto_str_and_clear();}
|
||||
}
|
||||
39
400_xowa/src_060_utl/gplx/Int_ary_parser.java
Normal file
39
400_xowa/src_060_utl/gplx/Int_ary_parser.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class Int_ary_parser extends Obj_ary_parser_base {
|
||||
Number_parser parser = new Number_parser(); int[] ary; int ary_idx;
|
||||
public int[] Parse_ary(String str, byte dlm) {byte[] bry = Bry_.new_u8(str); return Parse_ary(bry, 0, bry.length, dlm);}
|
||||
public int[] Parse_ary(byte[] bry, int bgn, int end, byte dlm) {
|
||||
Parse_core(bry, bgn, end, dlm, Byte_ascii.Nil);
|
||||
return ary;
|
||||
}
|
||||
@Override protected void Ary_len_(int v) {
|
||||
if (v == 0)
|
||||
ary = Int_.Ary_empty;
|
||||
else {
|
||||
ary = new int[v]; // NOTE: always create new array; never reuse;
|
||||
ary_idx = 0;
|
||||
}
|
||||
}
|
||||
@Override protected void Parse_itm(byte[] bry, int bgn, int end) {
|
||||
parser.Parse(bry, bgn, end); if (parser.Has_err() || parser.Has_frac()) throw Exc_.new_("failed to parse number", "val", String_.new_u8(bry, bgn, end));
|
||||
ary[ary_idx++] = parser.Rv_as_int();
|
||||
}
|
||||
public static final Int_ary_parser _ = new Int_ary_parser();
|
||||
}
|
||||
28
400_xowa/src_060_utl/gplx/Int_ary_parser_tst.java
Normal file
28
400_xowa/src_060_utl/gplx/Int_ary_parser_tst.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class Int_ary_parser_tst {
|
||||
@Test public void Many() {tst_ints("1,2,3,4,5" , 0, 9, Int_.Ary(1, 2, 3, 4, 5));}
|
||||
@Test public void One() {tst_ints("1" , 0, 1, Int_.Ary(1));}
|
||||
@Test public void None() {tst_ints("" , 0, 0, Int_.Ary());}
|
||||
private void tst_ints(String raw, int bgn, int end, int[] expd) {
|
||||
int[] actl = Int_ary_parser._.Parse_ary(Bry_.new_a7(raw), bgn, end, Byte_ascii.Comma);
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
}
|
||||
}
|
||||
44
400_xowa/src_060_utl/gplx/Int_list.java
Normal file
44
400_xowa/src_060_utl/gplx/Int_list.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class Int_list {
|
||||
private int[] ary = Int_.Ary_empty; private int ary_len, ary_max;
|
||||
public void Add(int uid) {
|
||||
int new_len = ary_len + 1;
|
||||
if (new_len > ary_max) {
|
||||
ary_max += 16;
|
||||
int[] new_ary = new int[ary_max];
|
||||
Int_.Ary_copy_to(ary, ary_len, new_ary);
|
||||
ary = new_ary;
|
||||
}
|
||||
ary[ary_len] = uid;
|
||||
ary_len = new_len;
|
||||
}
|
||||
public int Len() {return ary_len;}
|
||||
public int Get_at(int i) {return ary[i];}
|
||||
public void Clear() {
|
||||
ary = Int_.Ary_empty;
|
||||
ary_len = ary_max = 0;
|
||||
}
|
||||
public static Int_list new_(int... ary) {
|
||||
Int_list rv = new Int_list();
|
||||
int len = ary.length;
|
||||
rv.ary = ary; rv.ary_len = len; rv.ary_max = len;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
25
400_xowa/src_060_utl/gplx/Io_zip_mgr.java
Normal file
25
400_xowa/src_060_utl/gplx/Io_zip_mgr.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public interface Io_zip_mgr {
|
||||
void Zip_fil(Io_url src_fil, Io_url trg_fil);
|
||||
byte[] Zip_bry(byte[] src, int bgn, int len);
|
||||
byte[] Unzip_bry(byte[] src, int bgn, int len);
|
||||
void Unzip_to_dir(Io_url src_fil, Io_url trg_dir);
|
||||
void Zip_dir(Io_url src_dir, Io_url trg_fil);
|
||||
}
|
||||
119
400_xowa/src_060_utl/gplx/Io_zip_mgr_base.java
Normal file
119
400_xowa/src_060_utl/gplx/Io_zip_mgr_base.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.io.*;
|
||||
import java.util.zip.*;
|
||||
public class Io_zip_mgr_base implements Io_zip_mgr {
|
||||
public void Zip_fil(Io_url src_fil, Io_url trg_fil) {
|
||||
byte[] src_bry = Io_mgr.I.LoadFilBry(src_fil);
|
||||
byte[] trg_bry = Zip_bry(src_bry, 0, src_bry.length);
|
||||
Io_mgr.I.SaveFilBry(trg_fil, trg_bry);
|
||||
}
|
||||
public void Zip_dir(Io_url src_dir, Io_url trg_fil) {
|
||||
try {
|
||||
byte[] bry = new byte[4096];
|
||||
FileOutputStream fil_strm = new FileOutputStream(trg_fil.Raw());
|
||||
ZipOutputStream zip_strm = new ZipOutputStream(fil_strm);
|
||||
Zip_dir__add_dir(zip_strm, bry, "", src_dir, Zip_dir__get_subs(src_dir));
|
||||
zip_strm.flush();
|
||||
zip_strm.close();
|
||||
} catch(IOException e) {Exc_.new_exc(e, "io", "error duing zip", "src", src_dir.Raw(), "trg", trg_fil.Raw());}
|
||||
}
|
||||
private void Zip_dir__add_dir(ZipOutputStream zip_strm, byte[] bry, String zip_path, Io_url owner_dir, Io_url[] subs) {
|
||||
int len = subs.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Io_url sub = subs[i];
|
||||
String sub_path = zip_path + sub.NameAndExt_noDirSpr();
|
||||
if (sub.Type_dir())
|
||||
Zip_dir__add_dir(zip_strm, bry, sub_path + "/", sub, Zip_dir__get_subs(sub));
|
||||
else
|
||||
Zip_dir__add_fil(zip_strm, bry, sub_path, sub);
|
||||
}
|
||||
}
|
||||
private void Zip_dir__add_fil(ZipOutputStream zip_strm, byte[] bry, String zip_path, Io_url fil_url) {
|
||||
try {
|
||||
int len;
|
||||
FileInputStream fil_strm = new FileInputStream(fil_url.Raw());
|
||||
zip_strm.putNextEntry(new ZipEntry(zip_path));
|
||||
while ((len = fil_strm.read(bry)) > 0)
|
||||
zip_strm.write(bry, 0, len);
|
||||
fil_strm.close();
|
||||
} catch(IOException e) {throw Exc_.new_exc(e, "io", "error duing zip", "src", zip_path);}
|
||||
}
|
||||
private Io_url[] Zip_dir__get_subs(Io_url url) {
|
||||
return Io_mgr.I.QueryDir_args(url).DirInclude_().ExecAsUrlAry();
|
||||
}
|
||||
public byte[] Zip_bry(byte[] src, int bgn, int len) {
|
||||
ByteArrayInputStream src_stream = new ByteArrayInputStream(src, bgn, len);
|
||||
ByteArrayOutputStream trg_stream = new ByteArrayOutputStream(len);
|
||||
try {
|
||||
ZipOutputStream trgZip = new ZipOutputStream(trg_stream);
|
||||
ZipEntry entry = new ZipEntry("file");
|
||||
trgZip.putNextEntry(entry);
|
||||
int count;
|
||||
while((count = src_stream.read(tmp, 0, tmpLen)) != -1) {
|
||||
trgZip.write(tmp, 0, count);
|
||||
}
|
||||
trgZip.close();
|
||||
} catch(Exception e) {throw Exc_.new_("failed to zip", "err", e.getMessage());}
|
||||
return trg_stream.toByteArray();
|
||||
}
|
||||
public byte[] Unzip_bry(byte[] src, int bgn, int len) {
|
||||
ByteArrayInputStream src_stream = new ByteArrayInputStream(src, bgn, len);
|
||||
ByteArrayOutputStream trg_stream = new ByteArrayOutputStream(len);
|
||||
try {
|
||||
ZipInputStream srcZip = new ZipInputStream(src_stream);
|
||||
int count;
|
||||
while(srcZip.getNextEntry() != null) {
|
||||
while ((count = srcZip.read(tmp, 0, tmpLen)) != -1) {
|
||||
trg_stream.write(tmp, 0, count);
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {throw Exc_.new_("failed to unzip", "err", e.getMessage());}
|
||||
return trg_stream.toByteArray();
|
||||
}
|
||||
public void Unzip_to_dir(Io_url src_fil, Io_url trg_dir) {
|
||||
byte[] buffer = new byte[4096];
|
||||
try{
|
||||
Io_mgr.I.CreateDirIfAbsent(trg_dir);
|
||||
|
||||
ZipInputStream zip_strm = new ZipInputStream(new FileInputStream(src_fil.Raw()));
|
||||
ZipEntry zip_eny = zip_strm.getNextEntry();
|
||||
while (zip_eny != null) {
|
||||
String itm_name = zip_eny.getName();
|
||||
if (Op_sys.Cur().Tid_is_wnt()) itm_name = String_.Replace(itm_name, "/", "\\");
|
||||
Io_url itm_url = Io_url_.new_any_(trg_dir.GenSubFil(itm_name).Raw());
|
||||
Io_mgr.I.CreateDirIfAbsent(itm_url.OwnerDir()); // make sure owner dir exists
|
||||
if (itm_url.Type_fil()) {
|
||||
Io_mgr.I.SaveFilStr_args(itm_url, "").Exec();
|
||||
File itm_file = new File(itm_url.Raw());
|
||||
FileOutputStream itm_strm = new FileOutputStream(itm_file);
|
||||
int len;
|
||||
while ((len = zip_strm.read(buffer)) > 0)
|
||||
itm_strm.write(buffer, 0, len);
|
||||
itm_strm.close();
|
||||
}
|
||||
zip_eny = zip_strm.getNextEntry();
|
||||
}
|
||||
zip_strm.closeEntry();
|
||||
zip_strm.close();
|
||||
} catch(IOException e) {throw Exc_.new_exc(e, "io", "error duing unzip", "src", src_fil.Raw(), "trg", trg_dir.Raw());}
|
||||
}
|
||||
byte[] tmp = new byte[4096]; int tmpLen = 4096;
|
||||
public static final Io_zip_mgr _ = new Io_zip_mgr_base();
|
||||
}
|
||||
36
400_xowa/src_060_utl/gplx/Io_zip_mgr_mok.java
Normal file
36
400_xowa/src_060_utl/gplx/Io_zip_mgr_mok.java
Normal 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;
|
||||
public class Io_zip_mgr_mok implements Io_zip_mgr {
|
||||
public void Zip_fil(Io_url src_fil, Io_url trg_fil) {
|
||||
byte[] src_bry = Io_mgr.I.LoadFilBry(src_fil);
|
||||
byte[] zip_bry = Zip_bry(src_bry, 0, src_bry.length);
|
||||
Io_mgr.I.SaveFilBry(trg_fil, zip_bry);
|
||||
}
|
||||
public void Zip_dir(Io_url src_dir, Io_url trg_fil) {}
|
||||
public byte[] Zip_bry(byte[] src, int bgn, int len) {return Bry_.Add(Bry_zipped, Bry_.Mid(src, bgn, len));}
|
||||
public byte[] Unzip_bry(byte[] src, int bgn, int len) {
|
||||
if (src == Bry_.Empty) return src;
|
||||
byte[] section = Bry_.Mid(src, bgn, bgn + len);
|
||||
if (!Bry_.Has_at_bgn(section, Bry_zipped, 0, section.length)) throw Exc_.new_("src not zipped", "section", String_.new_u8(section));
|
||||
return Bry_.Mid(section, Bry_zipped.length, section.length);
|
||||
}
|
||||
public void Unzip_to_dir(Io_url src_fil, Io_url trg_dir) {}
|
||||
private static final byte[] Bry_zipped = Bry_.new_u8("zipped:");
|
||||
public static final Io_zip_mgr_mok _ = new Io_zip_mgr_mok(); Io_zip_mgr_mok() {}
|
||||
}
|
||||
31
400_xowa/src_060_utl/gplx/Io_zip_mgr_tst.java
Normal file
31
400_xowa/src_060_utl/gplx/Io_zip_mgr_tst.java
Normal 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;
|
||||
import org.junit.*;
|
||||
public class Io_zip_mgr_tst {
|
||||
@Test public void Zip_unzip() {
|
||||
Zip_unzip_tst("abcdefghijklmnopqrstuvwxyz");
|
||||
}
|
||||
private void Zip_unzip_tst(String s) {
|
||||
Io_zip_mgr zip_mgr = Io_zip_mgr_base._;
|
||||
byte[] src = Bry_.new_a7(s);
|
||||
byte[] zip = zip_mgr.Zip_bry(src, 0, src.length);
|
||||
byte[] unz = zip_mgr.Unzip_bry(zip, 0, zip.length);
|
||||
Tfds.Eq_ary(src, unz);
|
||||
}
|
||||
}
|
||||
181
400_xowa/src_060_utl/gplx/Number_parser.java
Normal file
181
400_xowa/src_060_utl/gplx/Number_parser.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class Number_parser {
|
||||
public int Rv_as_int() {return (int)int_val;} long int_val = 0;
|
||||
public DecimalAdp Rv_as_dec() {return dec_val == null ? DecimalAdp_.long_(int_val) : dec_val;} DecimalAdp dec_val = null;
|
||||
public boolean Has_err() {return has_err;} private boolean has_err;
|
||||
public boolean Has_frac() {return has_frac;} private boolean has_frac;
|
||||
public boolean Hex_enabled() {return hex_enabled;} public Number_parser Hex_enabled_(boolean v) {hex_enabled = v; return this;} private boolean hex_enabled;
|
||||
public Number_parser Ignore_chars_(byte[] v) {this.ignore_chars = v; return this;} private byte[] ignore_chars;
|
||||
public Number_parser Ignore_space_at_end_y_() {this.ignore_space_at_end = true; return this;} private boolean ignore_space_at_end;
|
||||
public void Clear() {
|
||||
ignore_chars = null;
|
||||
}
|
||||
public Number_parser Parse(byte[] src) {return Parse(src, 0, src.length);}
|
||||
public Number_parser Parse(byte[] ary, int bgn, int end) {
|
||||
int loop_bgn = end - 1, loop_end = bgn - 1, exp_multiplier = 1, factor = 10;
|
||||
long multiplier = 1, frc_multiplier = 1;
|
||||
int_val = 0; dec_val = null; boolean comma_nil = true;
|
||||
long frc_int = 0;
|
||||
has_err = false; has_frac = false; boolean has_exp = false, has_neg = false, exp_neg = false, has_plus = false, has_num = false;
|
||||
boolean input_is_hex = false;
|
||||
if (hex_enabled) {
|
||||
if (loop_end + 2 < end) { // ArrayOutOfBounds check
|
||||
byte b_2 = ary[loop_end + 2];
|
||||
switch (b_2) {
|
||||
case Byte_ascii.Ltr_x:
|
||||
case Byte_ascii.Ltr_X: // is 2nd char x?
|
||||
if (ary[loop_end + 1] == Byte_ascii.Num_0) { // is 1st char 0?
|
||||
factor = 16;
|
||||
input_is_hex = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = loop_bgn; i > loop_end; i--) {
|
||||
byte cur = ary[i];
|
||||
switch (cur) {
|
||||
case Byte_ascii.Num_0:
|
||||
case Byte_ascii.Num_1:
|
||||
case Byte_ascii.Num_2:
|
||||
case Byte_ascii.Num_3:
|
||||
case Byte_ascii.Num_4:
|
||||
case Byte_ascii.Num_5:
|
||||
case Byte_ascii.Num_6:
|
||||
case Byte_ascii.Num_7:
|
||||
case Byte_ascii.Num_8:
|
||||
case Byte_ascii.Num_9:
|
||||
int_val += (cur - Byte_ascii.Num_0) * multiplier;
|
||||
multiplier *= factor;
|
||||
has_num = true;
|
||||
break;
|
||||
case Byte_ascii.Dot:
|
||||
if (has_frac) return Has_err_y_();
|
||||
frc_int = int_val;
|
||||
int_val = 0;
|
||||
frc_multiplier = multiplier;
|
||||
multiplier = 1;
|
||||
has_frac = true;
|
||||
break;
|
||||
case Byte_ascii.Comma:
|
||||
if (comma_nil)
|
||||
comma_nil = false;
|
||||
else
|
||||
return Has_err_y_();
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
if (has_neg) return Has_err_y_();
|
||||
has_neg = true;
|
||||
break;
|
||||
case Byte_ascii.Space:
|
||||
if (i == bgn) {} // space at bgn
|
||||
else if (i == end - 1 && ignore_space_at_end) {} // ignore space at end; DATE:2015-04-29
|
||||
else
|
||||
return Has_err_y_();
|
||||
break;
|
||||
case Byte_ascii.Plus:
|
||||
if (has_plus) return Has_err_y_();
|
||||
has_plus = true;
|
||||
break;
|
||||
case Byte_ascii.Ltr_e:
|
||||
case Byte_ascii.Ltr_E:
|
||||
if (input_is_hex) {
|
||||
int_val += 14 * multiplier; // NOTE: 14=value of e/E
|
||||
multiplier *= factor;
|
||||
has_num = true;
|
||||
}
|
||||
else {
|
||||
if (has_exp) return Has_err_y_();
|
||||
exp_neg = has_neg;
|
||||
exp_multiplier = (int)Math_.Pow(10, int_val);
|
||||
int_val = 0;
|
||||
multiplier = 1;
|
||||
has_exp = true;
|
||||
has_neg = false;
|
||||
has_plus = false; // allow +1E+2
|
||||
}
|
||||
break;
|
||||
case Byte_ascii.Ltr_A:
|
||||
case Byte_ascii.Ltr_B:
|
||||
case Byte_ascii.Ltr_C:
|
||||
case Byte_ascii.Ltr_D:
|
||||
case Byte_ascii.Ltr_F:
|
||||
if (input_is_hex) {
|
||||
int_val += (cur - Byte_ascii.Ltr_A + 10) * multiplier;
|
||||
multiplier *= factor;
|
||||
has_num = true;
|
||||
}
|
||||
else
|
||||
return Has_err_y_();
|
||||
break;
|
||||
case Byte_ascii.Ltr_a:
|
||||
case Byte_ascii.Ltr_b:
|
||||
case Byte_ascii.Ltr_c:
|
||||
case Byte_ascii.Ltr_d:
|
||||
case Byte_ascii.Ltr_f:
|
||||
if (input_is_hex) {
|
||||
int_val += (cur - Byte_ascii.Ltr_a + 10) * multiplier;
|
||||
multiplier *= factor;
|
||||
has_num = true;
|
||||
}
|
||||
else
|
||||
return Has_err_y_();
|
||||
break;
|
||||
case Byte_ascii.Ltr_x:
|
||||
case Byte_ascii.Ltr_X:
|
||||
if (input_is_hex)
|
||||
return (factor == 16) ? this : Has_err_y_(); // check for '0x'
|
||||
else
|
||||
return Has_err_y_();
|
||||
default:
|
||||
if (ignore_chars != null) {
|
||||
int ignore_chars_len = ignore_chars.length;
|
||||
boolean ignored = false;
|
||||
for (int j = 0; j < ignore_chars_len; ++j) {
|
||||
if (cur == ignore_chars[j]) {
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignored) continue;
|
||||
}
|
||||
return Has_err_y_();
|
||||
}
|
||||
}
|
||||
if (!has_num) return Has_err_y_(); // handles situations wherein just symbols; EX: "+", ".", "-.", " , " etc.
|
||||
if (has_frac) {
|
||||
long full_val = (((int_val * frc_multiplier) + frc_int));
|
||||
if (has_neg) full_val *= -1;
|
||||
if (has_exp) {
|
||||
if (exp_neg) frc_multiplier *= exp_multiplier; // divide, so apply to frc
|
||||
else full_val *= exp_multiplier; // multiply, so apply to full_val
|
||||
}
|
||||
dec_val = DecimalAdp_.divide_(full_val, frc_multiplier);
|
||||
}
|
||||
else {
|
||||
if (has_neg) int_val *= -1;
|
||||
if (has_exp) int_val = exp_neg ? int_val / exp_multiplier : int_val * exp_multiplier;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private Number_parser Has_err_y_() {has_err = true; return this;}
|
||||
}
|
||||
103
400_xowa/src_060_utl/gplx/Number_parser_tst.java
Normal file
103
400_xowa/src_060_utl/gplx/Number_parser_tst.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class Number_parser_tst {
|
||||
private final Number_parser_fxt fxt = new Number_parser_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
@Test public void Integer() {
|
||||
fxt.Test_int("1", 1);
|
||||
fxt.Test_int("1234", 1234);
|
||||
fxt.Test_int("1234567890", 1234567890);
|
||||
fxt.Test_int("-1234", -1234);
|
||||
fxt.Test_int("+1", 1);
|
||||
fxt.Test_int("00001", 1);
|
||||
}
|
||||
@Test public void Decimal() {
|
||||
fxt.Test_dec("1.23", DecimalAdp_.parse_("1.23"));
|
||||
fxt.Test_dec("1.023", DecimalAdp_.parse_("1.023"));
|
||||
fxt.Test_dec("-1.23", DecimalAdp_.parse_("-1.23"));
|
||||
}
|
||||
@Test public void Double_long() {
|
||||
fxt.Test_dec(".42190046219457", DecimalAdp_.parse_(".42190046219457"));
|
||||
}
|
||||
@Test public void Exponent() {
|
||||
fxt.Test_int("1E2", 100);
|
||||
fxt.Test_dec("1.234E2", DecimalAdp_.parse_("123.4"));
|
||||
fxt.Test_dec("1.234E-2", DecimalAdp_.parse_(".01234"));
|
||||
fxt.Test_dec("123.4E-2", DecimalAdp_.parse_("1.234"));
|
||||
fxt.Test_dec("+6.0E-3", DecimalAdp_.parse_(".006"));
|
||||
}
|
||||
@Test public void Err() {
|
||||
fxt.Test_err("+", true);
|
||||
fxt.Test_err("-", true);
|
||||
fxt.Test_err("a", true);
|
||||
fxt.Test_err("1-2", false);
|
||||
fxt.Test_err("1..1", true);
|
||||
fxt.Test_err("1,,1", true);
|
||||
fxt.Test_err("1", false);
|
||||
}
|
||||
@Test public void Hex() {
|
||||
fxt.Test_hex("0x1" , 1);
|
||||
fxt.Test_hex("0xF" , 15);
|
||||
fxt.Test_hex("0x20" , 32);
|
||||
fxt.Test_hex("x20" , 0, false);
|
||||
fxt.Test_hex("d" , 0, false); // PURPOSE: d was being converted to 13; no.w:Hovedbanen; DATE:2014-04-13
|
||||
}
|
||||
@Test public void Ignore() {
|
||||
fxt.Init_ignore("\n\t");
|
||||
fxt.Test_int("1" , 1);
|
||||
fxt.Test_int("1\n" , 1);
|
||||
fxt.Test_int("1\t" , 1);
|
||||
fxt.Test_int("1\n2" , 12);
|
||||
fxt.Test_err("1\r" , true);
|
||||
}
|
||||
}
|
||||
class Number_parser_fxt {
|
||||
private final Number_parser parser = new Number_parser();
|
||||
public void Clear() {parser.Clear();}
|
||||
public void Init_ignore(String chars) {parser.Ignore_chars_(Bry_.new_a7(chars));}
|
||||
public void Test_int(String raw, int expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
int actl = parser.Parse(raw_bry, 0, raw_bry.length).Rv_as_int();
|
||||
Tfds.Eq(expd, actl, raw);
|
||||
}
|
||||
public void Test_dec(String raw, DecimalAdp expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
DecimalAdp actl = parser.Parse(raw_bry, 0, raw_bry.length).Rv_as_dec();
|
||||
Tfds.Eq(expd.Xto_decimal(), actl.Xto_decimal(), raw);
|
||||
}
|
||||
public void Test_err(String raw, boolean expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
boolean actl = parser.Parse(raw_bry, 0, raw_bry.length).Has_err();
|
||||
Tfds.Eq(expd, actl, raw);
|
||||
}
|
||||
public void Test_hex(String raw, int expd_val) {Test_hex(raw, expd_val, true);}
|
||||
public void Test_hex(String raw, int expd_val, boolean expd_pass) {
|
||||
parser.Hex_enabled_(true);
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
int actl = parser.Parse(raw_bry, 0, raw_bry.length).Rv_as_int();
|
||||
if (expd_pass) {
|
||||
Tfds.Eq(expd_val, actl, raw);
|
||||
Tfds.Eq(true, !parser.Has_err());
|
||||
}
|
||||
else
|
||||
Tfds.Eq(false, !parser.Has_err());
|
||||
parser.Hex_enabled_(false);
|
||||
}
|
||||
}
|
||||
58
400_xowa/src_060_utl/gplx/Obj_ary_parser_base.java
Normal file
58
400_xowa/src_060_utl/gplx/Obj_ary_parser_base.java
Normal 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;
|
||||
public abstract class Obj_ary_parser_base {
|
||||
int pos_len = 4; int[] pos;
|
||||
protected abstract void Ary_len_(int v);
|
||||
protected abstract void Parse_itm(byte[] bry, int bgn, int end);
|
||||
protected void Parse_core(byte[] bry, int bgn, int end, byte dlm_1, byte dlm_2) {
|
||||
if (pos == null) pos = new int[pos_len];
|
||||
if (end - bgn == 0) {
|
||||
this.Ary_len_(0);
|
||||
return;
|
||||
}
|
||||
int pos_idx = 0;
|
||||
int dlm_last = -1; // NOTE: -1 b/c dlm_2 can be 0 (Byte_ascii.Nil) and need to do dlm_last != dlm_2 check below
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = bry[i];
|
||||
if (b == dlm_1 || b == dlm_2) {
|
||||
if (pos_idx == pos_len - 1) { // -1 b/c pos[] will always be count_of_dlm + 1
|
||||
pos_len *= 2;
|
||||
int[] pos_new = new int[pos_len];
|
||||
Array_.Copy(pos, pos_new);
|
||||
pos = pos_new;
|
||||
}
|
||||
pos[pos_idx++] = i;
|
||||
dlm_last = b;
|
||||
}
|
||||
}
|
||||
if (dlm_last != dlm_2)
|
||||
pos[pos_idx++] = end;
|
||||
this.Ary_len_(pos_idx);
|
||||
int parse_bgn = bgn;
|
||||
for (int i = 0; i < pos_idx; i++) {
|
||||
int parse_end = pos[i];
|
||||
this.Parse_itm(bry, parse_bgn, parse_end);
|
||||
parse_bgn = parse_end + 1;
|
||||
}
|
||||
if (pos_len > 255) { // reset
|
||||
pos_len = 4;
|
||||
pos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
142
400_xowa/src_060_utl/gplx/StatRng.java
Normal file
142
400_xowa/src_060_utl/gplx/StatRng.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
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;
|
||||
class StatRng_fxt {
|
||||
StatRng rng;
|
||||
public StatRng_fxt ini_(int lo_ary_len, int hi_ary_len, int... slot_hi_ary) {
|
||||
rng = new StatRng(lo_ary_len, hi_ary_len, slot_hi_ary);
|
||||
return this;
|
||||
}
|
||||
public StatRng_fxt tst_(int... vals) {
|
||||
for (int i = 0; i < vals.length; i++) {
|
||||
int val = vals[i];
|
||||
rng.Assign(val, val);
|
||||
}
|
||||
Tfds.Eq(expd_count, rng.Count, "Count");
|
||||
Tfds.Eq(expd_lo, rng.Lo, "Lo");
|
||||
Tfds.Eq(expd_hi, rng.Hi, "Hi");
|
||||
Tfds.Eq_float(expd_avg, rng.Avg());
|
||||
Tfds.Eq_ary(expd_lo_ary, XtoIntAry(rng.Lo_ary), "Lo_ary");
|
||||
Tfds.Eq_ary(expd_hi_ary, XtoIntAry(rng.Hi_ary), "Hi_ary");
|
||||
Tfds.Eq_ary(expd_slots, XtoIntAry(rng.Slot_ary), "Slots");
|
||||
return this;
|
||||
}
|
||||
int[] XtoIntAry(StatItm[] ary) {
|
||||
int[] rv = new int[ary.length];
|
||||
for (int i = 0; i < rv.length; i++)
|
||||
rv[i] = ary[i].Val;
|
||||
return rv;
|
||||
}
|
||||
int[] XtoIntAry(StatRng[] ary) {
|
||||
int[] rv = new int[ary.length];
|
||||
for (int i = 0; i < rv.length; i++)
|
||||
rv[i] = ary[i].Count;
|
||||
return rv;
|
||||
}
|
||||
public StatRng_fxt Count_(int v) {expd_count = v; return this;} private int expd_count;
|
||||
public StatRng_fxt Lo_(int v) {expd_lo = v; return this;} private int expd_lo;
|
||||
public StatRng_fxt Hi_(int v) {expd_hi = v; return this;} private int expd_hi;
|
||||
public StatRng_fxt Avg_(float v) {expd_avg = v; return this;} float expd_avg;
|
||||
public StatRng_fxt Lo_ary_(int... v) {expd_lo_ary = v; return this;} private int[] expd_lo_ary;
|
||||
public StatRng_fxt Hi_ary_(int... v) {expd_hi_ary = v; return this;} private int[] expd_hi_ary;
|
||||
public StatRng_fxt Slots_(int... v) {expd_slots = v; return this;} private int[] expd_slots;
|
||||
}
|
||||
class StatRng {
|
||||
// public String Key;
|
||||
public int Lo = Int_.MaxValue;
|
||||
public int Hi = Int_.MinValue;
|
||||
public long Sum = 0;
|
||||
public int Count = 0;
|
||||
public float Avg() {return Sum / Count;}
|
||||
public final StatItm[] Lo_ary;
|
||||
public int Lo_ary_bound;
|
||||
public int Lo_ary_len;
|
||||
public final StatItm[] Hi_ary;
|
||||
public int Hi_ary_bound;
|
||||
public int Hi_ary_len;
|
||||
public StatRng[] Slot_ary;
|
||||
public int Slot_ary_len;
|
||||
public StatRng(int lo_ary_len, int hi_ary_len, int... slot_hi_ary) {
|
||||
this.Lo_ary_len = lo_ary_len;
|
||||
this.Lo_ary_bound = Int_.MaxValue;
|
||||
this.Lo_ary = NewBoundAry(lo_ary_len, Int_.MaxValue);
|
||||
this.Hi_ary_len = hi_ary_len;
|
||||
this.Hi_ary_bound = Int_.MinValue;
|
||||
this.Hi_ary = NewBoundAry(hi_ary_len, Int_.MinValue);
|
||||
if (slot_hi_ary != null && slot_hi_ary.length > 0) {
|
||||
Slot_ary_len = slot_hi_ary.length + 1; // + 1 to hold max value
|
||||
Slot_ary = new StatRng[Slot_ary_len];
|
||||
int slot_lo = Int_.MinValue;
|
||||
for (int i = 0; i < Slot_ary_len - 1; i++) {
|
||||
int slot_hi = slot_hi_ary[i];
|
||||
Slot_ary[i] = NewSlot(slot_lo, slot_hi);
|
||||
slot_lo = slot_hi;
|
||||
}
|
||||
Slot_ary[Slot_ary_len - 1] = NewSlot(slot_lo, Int_.MaxValue);
|
||||
}
|
||||
}
|
||||
public void Assign(Object key, int val) {
|
||||
if (val < Lo) Lo = val;
|
||||
if (val > Hi) Hi = val;
|
||||
Sum += val;
|
||||
++Count;
|
||||
|
||||
if (Slot_ary_len > 0) {
|
||||
for (int i = 0; i < Slot_ary_len; i++) {
|
||||
StatRng slot = Slot_ary[i];
|
||||
if (val >= slot.Lo && val < slot.Hi)
|
||||
slot.Assign(key, val);
|
||||
}
|
||||
}
|
||||
if (val < Lo_ary_bound) {
|
||||
Lo_ary_bound = CalcCutoff(Lo_ary, CompareAble_.More, Int_.MinValue, key, val);
|
||||
}
|
||||
if (val > Hi_ary_bound) {
|
||||
Hi_ary_bound = CalcCutoff(Hi_ary, CompareAble_.Less, Int_.MaxValue, key, val);
|
||||
}
|
||||
}
|
||||
int CalcCutoff(StatItm[] ary, int comp, int bgn_bound, Object key, int val) {
|
||||
int new_bound = bgn_bound;
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
StatItm itm = ary[i];
|
||||
if (Int_.Compare(itm.Val, val) == comp) {
|
||||
itm = new StatItm(key, val);
|
||||
ary[i] = itm;
|
||||
}
|
||||
if (Int_.Compare(itm.Val, new_bound) == comp) new_bound = itm.Val;
|
||||
}
|
||||
return new_bound;
|
||||
}
|
||||
StatRng NewSlot(int lo, int hi) {
|
||||
StatRng rv = new StatRng(0, 0);
|
||||
rv.Lo = lo;
|
||||
rv.Hi = hi;
|
||||
return rv;
|
||||
}
|
||||
StatItm[] NewBoundAry(int len, int dflt) {
|
||||
StatItm[] rv = new StatItm[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = new StatItm(null, dflt);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class StatItm {
|
||||
public Object Key;
|
||||
public int Val;
|
||||
public StatItm(Object key, int val) {this.Key = key; this.Val = val;}
|
||||
}
|
||||
39
400_xowa/src_060_utl/gplx/StatRng_tst.java
Normal file
39
400_xowa/src_060_utl/gplx/StatRng_tst.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class StatRng_tst {
|
||||
// Mwl_parser_fxt fx = new Mwl_parser_fxt(); Pf_func_lang_rsc rsc = Pf_func_lang_rsc._;
|
||||
StatRng_fxt fx = new StatRng_fxt();
|
||||
@Test public void Empty() {
|
||||
fx.ini_(1, 1, 5);
|
||||
fx.Count_(7).Lo_(2).Hi_(8).Avg_(5)
|
||||
.Lo_ary_(2)
|
||||
.Hi_ary_(8)
|
||||
.Slots_(3, 4);
|
||||
fx.tst_(5,7,2,8,3,4,6);
|
||||
}
|
||||
//@Test public void Basic() {fx.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a=1|b=2|3}}", "{{test|a}}", "1");}
|
||||
//@Test public void Basic() {fx.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|b=2|#default=3|a=1}}", "{{test|a}}", "1");}
|
||||
//@Test public void Basic() {fx.Test_parse_tmpl_str_test("{{#switch:{{{1}}}|a|b|c=1|d=2}}", "{{test|a}}", "1");}
|
||||
}
|
||||
/*
|
||||
public class Pf_func_switch_tst {
|
||||
// Mwl_parser_fxt fx = new Mwl_parser_fxt(); Pf_func_lang_rsc rsc = Pf_func_lang_rsc._;
|
||||
|
||||
*/
|
||||
30
400_xowa/src_060_utl/gplx/Tst_chkr.java
Normal file
30
400_xowa/src_060_utl/gplx/Tst_chkr.java
Normal 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;
|
||||
public interface Tst_chkr {
|
||||
Class<?> TypeOf();
|
||||
int Chk(Tst_mgr mgr, String path, Object actl);
|
||||
}
|
||||
class Tst_chkr_null implements Tst_chkr {
|
||||
public Class<?> TypeOf() {return Object.class;}
|
||||
public int Chk(Tst_mgr mgr, String path, Object actl) {
|
||||
mgr.Results().Add(Tst_itm.fail_("!=", path, "<cast type>", "<NULL TYPE>", ClassAdp_.NameOf_obj(actl)));
|
||||
// mgr.Results().Add(Tst_itm.fail_("!=", path, "<cast value>", "<NULL VAL>", Object_.Xto_str_strict_or_null(actl)));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
134
400_xowa/src_060_utl/gplx/Tst_mgr.java
Normal file
134
400_xowa/src_060_utl/gplx/Tst_mgr.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*;
|
||||
public class Tst_mgr {
|
||||
public Tst_mgr ThrowError_n_() {throwError = false; return this;} private boolean throwError = true;
|
||||
public List_adp Results() {return results;} List_adp results = List_adp_.new_();
|
||||
public KeyValHash Vars() {return vars;} KeyValHash vars = KeyValHash.new_();
|
||||
public Object Vars_get_by_key(String key) {return vars.FetchValOr(key, null);}
|
||||
public String Vars_get_bry_as_str(String key, int bgn, int end) {
|
||||
byte[] bry = (byte[])vars.FetchValOr(key, null); if (bry == null) return String_.Empty;
|
||||
if (bgn < 0 || end > bry.length || end < bgn || end < 0) return "<<OUT OF BOUNDS>>";
|
||||
return String_.new_u8(Bry_.Mid(bry, bgn, end));
|
||||
}
|
||||
public int Tst_val(boolean skip, String path, String name, Object expd, Object actl) {
|
||||
Tst_itm itm = Tst_itm.eq_(skip, path, name, expd, actl);
|
||||
results.Add(itm);
|
||||
return itm.Pass() ? 0 : 1;
|
||||
}
|
||||
public int Tst_val_ary(boolean skip, String path, String name, Object expd, Object actl) {
|
||||
Tst_itm itm = Tst_itm.eq_(skip, path, name, XtoStr(expd), XtoStr(actl));
|
||||
results.Add(itm);
|
||||
return itm.Pass() ? 0 : 1;
|
||||
}
|
||||
public void Tst_obj(Tst_chkr expd, Object actl) {
|
||||
results.Clear();
|
||||
int err = Tst_sub_obj(expd, actl, "", 0);
|
||||
if (throwError && err > 0) throw Exc_.new_(Build());
|
||||
}
|
||||
public void Tst_ary(String ownerPath, Tst_chkr[] expd_ary, Object[] actl_ary) {
|
||||
results.Clear();
|
||||
Tst_ary_inner(ownerPath, expd_ary, actl_ary);
|
||||
}
|
||||
private void Tst_ary_inner(String ownerPath, Tst_chkr[] expd_ary, Object[] actl_ary) {
|
||||
int expd_ary_len = expd_ary.length, actl_ary_len = actl_ary.length;
|
||||
int max_len = expd_ary_len > actl_ary_len ? expd_ary_len : actl_ary_len;
|
||||
int err = 0;
|
||||
for (int i = 0; i < max_len; i++) {
|
||||
String path = ownerPath + Int_.Xto_str(i);
|
||||
Tst_chkr expd_obj = i < expd_ary_len ? expd_ary[i] : Tst_mgr.Null_chkr;
|
||||
Object actl_obj = i < actl_ary_len ? actl_ary[i] : "<NULL OBJ>";
|
||||
String actl_type = i < actl_ary_len ? ClassAdp_.NameOf_obj(actl_obj) : "<NULL TYPE>";
|
||||
err += Tst_inner(expd_obj, actl_obj, actl_type, path, err);
|
||||
}
|
||||
if (throwError && err > 0) {
|
||||
String s = Build();
|
||||
throw Exc_.new_(s);
|
||||
}
|
||||
}
|
||||
public int Tst_sub_obj(Tst_chkr expd, Object actl, String path, int err) {
|
||||
return Tst_inner(expd, actl, actl == null ? "<NULL>" : ClassAdp_.NameOf_obj(actl), path, err);
|
||||
}
|
||||
public int Tst_sub_ary(Tst_chkr[] expd_subs, Object[] actl_subs, String path, int err) {
|
||||
Tst_ary_inner(path + ".", expd_subs, actl_subs);
|
||||
return err;
|
||||
}
|
||||
int Tst_inner(Tst_chkr expd_obj, Object actl_obj, String actl_type, String path, int err) {
|
||||
if (actl_obj == null || !ClassAdp_.IsAssignableFrom(expd_obj.TypeOf(), actl_obj.getClass())) {
|
||||
results.Add(Tst_itm.fail_("!=", path, "<cast type>", ClassAdp_.NameOf_type(expd_obj.TypeOf()), actl_type));
|
||||
return 1;
|
||||
// results.Add(Tst_itm.fail_("!=", path, "<cast value>", Object_.Xto_str_strict_or_null(expd_obj.ValueOf()), Object_.Xto_str_strict_or_null(actl_obj)));
|
||||
}
|
||||
else {
|
||||
return expd_obj.Chk(this, path, actl_obj);
|
||||
}
|
||||
}
|
||||
String XtoStr(Object ary) {
|
||||
if (ary == null) return "<NULL>";
|
||||
int len = Array_.Len(ary);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Object itm = Array_.Get_at(ary, i);
|
||||
ary_sb.Add(Object_.Xto_str_strict_or_null_mark(itm)).Add(",");
|
||||
}
|
||||
return ary_sb.Xto_str_and_clear();
|
||||
} String_bldr ary_sb = String_bldr_.new_();
|
||||
String Build() {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int comp_max = 0, path_max =0, name_max = 0;
|
||||
int len = results.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Tst_itm itm = (Tst_itm)results.Get_at(i);
|
||||
comp_max = Max(comp_max, itm.Comp());
|
||||
path_max = Max(path_max, itm.Path());
|
||||
name_max = Max(name_max, itm.Name());
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
Tst_itm itm = (Tst_itm)results.Get_at(i);
|
||||
sb.Add_fmt("\n{0} {1} {2} '{3}'", String_.PadEnd(itm.Comp(), comp_max, " "), "#" + String_.PadEnd(itm.Path(), path_max, " "), "@" + String_.PadEnd(itm.Name(), name_max, " ") + ":", itm.Expd());
|
||||
if (!itm.Pass())
|
||||
sb.Add_fmt("\n{0} {1} {2} '{3}'", String_.PadEnd("", comp_max, " "), " " + String_.PadEnd("", path_max, " "), " " + String_.PadEnd("", name_max, " ") + " ", itm.Actl());
|
||||
}
|
||||
return sb.Xto_str_and_clear();
|
||||
}
|
||||
int Max(int max, String s) {int len = String_.Len(s); return len > max ? len : max;}
|
||||
public static final Tst_chkr Null_chkr = new Tst_chkr_null();
|
||||
}
|
||||
class Tst_itm {
|
||||
public boolean Pass() {return pass;} private boolean pass;
|
||||
public boolean Skip() {return skip;} private boolean skip;
|
||||
public String Comp() {return comp;} public Tst_itm Comp_(String v) {comp = v; return this;} private String comp = "";
|
||||
public String Path() {return path;} public Tst_itm Path_(String v) {path = v; return this;} private String path = "";
|
||||
public String Name() {return name;} public Tst_itm Name_(String v) {name = v; return this;} private String name = "";
|
||||
public String Expd() {return expd;} public Tst_itm Expd_(String v) {expd = v; return this;} private String expd = "";
|
||||
public String Actl() {return actl;} public Tst_itm Actl_(String v) {actl = v; return this;} private String actl = "";
|
||||
public static Tst_itm eq_(boolean skip, String path, String name, Object expd, Object actl) {
|
||||
boolean pass = skip ? true : Object_.Eq(expd, actl);
|
||||
String comp = pass ? "==" : "!=";
|
||||
String expd_str = Object_.Xto_str_strict_or_null_mark(expd);
|
||||
String actl_str = Object_.Xto_str_strict_or_null_mark(actl);
|
||||
if (skip) expd_str = actl_str;
|
||||
return new_(skip, pass, comp, path, name, expd_str, actl_str);
|
||||
}
|
||||
public static Tst_itm fail_(String comp, String path, String name, String expd, String actl) {return new_(false, false, comp, path, name, expd, actl);}
|
||||
public static Tst_itm new_(boolean skip, boolean pass, String comp, String path, String name, String expd, String actl) {
|
||||
Tst_itm rv = new Tst_itm();
|
||||
rv.skip = skip; rv.pass = pass; rv.comp = comp; rv.path = path; rv.name = name;; rv.expd = expd; rv.actl = actl;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
309
400_xowa/src_060_utl/gplx/Url_encoder.java
Normal file
309
400_xowa/src_060_utl/gplx/Url_encoder.java
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.btries.*;
|
||||
import gplx.xowa.parsers.amps.*;
|
||||
public class Url_encoder implements Url_encoder_interface {
|
||||
private Url_encoder_itm[] encode_ary = new Url_encoder_itm[256], decode_ary = new Url_encoder_itm[256];
|
||||
private Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
|
||||
private Url_encoder anchor_encoder = null;
|
||||
private Object thread_lock = new Object();
|
||||
public void Itms_ini(byte primary_encode_marker) {
|
||||
Url_encoder_itm_hex hex = new Url_encoder_itm_hex(primary_encode_marker);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
encode_ary[i] = hex; // default encode to hex
|
||||
decode_ary[i] = Url_encoder_itm_same._; // default decode to same; needed for files; EX: A!%21.png -> A!!.png;
|
||||
}
|
||||
decode_ary[primary_encode_marker] = hex;
|
||||
}
|
||||
public void Itms_raw_diff_many(byte primary_encode_marker, int... ary) {
|
||||
Url_encoder_itm_hex hex = new Url_encoder_itm_hex(primary_encode_marker);
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
encode_ary[ary[i]] = hex;
|
||||
decode_ary[ary[i]] = hex;
|
||||
}
|
||||
decode_ary[primary_encode_marker] = hex;
|
||||
}
|
||||
public void Itms_decode_marker(byte decode_marker) {
|
||||
Url_encoder_itm_hex hex = new Url_encoder_itm_hex(decode_marker);
|
||||
decode_ary[decode_marker & 0xff] = hex;// PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
public void Itms_decode_diff(byte orig, byte repl) {
|
||||
decode_ary[orig & 0xff] = new Url_encoder_itm_diff(orig, repl);// PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
public void Itms_raw_same_rng(int bgn, int end) {
|
||||
for (int i = bgn; i <= end; i++) {
|
||||
encode_ary[i] = Url_encoder_itm_same._;
|
||||
decode_ary[i] = Url_encoder_itm_same._;
|
||||
}
|
||||
}
|
||||
public Url_encoder Itms_raw_same_many(int... ary) {
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
encode_ary[ary[i]] = Url_encoder_itm_same._;
|
||||
decode_ary[ary[i]] = Url_encoder_itm_same._;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Itms_raw_html_ent(byte src, Btrie_slim_mgr trie) {
|
||||
Url_encoder_itm_html_ent itm = new Url_encoder_itm_html_ent(trie);
|
||||
encode_ary[src] = itm;
|
||||
}
|
||||
public Url_encoder Itms_raw_diff(byte src, byte trg) {
|
||||
Url_encoder_itm_diff itm = new Url_encoder_itm_diff(src, trg);
|
||||
encode_ary[src] = itm;
|
||||
decode_ary[trg] = itm;
|
||||
return this;
|
||||
}
|
||||
public byte[] Encode_http(Io_url url) {
|
||||
synchronized (thread_lock) {
|
||||
tmp_bfr.Add(Io_url.Http_file_bry);
|
||||
Encode(tmp_bfr, url.RawBry());
|
||||
return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public String Encode_str(String str) {
|
||||
synchronized (thread_lock) {
|
||||
byte[] bry = Bry_.new_u8(str); Encode(tmp_bfr, bry, 0, bry.length); return tmp_bfr.Xto_str_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Encode_bry(String str) {
|
||||
synchronized (thread_lock) {
|
||||
byte[] bry = Bry_.new_u8(str); Encode(tmp_bfr, bry, 0, bry.length); return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Encode(byte[] bry) {Encode(tmp_bfr, bry, 0, bry.length); return tmp_bfr.Xto_bry_and_clear();}
|
||||
public Bry_bfr Encode(Bry_bfr bfr, byte[] bry) {Encode(bfr, bry, 0, bry.length); return bfr;}
|
||||
public void Encode(Bry_bfr bfr, byte[] bry, int bgn, int end) {
|
||||
synchronized (thread_lock) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = bry[i];
|
||||
if (anchor_encoder != null && b == Byte_ascii.Hash) {
|
||||
bfr.Add_byte(Byte_ascii.Hash);
|
||||
anchor_encoder.Encode(bfr, bry, i + 1, end);
|
||||
break;
|
||||
}
|
||||
Url_encoder_itm itm = encode_ary[b & 0xff];// PATCH.JAVA:need to convert to unsigned byte
|
||||
i += itm.Encode(bfr, bry, end, i, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Decode_str(String str) {
|
||||
synchronized (thread_lock) {
|
||||
byte[] bry = Bry_.new_u8(str); Decode(bry, 0, bry.length, tmp_bfr, true); return tmp_bfr.Xto_str_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Decode(byte[] bry) {
|
||||
synchronized (thread_lock) {
|
||||
Decode(bry, 0, bry.length, tmp_bfr, false); return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Decode_lax(byte[] bry) {
|
||||
synchronized (thread_lock) {
|
||||
Decode(bry, 0, bry.length, tmp_bfr, false); return tmp_bfr.Xto_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public void Decode(byte[] bry, int bgn, int end, Bry_bfr bfr, boolean fail_when_invalid) {
|
||||
synchronized (thread_lock) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = bry[i];
|
||||
if (anchor_encoder != null && b == Byte_ascii.Hash) {
|
||||
bfr.Add_byte(Byte_ascii.Hash);
|
||||
anchor_encoder.Decode(bry, i + 1, end, bfr, false);
|
||||
break;
|
||||
}
|
||||
Url_encoder_itm itm = decode_ary[b & 0xff];// PATCH.JAVA:need to convert to unsigned byte
|
||||
i += itm.Decode(bfr, bry, end, i, b, fail_when_invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void mediawiki_base(Url_encoder rv, boolean encode_colon) {
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Num_0, Byte_ascii.Num_9);
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Ltr_A, Byte_ascii.Ltr_Z);
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Ltr_a, Byte_ascii.Ltr_z);
|
||||
rv.Itms_raw_same_many(Byte_ascii.Dash, Byte_ascii.Dot, Byte_ascii.Underline);
|
||||
if (encode_colon)
|
||||
rv.Itms_raw_same_many(Byte_ascii.Colon);
|
||||
}
|
||||
public static Url_encoder new_html_id_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Dot);
|
||||
mediawiki_base(rv, true);
|
||||
rv.Itms_decode_marker(Byte_ascii.Dot);
|
||||
rv.Itms_raw_diff(Byte_ascii.Space, Byte_ascii.Underline);
|
||||
rv.Itms_raw_html_ent(Byte_ascii.Amp, Xop_amp_trie._);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_http_url_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, false);
|
||||
rv.Itms_raw_diff(Byte_ascii.Space, Byte_ascii.Plus);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_http_url_ttl_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, true);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_http_url_space_is_space() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, true);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_fsys_lnx_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, true);
|
||||
rv.Itms_raw_same_many(Byte_ascii.Slash);
|
||||
rv.Itms_raw_diff(Byte_ascii.Backslash, Byte_ascii.Slash);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_fsys_wnt_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Num_0, Byte_ascii.Num_9);
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Ltr_A, Byte_ascii.Ltr_Z);
|
||||
rv.Itms_raw_same_rng(Byte_ascii.Ltr_a, Byte_ascii.Ltr_z);
|
||||
rv.Itms_raw_same_many
|
||||
( Byte_ascii.Bang, Byte_ascii.At, Byte_ascii.Hash, Byte_ascii.Dollar, Byte_ascii.Percent, Byte_ascii.Pow, Byte_ascii.Amp
|
||||
, Byte_ascii.Plus, Byte_ascii.Eq, Byte_ascii.Underline, Byte_ascii.Dash
|
||||
, Byte_ascii.Dot, Byte_ascii.Comma
|
||||
, Byte_ascii.Tick, Byte_ascii.Tilde, Byte_ascii.Brack_bgn, Byte_ascii.Brack_end, Byte_ascii.Curly_bgn, Byte_ascii.Curly_end);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_file_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, true);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_gfs_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
rv.Itms_raw_same_many(Byte_ascii.Paren_bgn, Byte_ascii.Paren_end, Byte_ascii.Apos, Byte_ascii.Semic);
|
||||
mediawiki_base(rv, true);
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_html_href_mw_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
mediawiki_base(rv, true);
|
||||
rv.Itms_raw_diff(Byte_ascii.Space, Byte_ascii.Underline);
|
||||
rv.Itms_raw_same_many(Byte_ascii.Semic, Byte_ascii.At, Byte_ascii.Dollar, Byte_ascii.Bang, Byte_ascii.Star
|
||||
, Byte_ascii.Paren_bgn, Byte_ascii.Paren_end, Byte_ascii.Comma, Byte_ascii.Slash, Byte_ascii.Colon
|
||||
, Byte_ascii.Hash// NOTE: not part of wfUrlEncode; not sure where this is specified; needed for A#b
|
||||
);
|
||||
rv.anchor_encoder = new_html_id_();
|
||||
return rv;
|
||||
}
|
||||
public static Url_encoder new_html_href_quotes_() {
|
||||
Url_encoder rv = new Url_encoder();
|
||||
rv.Itms_ini(Byte_ascii.Percent);
|
||||
rv.Itms_raw_same_rng(0, 255); // default everything to same;
|
||||
rv.Itms_raw_diff_many(Byte_ascii.Percent
|
||||
, Byte_ascii.Apos, Byte_ascii.Quote, Byte_ascii.Lt, Byte_ascii.Gt); // encode ', ", <, >
|
||||
rv.Itms_raw_diff(Byte_ascii.Space, Byte_ascii.Underline); // convert " " to "_"
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
interface Url_encoder_itm {
|
||||
int Encode(Bry_bfr bfr, byte[] src, int end, int idx, byte b);
|
||||
int Decode(Bry_bfr bfr, byte[] src, int end, int idx, byte b, boolean fail_when_invalid);
|
||||
}
|
||||
class Url_encoder_itm_same implements Url_encoder_itm {
|
||||
public int Encode(Bry_bfr bfr, byte[] src, int end, int idx, byte b) {bfr.Add_byte(b); return 0;}
|
||||
public int Decode(Bry_bfr bfr, byte[] src, int end, int idx, byte b, boolean fail_when_invalid) {bfr.Add_byte(b); return 0;}
|
||||
public static final Url_encoder_itm _ = new Url_encoder_itm_same();
|
||||
}
|
||||
class Url_encoder_itm_diff implements Url_encoder_itm {
|
||||
public Url_encoder_itm_diff(byte orig, byte repl) {this.orig = orig; this.repl = repl;} private byte orig, repl;
|
||||
public int Encode(Bry_bfr bfr, byte[] src, int end, int idx, byte b) {bfr.Add_byte(repl); return 0;}
|
||||
public int Decode(Bry_bfr bfr, byte[] src, int end, int idx, byte b, boolean fail_when_invalid) {bfr.Add_byte(orig); return 0;}
|
||||
}
|
||||
class Url_encoder_itm_hex implements Url_encoder_itm {
|
||||
public Url_encoder_itm_hex(byte encode_marker) {this.encode_marker = encode_marker;} private byte encode_marker;
|
||||
public int Encode(Bry_bfr bfr, byte[] src, int end, int idx, byte b) {Encode_byte(b, bfr, encode_marker); return 0;}
|
||||
public static void Encode_byte(byte b, Bry_bfr bfr, byte encode_marker) {
|
||||
int b_int = b & 0xFF;// PATCH.JAVA:need to convert to unsigned byte
|
||||
bfr.Add_byte(encode_marker);
|
||||
bfr.Add_byte(HexBytes[b_int >> 4]);
|
||||
bfr.Add_byte(HexBytes[b_int & 15]);
|
||||
}
|
||||
public int Decode(Bry_bfr bfr, byte[] src, int end, int idx, byte b, boolean fail_when_invalid) {
|
||||
if (idx + 2 >= end) {
|
||||
if (fail_when_invalid) throw Exc_.new_("decode needs 3 bytes", "idx", idx, "len", end, "snip", String_.new_u8(Bry_.Mid_by_len_safe(src, idx, 3)));
|
||||
else {
|
||||
bfr.Add_byte(b);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int hex_val = Int_.Xto_int_hex(src[idx + 1]);
|
||||
if (hex_val == -1) { // invalid hex byte; EX: %GC; DATE:2014-04-10
|
||||
bfr.Add_byte(b);
|
||||
return 0;
|
||||
}
|
||||
int v_0 = hex_val * 16;
|
||||
if (v_0 != -1) {
|
||||
int v_1 = Int_.Xto_int_hex(src[idx + 2]);
|
||||
if (v_1 != -1) {
|
||||
bfr.Add_byte((byte)(v_0 + v_1));
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if (fail_when_invalid)
|
||||
throw Exc_.new_("decode is invalid", "idx", idx, "snip", String_.new_u8(Bry_.Mid_by_len_safe(src, idx, 3)));
|
||||
else {
|
||||
bfr.Add_byte(b);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static final byte[] HexBytes = new byte[]
|
||||
{ Byte_ascii.Num_0, Byte_ascii.Num_1, Byte_ascii.Num_2, Byte_ascii.Num_3, Byte_ascii.Num_4, Byte_ascii.Num_5, Byte_ascii.Num_6, Byte_ascii.Num_7
|
||||
, Byte_ascii.Num_8, Byte_ascii.Num_9, Byte_ascii.Ltr_A, Byte_ascii.Ltr_B, Byte_ascii.Ltr_C, Byte_ascii.Ltr_D, Byte_ascii.Ltr_E, Byte_ascii.Ltr_F
|
||||
};
|
||||
}
|
||||
class Url_encoder_itm_html_ent implements Url_encoder_itm {
|
||||
public Url_encoder_itm_html_ent(Btrie_slim_mgr amp_trie) {this.amp_trie = amp_trie;} Btrie_slim_mgr amp_trie;
|
||||
public int Encode(Bry_bfr bfr, byte[] src, int end, int idx, byte b) {
|
||||
++idx; // b is &; get next character afterwards
|
||||
if (idx == end) { // & is last char; return
|
||||
Url_encoder_itm_hex.Encode_byte(Byte_ascii.Amp, bfr, Byte_ascii.Dot);
|
||||
return 0;
|
||||
}
|
||||
b = src[idx];
|
||||
Object o = amp_trie.Match_bgn_w_byte(b, src, idx, end);
|
||||
if (o == null) { // unknown entity (EX:&unknown;); return &;
|
||||
Url_encoder_itm_hex.Encode_byte(Byte_ascii.Amp, bfr, Byte_ascii.Dot);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
Xop_amp_trie_itm itm = (Xop_amp_trie_itm)o;
|
||||
byte[] bry_utf8 = itm.Utf8_bry(); // NOTE: must utf8 encode val; EX: is 160 but must become 192,160
|
||||
for (int i = 0; i < bry_utf8.length; i++)
|
||||
Url_encoder_itm_hex.Encode_byte(bry_utf8[i], bfr, Byte_ascii.Dot);
|
||||
return itm.Xml_name_bry().length - 1; // -1 to ignore & in XmlEntityName
|
||||
}
|
||||
}
|
||||
public int Decode(Bry_bfr bfr, byte[] src, int end, int idx, byte b, boolean fail_when_invalid) {
|
||||
bfr.Add_byte(b); return 0;
|
||||
}
|
||||
}
|
||||
72
400_xowa/src_060_utl/gplx/Url_encoder_tst.java
Normal file
72
400_xowa/src_060_utl/gplx/Url_encoder_tst.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class Url_encoder_tst {
|
||||
@Before public void init() {fxt = new Url_encoder_fxt();} Url_encoder_fxt fxt;
|
||||
@Test public void Id_nums() {fxt.Encoder_id().Test_encode_decode("0123456789", "0123456789");}
|
||||
@Test public void Id_ltrs_lower() {fxt.Encoder_id().Test_encode_decode("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz");}
|
||||
@Test public void Id_ltrs_upper() {fxt.Encoder_id().Test_encode_decode("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");}
|
||||
@Test public void Id_syms() {fxt.Encoder_id().Test_encode("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ".21.22.23.24.25.26.27.28.29.2A.2B.2C-..2F:.3B.3C.3D.3E.3F.40.5B.5C.5D.5E_.60.7B.7C.7D.7E");} // NOTE: not reversible since "." is encode_marker but not encoded
|
||||
@Test public void Id_foreign() {fxt.Encoder_id().Test_encode_decode("aéb", "a.C3.A9b");}
|
||||
@Test public void Id_space() {fxt.Encoder_id().Test_encode_decode("a b", "a_b");}
|
||||
@Test public void Id_err() {
|
||||
byte[] raw = Bry_.new_a7("0%.jpg");
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
fxt.Encoder_id().Encoder().Decode(raw, 0, raw.length, tmp_bfr, false);
|
||||
Tfds.Eq("0%.jpg", tmp_bfr.Xto_str_and_clear());
|
||||
}
|
||||
@Test public void Id_nbsp() {fxt.Encoder_id().Test_encode("a b", "a.C2.A0b");} // NOTE: not just .A0 (160) but utf8-encoded .C2.A0
|
||||
@Test public void Url_syms() {fxt.Encoder_url().Test_encode_decode("!?^~", "%21%3F%5E%7E");}
|
||||
@Test public void Url_foreign() {fxt.Encoder_url().Test_encode_decode("aéb", "a%C3%A9b");}
|
||||
@Test public void Url_space() {fxt.Encoder_url().Test_encode_decode("a b", "a+b");}
|
||||
@Test public void File_space() {
|
||||
fxt.Encoder_href().Test_encode("a b", "a_b");
|
||||
// fxt.Encoder_url().tst_decode("a_b", "a_b");
|
||||
}
|
||||
@Test public void Href_special_and_anchor() { // PURPOSE: MediaWiki encodes with % for ttls, but . for anchors; REF:Title.php!(before-anchor)getLocalUrl;wfUrlencode (after-anchor)escapeFragmentForURL
|
||||
fxt.Encoder_href().Test_encode("^#^", "%5E#.5E");
|
||||
fxt.Encoder_href().Test_encode("A#", "A#");
|
||||
fxt.Encoder_href().tst_decode("%5E#.5E", "^#^");
|
||||
}
|
||||
@Test public void Fsys_wnt() {
|
||||
fxt.Encoder_fsys_safe().Test_encode("Help:Options/HTML", "Help%3AOptions%2FHTML");
|
||||
}
|
||||
@Test public void Invalid_url_decode() { // PURPOSE: check that invalid url decodings are rendered literally; DATE:2014-04-10
|
||||
fxt.Encoder_href().Test_encode("%GC", "%25GC");
|
||||
}
|
||||
}
|
||||
class Url_encoder_fxt {
|
||||
public Url_encoder Encoder() {return encoder;} Url_encoder encoder;
|
||||
public Url_encoder_fxt Encoder_id() {encoder = Url_encoder.new_html_id_(); return this;}
|
||||
public Url_encoder_fxt Encoder_href() {encoder = Url_encoder.new_html_href_mw_(); return this;}
|
||||
public Url_encoder_fxt Encoder_url() {encoder = Url_encoder.new_http_url_(); return this;}
|
||||
public Url_encoder_fxt Encoder_fsys_safe() {encoder = Url_encoder.new_fsys_wnt_(); return this;}
|
||||
public void Test_encode_decode(String raw, String encoded) {
|
||||
Test_encode(raw, encoded);
|
||||
tst_decode(encoded, raw);
|
||||
}
|
||||
public void Test_encode(String raw, String expd) {
|
||||
byte[] bry = encoder.Encode(Bry_.new_u8(raw));
|
||||
Tfds.Eq(expd, String_.new_u8(bry));
|
||||
}
|
||||
public void tst_decode(String raw, String expd) {
|
||||
byte[] bry = encoder.Decode(Bry_.new_u8(raw));
|
||||
Tfds.Eq(expd, String_.new_u8(bry));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user