diff --git a/100_core/src/gplx/Bry_.java b/100_core/src/gplx/Bry_.java index 73c2b423e..e532f06df 100644 --- a/100_core/src/gplx/Bry_.java +++ b/100_core/src/gplx/Bry_.java @@ -154,7 +154,7 @@ public class Bry_ { public static byte[] Resize(byte[] src, int src_bgn, int trg_len) { byte[] trg = new byte[trg_len]; int src_len = src.length; if (src_len > trg_len) src_len = trg_len; // trg_len can be less than src_len - Copy_by_len(src, src_bgn, src_len, trg, 0); + Copy_to(src, src_bgn, src_len, trg, 0); return trg; } public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);} @@ -178,14 +178,14 @@ public class Bry_ { public static byte[] Add(byte[] src, byte b) { int src_len = src.length; byte[] rv = new byte[src_len + 1]; - Copy_by_pos(src, 0, src_len, rv, 0); + Copy_to(src, 0, src_len, rv, 0); rv[src_len] = b; return rv; } public static byte[] Add(byte b, byte[] src) { int src_len = src.length; byte[] rv = new byte[src_len + 1]; - Copy_by_pos(src, 0, src_len, rv, 1); + Copy_to(src, 0, src_len, rv, 1); rv[0] = b; return rv; } @@ -297,29 +297,30 @@ public class Bry_ { for (int i = 0; i < repl_len; i++) src[i + bgn] = repl[i]; } - public static void Copy_by_pos(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) { + public static void Copy_to(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) { int trg_adj = trg_bgn - src_bgn; for (int i = src_bgn; i < src_end; i++) trg[i + trg_adj] = src[i]; } - public static void Copy_by_pos_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) { + public static void Copy_to_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) { + // copies src to trg, but in reverse order; EX: trg="1" src="432." -> "1.234" int len = src_end - src_bgn; for (int i = 0; i < len; i++) trg[trg_bgn + i] = src[src_end - i - 1]; } - private static void Copy_by_len(byte[] src, int src_bgn, int src_len, byte[] trg, int trg_bgn) { - for (int i = 0; i < src_len; i++) - trg[i + trg_bgn] = src[i + src_bgn]; - } - public static byte[] Replace_one(byte[] src, byte[] find, byte[] repl) { - int src_len = src.length; - int findPos = Bry_find_.Find(src, find, 0, src_len, true); if (findPos == Bry_find_.Not_found) return src; - int findLen = find.length, replLen = repl.length; - int rvLen = src_len + replLen - findLen; - byte[] rv = new byte[rvLen]; - Copy_by_len(src , 0 , findPos , rv, 0 ); - Copy_by_len(repl, 0 , replLen , rv, findPos ); - Copy_by_len(src , findPos + findLen , src_len - findPos - findLen , rv, findPos + replLen); + public static byte[] Replace_one(byte[] orig, byte[] find, byte[] repl) { + // find val + int orig_len = orig.length; + int find_pos = Bry_find_.Find(orig, find, 0, orig_len, true); + if (find_pos == Bry_find_.Not_found) return orig; // nothing found; exit + + // do copy + int find_len = find.length, repl_len = repl.length; + int rv_len = orig_len + repl_len - find_len; + byte[] rv = new byte[rv_len]; + Copy_to(orig, 0 , find_pos, rv, 0 ); // copy orig before repl + Copy_to(repl, 0 , repl_len, rv, find_pos ); // copy repl + Copy_to(orig, find_pos + find_len, orig_len, rv, find_pos + repl_len); // copy orig after repl return rv; } public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);} diff --git a/100_core/src/gplx/Bry_bfr.java b/100_core/src/gplx/Bry_bfr.java index 9f4d25e62..4fe3f994c 100644 --- a/100_core/src/gplx/Bry_bfr.java +++ b/100_core/src/gplx/Bry_bfr.java @@ -79,7 +79,7 @@ public class Bry_bfr { public Bry_bfr Add(byte[] val) { int val_len = val.length; if (bfr_len + val_len > bfr_max) Resize((bfr_max + val_len) * 2); - Bry_.Copy_by_pos(val, 0, val_len, bfr, bfr_len); + Bry_.Copy_to(val, 0, val_len, bfr, bfr_len); // Array_.Copy_to(val, 0, bfr, bfr_len, val_len); bfr_len += val_len; return this; @@ -88,7 +88,7 @@ public class Bry_bfr { int len = end - bgn; if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11 if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2); - Bry_.Copy_by_pos(val, bgn, end, bfr, bfr_len); + Bry_.Copy_to(val, bgn, end, bfr, bfr_len); // Array_.Copy_to(val, bgn, bfr, bfr_len, len); bfr_len += len; return this; @@ -97,7 +97,7 @@ public class Bry_bfr { int len = end - bgn; if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11 if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2); - Bry_.Copy_by_pos_reversed(val, bgn, end, bfr, bfr_len); + Bry_.Copy_to_reversed(val, bgn, end, bfr, bfr_len); // Array_.Copy_to(val, bgn, bfr, bfr_len, len); bfr_len += len; return this; @@ -118,7 +118,7 @@ public class Bry_bfr { public Bry_bfr Add_bfr_and_preserve(Bry_bfr src) { int len = src.bfr_len; if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2); - Bry_.Copy_by_pos(src.bfr, 0, len, bfr, bfr_len); + Bry_.Copy_to(src.bfr, 0, len, bfr, bfr_len); // Array_.Copy_to(src.bfr, 0, bfr, bfr_len, len); bfr_len += len; return this; @@ -163,7 +163,7 @@ public class Bry_bfr { if (all_ws) return this; } src_len = src_end - src_bgn; - Bry_.Copy_by_pos(src.bfr, src_bgn, src_end, bfr, bfr_len); + Bry_.Copy_to(src.bfr, src_bgn, src_end, bfr, bfr_len); // Array_.Copy_to(src.bfr, src_bgn, bfr, bfr_len, src_len); bfr_len += src_len; src.Clear(); @@ -304,10 +304,10 @@ public class Bry_bfr { Add_mid(val, bgn, end); return this; } - public Bry_bfr Add_bry_many(byte[]... ary) { - int len = ary.length; + public Bry_bfr Add_bry_many(byte[]... val) { + int len = val.length; for (int i = 0; i < len; i++) { - byte[] bry = ary[i]; + byte[] bry = val[i]; if (bry != null && bry.length > 0) this.Add(bry); } @@ -338,10 +338,10 @@ public class Bry_bfr { } catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);} } - public Bry_bfr Add_str_u8_many(String... ary) { - int len = ary.length; + public Bry_bfr Add_str_u8_many(String... val) { + int len = val.length; for (int i = 0; i < len; ++i) - Add_str_u8(ary[i]); + Add_str_u8(val[i]); return this; } public Bry_bfr Add_str_u8_fmt(String fmt, Object... args) { @@ -364,6 +364,10 @@ public class Bry_bfr { } catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);} } + public Bry_bfr Add_str_mid(String src, int bgn, int end) { + this.Add_str_u8(String_.Mid(src, bgn, end)); + return this; + } public Bry_bfr Add_kv_dlm(boolean line, String key, Object val) { this.Add_str_a7(key).Add_byte_colon().Add_byte_space(); this.Add(Bry_.new_u8(Object_.Xto_str_strict_or_null_mark(val))); @@ -495,16 +499,16 @@ public class Bry_bfr { } public boolean Match_end_byt(byte b) {return bfr_len == 0 ? false : bfr[bfr_len - 1] == b;} public boolean Match_end_byt_nl_or_bos() {return bfr_len == 0 ? true : bfr[bfr_len - 1] == Byte_ascii.Nl;} - public boolean Match_end_ary(byte[] ary) {return Bry_.Match(bfr, bfr_len - ary.length, bfr_len, ary);} + public boolean Match_end_ary(byte[] val) {return Bry_.Match(bfr, bfr_len - val.length, bfr_len, val);} public Bry_bfr Insert_at(int add_pos, byte[] add_bry) {return Insert_at(add_pos, add_bry, 0, add_bry.length);} public Bry_bfr Insert_at(int add_pos, byte[] add_bry, int add_bgn, int add_end) { int add_len = add_end - add_bgn; int new_max = bfr_max + add_len; byte[] new_bfr = new byte[new_max]; if (add_pos > 0) - Bry_.Copy_by_pos (bfr , 0, add_pos, new_bfr, 0); - Bry_.Copy_by_pos (add_bry, add_bgn, add_end, new_bfr, add_pos); - Bry_.Copy_by_pos (bfr , add_pos, bfr_len, new_bfr, add_pos + add_len); + Bry_.Copy_to (bfr , 0, add_pos, new_bfr, 0); + Bry_.Copy_to (add_bry, add_bgn, add_end, new_bfr, add_pos); + Bry_.Copy_to (bfr , add_pos, bfr_len, new_bfr, add_pos + add_len); bfr = new_bfr; bfr_len += add_len; bfr_max = new_max; @@ -514,7 +518,7 @@ public class Bry_bfr { public Bry_bfr Delete_rng_to_end(int pos) {return Delete_rng(pos, bfr_len);} public Bry_bfr Delete_rng(int rng_bgn, int rng_end) { int rng_len = rng_end - rng_bgn; - Bry_.Copy_by_pos(bfr, rng_end, bfr_len, bfr, rng_bgn); + Bry_.Copy_to(bfr, rng_end, bfr_len, bfr, rng_bgn); bfr_len -= rng_len; return this; } @@ -564,10 +568,10 @@ public class Bry_bfr { rv[11] = true; return rv; } - public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... ary) { - int ary_len = ary.length; - for (int i = 0; i < ary_len; i++) { - byte[] itm = ary[i]; + public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... val) { + int val_len = val.length; + for (int i = 0; i < val_len; i++) { + byte[] itm = val[i]; boolean itm_has_bytes = Bry_.Len_gt_0(itm); if ( i != 0 && itm_has_bytes diff --git a/400_xowa/src/gplx/xowa/bldrs/Xobdc_utl.java b/400_xowa/src/gplx/xowa/bldrs/Xobdc_utl.java index f229de4d3..af21c17c4 100644 --- a/400_xowa/src/gplx/xowa/bldrs/Xobdc_utl.java +++ b/400_xowa/src/gplx/xowa/bldrs/Xobdc_utl.java @@ -21,7 +21,7 @@ class Io_sort_filCmd_reg implements Io_sort_filCmd { // 123|bgn|end|1 public void Bfr_add(Io_line_rdr stream) { ++itm_count; int key_bgn = stream.Key_pos_bgn(), key_end = stream.Key_pos_end(); - Bry_.Copy_by_pos(stream.Bfr(), key_bgn, key_end, prv_key, 0); prv_key_len = key_end - key_bgn; + Bry_.Copy_to(stream.Bfr(), key_bgn, key_end, prv_key, 0); prv_key_len = key_end - key_bgn; } byte[] prv_key = new byte[1024]; int prv_key_len = 0; public void Fil_bgn(Io_line_rdr stream) { bfr.Add_int_variable(fil_idx++).Add_byte(Byte_ascii.Pipe); diff --git a/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java b/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java index 94281ee0b..6fc7a15cf 100644 --- a/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java +++ b/400_xowa/src/gplx/xowa/files/Xof_file_wkr_.java @@ -44,7 +44,7 @@ public class Xof_file_wkr_ { if (b == Byte_ascii.Space) { if (!dirty) { dirty = true; - rv = new byte[len]; Bry_.Copy_by_pos(src, 0, i, rv, 0); + rv = new byte[len]; Bry_.Copy_to(src, 0, i, rv, 0); } rv[i] = Byte_ascii.Underline; } diff --git a/400_xowa/src/gplx/xowa/mediawiki/Char_bfr.java b/400_xowa/src/gplx/xowa/mediawiki/Char_bfr.java new file mode 100644 index 000000000..7e46dc56b --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/Char_bfr.java @@ -0,0 +1,77 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; +public class Char_bfr { + private char[] ary; + private int ary_len; + private int ary_max, ary_max_reset; + public Char_bfr(int ary_max) { + this.ary_max = ary_max; + ary = new char[ary_max]; + ary_max_reset = ary_max; + } + public Char_bfr Add_char(char val) { + int new_len = ary_len + 1; + if (new_len > ary_len) Resize(ary_len * 2); + ary[ary_len] = val; + ary_len = new_len; + return this; + } + public Char_bfr Add_chry(char[] val) { + int val_len = val.length; + if (ary_len + val_len > ary_max) Resize((ary_max + val_len) * 2); + Copy_to(val, 0, val_len, ary, ary_len); + ary_len += val_len; + return this; + } + public Char_bfr Add_bry(byte[] val) {return Add_str(String_.new_u8(val));} + public Char_bfr Add_str(String val) { + int val_len = String_.Len(val); + if (ary_len + val_len > ary_max) Resize((ary_max + val_len) * 2); + Copy_to(val, 0, val_len, ary, ary_len); + ary_len += val_len; + return this; + } + private void Resize(int new_max) { + ary_max = new_max; + ary = Resize(ary, 0, new_max); + } + public String To_str_and_clear() { + String rv = String_.new_charAry_(ary, 0, ary_len); + ary_len = 0; + ary_max = ary_max_reset; + return rv; + } + public byte[] To_bry_and_clear() { + return Bry_.new_u8(To_str_and_clear()); + } + private static char[] Resize(char[] src, int src_bgn, int trg_len) { + char[] trg = new char[trg_len]; + int src_len = src.length; if (src_len > trg_len) src_len = trg_len; // trg_len can be less than src_len + Copy_to(src, src_bgn, src_len, trg, 0); + return trg; + } + private static void Copy_to(char[] src, int src_bgn, int src_end, char[] trg, int trg_bgn) { + int trg_adj = trg_bgn - src_bgn; + for (int i = src_bgn; i < src_end; i++) + trg[i + trg_adj] = src[i]; + } + private static void Copy_to(String src, int src_bgn, int src_end, char[] trg, int trg_bgn) { + int trg_adj = trg_bgn - src_bgn; + for (int i = src_bgn; i < src_end; i++) + trg[i + trg_adj] = String_.CharAt(src, i); + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java index a7cfd039e..1019e5b6e 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArray.java @@ -14,11 +14,123 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; -public class XophpArray { - public static boolean in_array(String needle, String[] haystack) { - for (String hay : haystack) - if (String_.Eq(hay, needle)) - return true; - return false; +import gplx.core.brys.*; +public class XophpArray implements Bry_bfr_able { + private final Ordered_hash hash = Ordered_hash_.New(); + private int nxt_idx; + public int Len() {return hash.Len();} + public void Clear() { + hash.Clear(); + nxt_idx = 0; + } + public XophpArray Add(Object val) { + int key = nxt_idx++; + XophpArrayItm itm = XophpArrayItm.New_int(key, val); + Set_or_add(key, itm); + return this; + } + public XophpArray Add(int key, Object val) { + nxt_idx = key + 1; + XophpArrayItm itm = XophpArrayItm.New_int(key, val); + Set_or_add(key, itm); + return this; + } + public XophpArray Add(double key, Object val) { + int key_as_int = (int)key; + nxt_idx = key_as_int + 1; + XophpArrayItm itm = XophpArrayItm.New_int(key_as_int, val); + Set_or_add(key_as_int, itm); + return this; + } + public XophpArray Add(boolean key, Object val) { + int key_as_int = key ? 1 : 0; + nxt_idx = key_as_int + 1; + XophpArrayItm itm = XophpArrayItm.New_int(key_as_int, val); + Set_or_add(key_as_int, itm); + return this; + } + public XophpArray Add(String key, Object val) { + XophpArrayItm itm = null; + int key_as_int = Int_.Parse_or(key, Int_.Min_value); + if (key_as_int == Int_.Min_value) { + itm = XophpArrayItm.New_str(key, val); + Set_or_add(key, itm); + } + else { + itm = XophpArrayItm.New_int(key_as_int, val); + Set_or_add(key_as_int, itm); + nxt_idx = key_as_int + 1; + } + return this; + } + public XophpArrayItm Get_at(int i) { + return (XophpArrayItm)hash.Get_at(i); + } + public void Del_at(int i) { + XophpArrayItm itm = (XophpArrayItm)hash.Get_at(i); + if (itm != null) { + if (itm.Key_as_str() == null) + hash.Del(itm.Key_as_int()); + else + hash.Del(itm.Key_as_str()); + } + } + private void Set_or_add(Object key, XophpArrayItm val) { + XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key); + if (itm == null) { + hash.Add(key, val); + } + else { + itm.Val_(val.Val()); + } + } + public XophpArray Add_many(Object... val) { + for (Object itm : val) { + Add(itm); + } + return this; + } + public Object Get(Object key) { + XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key); + return itm.Val(); + } + public void Set(int key, Object val) { + hash.Del(key); + this.Add(key, val); + } + public void Unset(Object key) { + hash.Del(key); + } + public boolean Has(Object key) { + return hash.Has(key); + } + public XophpArray Values() { + XophpArray rv = new XophpArray(); + int len = hash.Len(); + for (int i = 0; i < len; i++) { + XophpArrayItm old_itm = (XophpArrayItm)hash.Get_at(i); + rv.Add(i, old_itm.Val()); + } + return rv; + } + public XophpArrayItm[] To_ary() { + return (XophpArrayItm[])hash.To_ary(XophpArrayItm.class); + } + public String To_str() { + Bry_bfr bfr = Bry_bfr_.New(); + To_bfr(bfr); + return bfr.To_str_and_clear(); + } + public void To_bfr(Bry_bfr bfr) { + XophpArrayItm[] itms = To_ary(); + for (XophpArrayItm itm : itms) { + itm.To_bfr(bfr); + } + } + public static XophpArray New(Object... vals) { + XophpArray rv = new XophpArray(); + for (Object val : vals) + rv.Add(val); + return rv; } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_itm.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayItm.java similarity index 61% rename from 400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_itm.java rename to 400_xowa/src/gplx/xowa/mediawiki/XophpArrayItm.java index bd8752b3d..6410a00a9 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_itm.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayItm.java @@ -15,29 +15,32 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; import gplx.core.brys.*; -public class Xophp_ary_itm implements Bry_bfr_able { - public Xophp_ary_itm(int key_as_int, String key_as_str, Object val) { +public class XophpArrayItm implements Bry_bfr_able { + public XophpArrayItm(int key_as_int, String key_as_str, Object val) { + this.key_is_int = key_as_str == null; this.key_as_int = key_as_int; this.key_as_str = key_as_str; this.val = val; } + public boolean Key_is_int() {return key_is_int;} private final boolean key_is_int; public int Key_as_int() {return key_as_int;} private final int key_as_int; public String Key_as_str() {return key_as_str;} private final String key_as_str; - public Object Val() {return val;} private final Object val; + public Object Val() {return val;} public void Val_(Object v) {this.val = v;} private Object val; + public void To_bfr(Bry_bfr bfr) { String key = key_as_str == null ? Int_.To_str(key_as_int) : key_as_str; bfr.Add_str_u8(key).Add_byte_eq(); - if (Type_.Type_by_obj(val) == Xophp_ary.class) { - Xophp_ary sub_ary = (Xophp_ary)val; + if (Type_.Type_by_obj(val) == XophpArray.class) { + XophpArray sub_ary = (XophpArray)val; bfr.Add_byte_nl(); sub_ary.To_bfr(bfr); } else { - bfr.Add_obj(val); + bfr.Add_obj(val).Add_byte_space(); } } - public static Xophp_ary_itm New(int key, Object val) {return new Xophp_ary_itm(key, null, val);} - public static Xophp_ary_itm New(String key, Object val) {return new Xophp_ary_itm(-1 , key , val);} + public static XophpArrayItm New_int(int key, Object val) {return new XophpArrayItm(key, null, val);} + public static XophpArrayItm New_str(String key, Object val) {return new XophpArrayItm(-1 , key , val);} } diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl.java index a3b33c63d..95287a739 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl.java @@ -51,4 +51,83 @@ public class XophpArrayUtl { rv[i - 1] = ary[i]; return rv; } + public static boolean in_array(String needle, String[] haystack) { + for (String hay : haystack) + if (String_.Eq(hay, needle)) + return true; + return false; + } + public static XophpArray array_merge(XophpArray... vals) { + XophpArray rv = new XophpArray(); + for (XophpArray ary : vals) { + XophpArrayItm[] itms = ary.To_ary(); + for (XophpArrayItm itm : itms) { + array_add(rv, itm); + } + } + return rv; + } + private static void array_add(XophpArray ary, XophpArrayItm itm) { + if (itm.Key_as_str() == null) + ary.Add(itm.Val()); + else + ary.Add(itm.Key_as_str(), itm.Val()); + } + public static XophpArray array_splice(XophpArray src, int bgn) {return array_splice(src, bgn, src.Len(), null);} + public static XophpArray array_splice(XophpArray src, int bgn, int len) {return array_splice(src, bgn, len , null);} + public static XophpArray array_splice(XophpArray src, int bgn, int len, XophpArray repl) { + // get itms before clearing it + int src_len = src.Len(); + XophpArrayItm[] itms = src.To_ary(); + src.Clear(); + + // calc bgn + if (bgn < 0) { // negative bgn should be adusted from src_len; EX: -1 means start at last item + bgn += src_len; + if (bgn < 0) // large negative bgn should be capped at 0; EX: -99 + bgn = 0; + } + else if (bgn > src_len) // large positive bgn should be capped at src_len; EX: 99 + bgn = src_len; + + // add src from 0 to bgn + for (int i = 0; i < bgn; i++) { + array_add(src, itms[i]); + } + + // add repl + if (repl != null) { + XophpArrayItm[] repl_itms = repl.To_ary(); + for (XophpArrayItm itm : repl_itms) { + array_add(src, itm); + } + } + + // calc end + int end; + if (len < 0) { // negative len should be adjusted from src_len; EX: -1 means stop at last itm + end = src_len + len; + if (end < 0) // large_negative len should be capped at 0; EX: -99 + end = 0; + } + else { // positive len should be added to bgn to find end + end = bgn + len; + } + if (end < bgn) // end should never be less than bgn; EX: splice(1, -99) + end = bgn; + else if (end > src_len) // end should not be more then end; + end = src_len; + + // add src from end to len + for (int i = end; i < src_len; i++) { + array_add(src, itms[i]); + } + + // add del to rv + XophpArray rv = new XophpArray(); + for (int i = bgn; i < end; i++) { + array_add(rv, itms[i]); + } + return rv; + } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl_tst.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl_tst.java new file mode 100644 index 000000000..30197ea12 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArrayUtl_tst.java @@ -0,0 +1,228 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; +import org.junit.*; import gplx.core.tests.*; +public class XophpArrayUtl_tst { // REF:https://www.php.net/manual/en/function.array-merge.php + private final XophpArrayUtl_fxt fxt = new XophpArrayUtl_fxt(); + @Test public void array_merge__basic() { + XophpArray ary1 = fxt.Make().Add("key1", "val1").Add("a"); + XophpArray ary2 = fxt.Make().Add("key2", "val2").Add("b"); + fxt.Test__array_merge + ( fxt.Make().Add("key1", "val1").Add("a").Add("key2", "val2").Add("b") + , ary1, ary2); + } + @Test public void array_merge__same_key() { + XophpArray ary1 = fxt.Make().Add("key", "val1"); + XophpArray ary2 = fxt.Make().Add("key", "val2"); + fxt.Test__array_merge + ( fxt.Make().Add("key", "val2") + , ary1, ary2); + } + @Test public void array_merge__same_idx() { + XophpArray ary1 = fxt.Make().Add(0, "a"); + XophpArray ary2 = fxt.Make().Add(0, "b"); + fxt.Test__array_merge + ( fxt.Make().Add(0, "a").Add(1, "b") + , ary1, ary2); + } + @Test public void array_merge__renumber() { + XophpArray ary1 = fxt.Make().Add(3, "a"); + XophpArray ary2 = fxt.Make().Add(2, "b"); + fxt.Test__array_merge + ( fxt.Make().Add(0, "a").Add(1, "b") + , ary1, ary2); + } + @Test public void array_merge__example_1() { + XophpArray ary1 = fxt.Make().Add("color", "red").Add_many(2, 4); + XophpArray ary2 = fxt.Make().Add_many("a", "b").Add("color", "green").Add("shape", "trapezoid").Add(4); + fxt.Test__array_merge + ( fxt.Make().Add("color", "green").Add_many(2, 4, "a", "b").Add("shape", "trapezoid").Add(4) + , ary1, ary2); + } + @Test public void array_merge__example_2() { + XophpArray ary1 = fxt.Make(); + XophpArray ary2 = fxt.Make().Add(1, "data"); + fxt.Test__array_merge + ( fxt.Make().Add(0, "data") + , ary1, ary2); + } + @Test public void array_splice__bgn_is_positive() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1); + fxt.Test__eq + ( fxt.Make().Add_many("a") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("b", "c", "d") + , del + ); + } + @Test public void array_splice__bgn_is_positive_large() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 99); + fxt.Test__eq + ( fxt.Make().Add_many("a", "b", "c", "d") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many() + , del + ); + } + @Test public void array_splice__bgn_is_negative() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, -3); + fxt.Test__eq + ( fxt.Make().Add_many("a") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("b", "c", "d") + , del + ); + } + @Test public void array_splice__bgn_is_negative_large() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, -99); + fxt.Test__eq + ( fxt.Make() + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("a", "b", "c", "d") + , del + ); + } + @Test public void array_splice__len_is_positive() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, 2); + fxt.Test__eq + ( fxt.Make().Add_many("a", "d") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("b", "c") + , del + ); + } + @Test public void array_splice__len_is_positive_large() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, 99); + fxt.Test__eq + ( fxt.Make().Add_many("a") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("b", "c", "d") + , del + ); + } + @Test public void array_splice__len_is_negative() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, -2); + fxt.Test__eq + ( fxt.Make().Add_many("a", "c", "d") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("b") + , del + ); + } + @Test public void array_splice__len_is_negative_large() { + XophpArray src = fxt.Make().Add_many("a", "b", "c", "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, -99); + fxt.Test__eq + ( fxt.Make().Add_many("a", "b", "c", "d") + , src + ); + fxt.Test__eq + ( fxt.Make() + , del + ); + } + @Test public void array_splice__repl() { + XophpArray src = fxt.Make().Add(0, "a").Add(1, "b").Add(2, "c").Add(3, "d"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, 2, fxt.Make().Add(0, "x")); + fxt.Test__eq + ( fxt.Make().Add(0, "a").Add(1, "x").Add(2, "d") + , src + ); + fxt.Test__eq + ( fxt.Make().Add(0, "b").Add(1, "c") + , del + ); + } + @Test public void array_splice__example_1a() { + XophpArray src = fxt.Make().Add_many("red", "green", "blue", "yellow"); + XophpArray del = XophpArrayUtl.array_splice(src, 2); + fxt.Test__eq + ( fxt.Make().Add_many("red", "green") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("blue", "yellow") + , del + ); + } + @Test public void array_splice__example_1b() { + XophpArray src = fxt.Make().Add_many("red", "green", "blue", "yellow"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, -1); + fxt.Test__eq + ( fxt.Make().Add_many("red", "yellow") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("green", "blue") + , del + ); + } + @Test public void array_splice__example_1c() { + XophpArray src = fxt.Make().Add_many("red", "green", "blue", "yellow"); + XophpArray del = XophpArrayUtl.array_splice(src, 1, 4, XophpArray.New("orange")); + fxt.Test__eq + ( fxt.Make().Add_many("red", "orange") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("green", "blue", "yellow") + , del + ); + } + @Test public void array_splice__example_1d() { + XophpArray src = fxt.Make().Add_many("red", "green", "blue", "yellow"); + XophpArray del = XophpArrayUtl.array_splice(src, -1, 1, XophpArray.New("black", "maroon")); + fxt.Test__eq + ( fxt.Make().Add_many("red", "green", "blue", "black", "maroon") + , src + ); + fxt.Test__eq + ( fxt.Make().Add_many("yellow") + , del + ); + } +} +class XophpArrayUtl_fxt { + public XophpArray Make() {return new XophpArray();} + public void Test__array_merge(XophpArray expd, XophpArray... vals) { + XophpArray actl = XophpArrayUtl.array_merge(vals); + Gftest.Eq__str(expd.To_str(), actl.To_str()); + } + public void Test__eq(XophpArray expd, XophpArray actl) { + Gftest.Eq__str(expd.To_str(), actl.To_str()); + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_tst.java b/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java similarity index 60% rename from 400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_tst.java rename to 400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java index ec6f29c31..b80a595de 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary_tst.java +++ b/400_xowa/src/gplx/xowa/mediawiki/XophpArray_tst.java @@ -15,68 +15,68 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; import org.junit.*; import gplx.core.tests.*; -public class Xophp_ary_tst { // REF: http://php.net/manual/en/language.types.array.php +public class XophpArray_tst { // REF: http://php.net/manual/en/language.types.array.php private final XophpArray_fxt fxt = new XophpArray_fxt(); @Test public void array__kvs() { // $array = array("foo" => "bar", "bar" => "foo",); fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add("foo", "bar") . Add("bar", "foo") - , Xophp_ary_itm.New("foo", "bar") - , Xophp_ary_itm.New("bar", "foo") + , XophpArrayItm.New_str("foo", "bar") + , XophpArrayItm.New_str("bar", "foo") ); } @Test public void array__casting() { // $array = array(1 => "a", "1" => "b", 1.5 => "c", true => "d",); fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add(1 , "a") . Add("1" , "b") . Add(1.5 , "c") . Add(true, "d") - , Xophp_ary_itm.New(1, "d")); + , XophpArrayItm.New_int(1, "d")); } @Test public void array__mixed() { // $array = array("foo" => "bar", "bar" => "foo", 100 => -100, -100 => 100); fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add("foo", "bar") . Add("bar", "foo") . Add(100, -100) . Add(-100, 100) - , Xophp_ary_itm.New("foo", "bar") - , Xophp_ary_itm.New("bar", "foo") - , Xophp_ary_itm.New(100, -100) - , Xophp_ary_itm.New(-100, 100) + , XophpArrayItm.New_str("foo", "bar") + , XophpArrayItm.New_str("bar", "foo") + , XophpArrayItm.New_int(100, -100) + , XophpArrayItm.New_int(-100, 100) ); } @Test public void array__objs() { // $array = array("foo", "bar", "hello", "world"); fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add("foo") . Add("bar") . Add("hello") . Add("world") - , Xophp_ary_itm.New(0, "foo") - , Xophp_ary_itm.New(1, "bar") - , Xophp_ary_itm.New(2, "hello") - , Xophp_ary_itm.New(3, "world") + , XophpArrayItm.New_int(0, "foo") + , XophpArrayItm.New_int(1, "bar") + , XophpArrayItm.New_int(2, "hello") + , XophpArrayItm.New_int(3, "world") ); } @Test public void array__unkeyed() { // $array = array("a", "b", 6 => "c", "d"); fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add("a") . Add("b") . Add(6, "c") . Add("d") - , Xophp_ary_itm.New(0, "a") - , Xophp_ary_itm.New(1, "b") - , Xophp_ary_itm.New(6, "c") - , Xophp_ary_itm.New(7, "d") + , XophpArrayItm.New_int(0, "a") + , XophpArrayItm.New_int(1, "b") + , XophpArrayItm.New_int(6, "c") + , XophpArrayItm.New_int(7, "d") ); } @Test public void array__multidimensional() { @@ -92,23 +92,23 @@ public class Xophp_ary_tst { // REF: http://php.net/manual/en/language.types.arr ); */ fxt.Test__array - ( Xophp_ary.New() + ( XophpArray.New() . Add("foo" , "bar") . Add(42 , 24) - . Add("multi" , Xophp_ary.New() - . Add("dimensional", Xophp_ary.New() + . Add("multi" , XophpArray.New() + . Add("dimensional", XophpArray.New() . Add("array", "foo") )) - , Xophp_ary_itm.New("foo", "bar") - , Xophp_ary_itm.New(42, "24") - , Xophp_ary_itm.New("multi", Xophp_ary.New() - . Add("dimensional", Xophp_ary.New() + , XophpArrayItm.New_str("foo", "bar") + , XophpArrayItm.New_int(42, "24") + , XophpArrayItm.New_str("multi", XophpArray.New() + . Add("dimensional", XophpArray.New() . Add("array", "foo") )) ); } @Test public void array__unset() { - Xophp_ary ary = Xophp_ary.New(); + XophpArray ary = XophpArray.New(); ary.Add(0, "a").Add(1, "b"); // delete all @@ -118,20 +118,20 @@ public class Xophp_ary_tst { // REF: http://php.net/manual/en/language.types.arr // add new and assert idx is 2 ary.Add("c"); - fxt.Test__array(ary, Xophp_ary_itm.New(2, "c")); + fxt.Test__array(ary, XophpArrayItm.New_int(2, "c")); ary = ary.Values(); ary.Add("d"); - fxt.Test__array(ary, Xophp_ary_itm.New(0, "c"), Xophp_ary_itm.New(1, "d")); + fxt.Test__array(ary, XophpArrayItm.New_int(0, "c"), XophpArrayItm.New_int(1, "d")); } } class XophpArray_fxt { - public void Test__array(Xophp_ary ary, Xophp_ary_itm... expd) { - Xophp_ary_itm[] actl = ary.To_ary(); + public void Test__array(XophpArray ary, XophpArrayItm... expd) { + XophpArrayItm[] actl = ary.To_ary(); Gftest.Eq__ary(expd, actl); } - public void Test__unset(Xophp_ary ary, int idx, Xophp_ary_itm... expd) { - Xophp_ary_itm[] actl = ary.To_ary(); + public void Test__unset(XophpArray ary, int idx, XophpArrayItm... expd) { + XophpArrayItm[] actl = ary.To_ary(); Gftest.Eq__ary(expd, actl); } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary.java b/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary.java deleted file mode 100644 index d36cc7f22..000000000 --- a/400_xowa/src/gplx/xowa/mediawiki/Xophp_ary.java +++ /dev/null @@ -1,90 +0,0 @@ -/* -XOWA: the XOWA Offline Wiki Application -Copyright (C) 2012-2017 gnosygnu@gmail.com - -XOWA is licensed under the terms of the General Public License (GPL) Version 3, -or alternatively under the terms of the Apache License Version 2.0. - -You may use XOWA according to either of these licenses as is most appropriate -for your project on a case-by-case basis. - -The terms of each license can be found in the source code repository: - -GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt -Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt -*/ -package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*; -import gplx.core.brys.*; -public class Xophp_ary implements Bry_bfr_able { - private final Ordered_hash hash = Ordered_hash_.New(); - private int nxt_idx; - public Xophp_ary Add(Object val) { - int key = nxt_idx++; - Xophp_ary_itm itm = Xophp_ary_itm.New(key, val); - hash.Add_if_dupe_use_nth(key, itm); - return this; - } - public Xophp_ary Add(int key, Object val) { - nxt_idx = key + 1; - Xophp_ary_itm itm = Xophp_ary_itm.New(key, val); - hash.Add_if_dupe_use_nth(key, itm); - return this; - } - public Xophp_ary Add(double key, Object val) { - int key_as_int = (int)key; - nxt_idx = key_as_int + 1; - Xophp_ary_itm itm = Xophp_ary_itm.New(key_as_int, val); - hash.Add_if_dupe_use_nth(key_as_int, itm); - return this; - } - public Xophp_ary Add(boolean key, Object val) { - int key_as_int = key ? 1 : 0; - nxt_idx = key_as_int + 1; - Xophp_ary_itm itm = Xophp_ary_itm.New(key_as_int, val); - hash.Add_if_dupe_use_nth(key_as_int, itm); - return this; - } - public Xophp_ary Add(String key, Object val) { - Xophp_ary_itm itm = null; - int key_as_int = Int_.Parse_or(key, Int_.Min_value); - if (key_as_int != Int_.Min_value) { - itm = Xophp_ary_itm.New(key_as_int, val); - nxt_idx = key_as_int + 1; - hash.Add_if_dupe_use_nth(key_as_int, itm); - } - else { - itm = Xophp_ary_itm.New(key, val); - hash.Add_if_dupe_use_nth(key, itm); - } - return this; - } - public Object Get(Object key) { - Xophp_ary_itm itm = (Xophp_ary_itm)hash.Get_by(key); - return itm.Val(); - } - public void Unset(Object key) { - hash.Del(key); - } - public boolean Has(Object key) { - return hash.Has(key); - } - public Xophp_ary Values() { - Xophp_ary rv = new Xophp_ary(); - int len = hash.Len(); - for (int i = 0; i < len; i++) { - Xophp_ary_itm old_itm = (Xophp_ary_itm)hash.Get_at(i); - rv.Add(i, old_itm.Val()); - } - return rv; - } - public Xophp_ary_itm[] To_ary() { - return (Xophp_ary_itm[])hash.To_ary(Xophp_ary_itm.class); - } - public void To_bfr(Bry_bfr bfr) { - Xophp_ary_itm[] itms = To_ary(); - for (Xophp_ary_itm itm : itms) { - itm.To_bfr(bfr); - } - } - public static Xophp_ary New() {return new Xophp_ary();} -} diff --git a/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCSingleton.java b/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCSingleton.java index a1f1fc388..152f21b27 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCSingleton.java +++ b/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCSingleton.java @@ -43,7 +43,7 @@ public class JCSingleton { private final Ordered_hash mapCacheLru = Ordered_hash_.New(); public Xomw_page_fetcher Store() {return store;} public void Store_(Xomw_page_fetcher v) {this.store = v;} private Xomw_page_fetcher store; - public Xophp_ary ConfigModels() {return configModels;} private final Xophp_ary configModels = new Xophp_ary(); + public XophpArray ConfigModels() {return configModels;} private final XophpArray configModels = new XophpArray(); // /** // * @var TitleParser cached invariant title parser // */ @@ -423,8 +423,8 @@ public class JCSingleton { String clz = null; if (configModels.Has(modelId)) { Object val = configModels.Get(modelId); - if (Type_.Type_by_obj(val) == Xophp_ary.class) { - Xophp_ary val_as_ary = (Xophp_ary)val; + if (Type_.Type_by_obj(val) == XophpArray.class) { + XophpArray val_as_ary = (XophpArray)val; if (val_as_ary.Has("class")) { Gfo_usr_dlg_.Instance.Warn_many("", "", "JsonConfig: Invalid +$wgJsonConfigModels['modelId'] array " + "value, 'cl"+ "ass' not found"); } else { diff --git a/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCValue.java b/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCValue.java index 897d0a39b..3d0297e74 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCValue.java +++ b/400_xowa/src/gplx/xowa/mediawiki/extensions/JsonConfig/includes/JCValue.java @@ -20,7 +20,7 @@ public class JCValue { private Ordered_hash value = Ordered_hash_.New(); private int statusVal; private XophpStdClass value_as_obj; - private Xophp_ary value_as_ary; + private XophpArray value_as_ary; private Object value_as_prim; private int value_tid; private boolean sameAsDefaultVal = false; @@ -45,7 +45,7 @@ public class JCValue { /** @param int status * @param mixed value */ - public JCValue(int status, XophpStdClass value_as_obj, Xophp_ary value_as_ary, Object value_as_prim) { + public JCValue(int status, XophpStdClass value_as_obj, XophpArray value_as_ary, Object value_as_prim) { this.statusVal = status; this.value_as_obj = value_as_obj; this.value_as_ary = value_as_ary; diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/XomwDefaultSettings.java b/400_xowa/src/gplx/xowa/mediawiki/includes/XomwDefaultSettings.java index 3c21d9718..74ea9ecb9 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/XomwDefaultSettings.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/XomwDefaultSettings.java @@ -2178,12 +2178,12 @@ public class XomwDefaultSettings { // * Allow schema updates // */ // $wgAllowSchemaUpdates = true; -// -// /** -// * Maximum article size in kilobytes -// */ -// $wgMaxArticleSize = 2048; -// + + /** + * Maximum article size in kilobytes + */ + public static int wgMaxArticleSize = 2048; + // /** // * The minimum amount of memory that MediaWiki "needs"; MediaWiki will try to // * raise PHP's memory limit if it's below this amount. diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/content/ContentHandler.java b/400_xowa/src/gplx/xowa/mediawiki/includes/content/ContentHandler.java index 1c9615fe4..3e4cb2676 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/content/ContentHandler.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/content/ContentHandler.java @@ -532,7 +532,7 @@ public abstract class ContentHandler { return true; // this means "use the default" } - return XophpArray.in_array(format, this.mSupportedFormats); + return XophpArrayUtl.in_array(format, this.mSupportedFormats); } /** diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java index 771cd9a60..2a5a8bd61 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParser.java @@ -27,6 +27,7 @@ import gplx.xowa.mediawiki.includes.parsers.quotes.*; import gplx.xowa.mediawiki.includes.parsers.lnkes.*; import gplx.xowa.mediawiki.includes.parsers.magiclinks.*; import gplx.xowa.mediawiki.includes.parsers.nbsps.*; +import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; /** * PHP Parser - Processes wiki markup (which uses a more user-friendly * syntax, such as "[[link]]" for making links), and provides a one-way @@ -163,11 +164,13 @@ public class XomwParser implements XomwParserIface { // public $mSubstWords; // # Initialised in constructor // public $mConf, $mExtLinkBracketedRegex, $mUrlProtocols; -// -// # Initialized in getPreprocessor() -// /** @var Preprocessor */ -// public $mPreprocessor; -// + + // Initialized in getPreprocessor() + /** @var Preprocessor */ + public XomwPreprocessor mPreprocessor; + + private XomwPreprocessor mPreprocessorClass; + // # Cleared with clearState(): // /** // * @var ParserOutput @@ -282,31 +285,33 @@ public class XomwParser implements XomwParserIface { public XomwSanitizer Sanitizer() {return sanitizer;} public XomwStripState Strip_state() {return mStripState;} -// /** -// * @param array $conf -// */ -// public function __construct($conf = []) { + /** + * @param array $conf + */ + public void __construct() { // $conf = [] // this.mConf = $conf; // this.mUrlProtocols = wfUrlProtocols(); // this.mExtLinkBracketedRegex = '/\[(((?i)' . this.mUrlProtocols . ')' . // self::EXT_LINK_ADDR . // self::EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F]*?)\]/Su'; -// if (isset($conf['preprocessorClass'])) { -// this.mPreprocessorClass = $conf['preprocessorClass']; -// } elseif (defined('HPHP_VERSION')) { -// # Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop -// this.mPreprocessorClass = 'Preprocessor_Hash'; -// } elseif (extension_loaded('domxml')) { -// # PECL extension that conflicts with the core DOM extension (T15770) -// wfDebug("Warning: you have the obsolete domxml extension for PHP. Please remove it!\n"); -// this.mPreprocessorClass = 'Preprocessor_Hash'; -// } elseif (extension_loaded('dom')) { -// this.mPreprocessorClass = 'Preprocessor_DOM'; -// } else { -// this.mPreprocessorClass = 'Preprocessor_Hash'; -// } -// wfDebug(__CLASS__ . ": using preprocessor: {this.mPreprocessorClass}\n"); -// } + + this.mPreprocessorClass = XomwPreprocessor_DOM.Instance; + // if (isset($conf['preprocessorClass'])) { + // this.mPreprocessorClass = $conf['preprocessorClass']; + // } elseif (defined('HPHP_VERSION')) { + // # Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop + // this.mPreprocessorClass = 'Preprocessor_Hash'; + // } elseif (extension_loaded('domxml')) { + // # PECL extension that conflicts with the core DOM extension (T15770) + // wfDebug("Warning: you have the obsolete domxml extension for PHP. Please remove it!\n"); + // this.mPreprocessorClass = 'Preprocessor_Hash'; + // } elseif (extension_loaded('dom')) { + // this.mPreprocessorClass = 'Preprocessor_DOM'; + // } else { + // this.mPreprocessorClass = 'Preprocessor_Hash'; + // } + // wfDebug(__CLASS__ . ": using preprocessor: {this.mPreprocessorClass}\n"); + } private final Btrie_slim_mgr protocols_trie; public XomwEnv Env() {return env;} public Xomw_lnki_wkr Lnki_wkr() {return lnkiWkr;} @@ -314,6 +319,7 @@ public class XomwParser implements XomwParserIface { public byte[] Get_external_link_rel; private static byte[] Atr__rel; public XomwParser(XomwEnv env) { + this.__construct(); if (regex_space == null) { synchronized (Type_.Type_by_obj(this)) { regex_space = new Xomw_regex_space(); @@ -972,19 +978,19 @@ public class XomwParser implements XomwParserIface { // } // return this.mOptions->getUser(); // } -// -// /** -// * Get a preprocessor Object -// * -// * @return Preprocessor -// */ -// public function getPreprocessor() { -// if (!isset(this.mPreprocessor)) { -// $class = this.mPreprocessorClass; -// this.mPreprocessor = new $class($this); -// } -// return this.mPreprocessor; -// } + + /** + * Get a preprocessor Object + * + * @return Preprocessor + */ + public XomwPreprocessor getPreprocessor() { + if (this.mPreprocessor == null) { + XomwPreprocessor factory = this.mPreprocessorClass; + this.mPreprocessor = factory.Make_new(this); + } + return this.mPreprocessor; + } /** * Get a LinkRenderer instance to make links with @@ -2124,34 +2130,34 @@ public class XomwParser implements XomwParserIface { // this.mVariables = new MagicWordArray($variableIDs); // this.mSubstWords = new MagicWordArray($substIDs); // } -// -// /** -// * Preprocess some wikitext and return the document tree. -// * This is the ghost of replace_variables(). -// * -// * @param String $text The text to parse -// * @param int $flags Bitwise combination of: -// * - self::PTD_FOR_INCLUSION: Handle "" and "" as if the text is being -// * included. Default is to assume a direct page view. -// * -// * The generated DOM tree must depend only on the input text and the flags. -// * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of T6899. -// * -// * Any flag added to the $flags parameter here, or any other parameter liable to cause a -// * change in the DOM tree for a given text, must be passed through the section identifier -// * in the section edit link and thus back to extractSections(). -// * -// * The output of this function is currently only cached in process memory, but a persistent -// * cache may be implemented at a later date which takes further advantage of these strict -// * dependency requirements. -// * -// * @return PPNode -// */ -// public function preprocessToDom($text, $flags = 0) { -// $dom = this.getPreprocessor()->preprocessToObj($text, $flags); -// return $dom; -// } -// + + /** + * Preprocess some wikitext and return the document tree. + * This is the ghost of replace_variables(). + * + * @param String $text The text to parse + * @param int $flags Bitwise combination of: + * - self::PTD_FOR_INCLUSION: Handle "" and "" as if the text is being + * included. Default is to assume a direct page view. + * + * The generated DOM tree must depend only on the input text and the flags. + * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of T6899. + * + * Any flag added to the $flags parameter here, or any other parameter liable to cause a + * change in the DOM tree for a given text, must be passed through the section identifier + * in the section edit link and thus back to extractSections(). + * + * The output of this function is currently only cached in process memory, but a persistent + * cache may be implemented at a later date which takes further advantage of these strict + * dependency requirements. + * + * @return PPNode + */ + public XomwPPNode preprocessToDom(String text, int flags) { + XomwPPNode dom = this.getPreprocessor().preprocessToObj(text, flags); + return dom; + } + // /** // * Return a three-element array: leading whitespace, String contents, trailing whitespace // * @@ -2171,49 +2177,48 @@ public class XomwParser implements XomwParserIface { // } // return [ $w1, $trimmed, $w2 ]; // } -// -// /** -// * Replace magic variables, templates, and template arguments -// * with the appropriate text. Templates are substituted recursively, -// * taking care to avoid infinite loops. -// * -// * Note that the substitution depends on value of $mOutputType: -// * self::OT_WIKI: only {{subst:}} templates -// * self::OT_PREPROCESS: templates but not extension tags -// * self::OT_HTML: all templates and extension tags -// * -// * @param String $text The text to transform -// * @param boolean|PPFrame $frame Object describing the arguments passed to the -// * template. Arguments may also be provided as an associative array, as -// * was the usual case before MW1.12. Providing arguments this way may be -// * useful for extensions wishing to perform variable replacement -// * explicitly. -// * @param boolean $argsOnly Only do argument (triple-brace) expansion, not -// * double-brace expansion. -// * @return String -// */ -// public function replaceVariables($text, $frame = false, $argsOnly = false) { -// # Is there any text? Also, Prevent too big inclusions! -// $textSize = strlen($text); -// if ($textSize < 1 || $textSize > this.mOptions->getMaxIncludeSize()) { -// return $text; -// } -// -// if ($frame === false) { -// $frame = this.getPreprocessor()->newFrame(); -// } elseif (!($frame instanceof PPFrame)) { -// wfDebug(__METHOD__ . " called using plain parameters instead of " -// . "a PPFrame instance. Creating custom frame.\n"); -// $frame = this.getPreprocessor()->newCustomFrame($frame); -// } -// -// $dom = this.preprocessToDom($text); -// $flags = $argsOnly ? PPFrame::NO_TEMPLATES : 0; -// $text = $frame->expand($dom, $flags); -// -// return $text; -// } -// + + /** + * Replace magic variables, templates, and template arguments + * with the appropriate text. Templates are substituted recursively, + * taking care to avoid infinite loops. + * + * Note that the substitution depends on value of $mOutputType: + * self::OT_WIKI: only {{subst:}} templates + * self::OT_PREPROCESS: templates but not extension tags + * self::OT_HTML: all templates and extension tags + * + * @param String $text The text to transform + * @param boolean|PPFrame $frame Object describing the arguments passed to the + * template. Arguments may also be provided as an associative array, as + * was the usual case before MW1.12. Providing arguments this way may be + * useful for extensions wishing to perform variable replacement + * explicitly. + * @param boolean $argsOnly Only do argument (triple-brace) expansion, not + * double-brace expansion. + * @return String + */ + public String replaceVariables(String text, XomwParserCtx pctx, XomwPPFrame frame, boolean argsOnly) { + // Is there any text? Also, Prevent too big inclusions! + int textSize = String_.Len(text); + if (textSize < 1 || textSize > this.mOptions.getMaxIncludeSize()) { + return text; + } + + if (frame == null) { + frame = this.getPreprocessor().newFrame(); + } else if (!(Type_.Is_assignable_from_by_obj(frame, XomwPPFrame.class))) { + // wfDebug(__METHOD__ . " called using plain parameters instead of " + // . "a PPFrame instance. Creating custom frame.\n"); + frame = this.getPreprocessor().newCustomFrame(frame); + } + + XomwPPNode dom = this.preprocessToDom(text, 0); + int flags = argsOnly ? XomwPPFrame.NO_TEMPLATES : 0; + text = frame.expand(dom, flags); + return text; + } + // /** // * Clean up argument array - refactored in 1.9 so parserfunctions can use it, too. // * diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java index f0c827d2c..da3148488 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwParserOptions.java @@ -17,6 +17,7 @@ package gplx.xowa.mediawiki.includes.parsers; import gplx.*; import gplx.xowa.*; public class XomwParserOptions { public XomwParserOptions() { this.mThumbSize = 220; + initialiseFromUser(); } // /** // * Interlanguage links are removed and returned in an array @@ -68,11 +69,11 @@ public class XomwParserOptions { // */ // private $mTargetLanguage = null; // -// /** -// * Maximum size of template expansions, in bytes -// */ -// private $mMaxIncludeSize; -// + /** + * Maximum size of template expansions, in bytes + */ + private int mMaxIncludeSize; + // /** // * Maximum number of nodes touched by PPFrame::expand() // */ @@ -271,10 +272,10 @@ public class XomwParserOptions { // return this.mTargetLanguage; // } // -// public function getMaxIncludeSize() { -// return this.mMaxIncludeSize; -// } -// + public int getMaxIncludeSize() { + return this.mMaxIncludeSize; + } + // public function getMaxPPNodeCount() { // return this.mMaxPPNodeCount; // } @@ -679,28 +680,29 @@ public class XomwParserOptions { // public static function newFromContext( IContextSource $context ) { // return new ParserOptions( $context->getUser(), $context->getLanguage() ); // } -// -// /** -// * Get user options -// * -// * @param User $user -// * @param Language $lang -// */ -// private function initialiseFromUser( $user, $lang ) { + + /** + * Get user options + * + * @param User $user + * @param Language $lang + */ + // private function initialiseFromUser( $user, $lang ) { + private void initialiseFromUser() { // global $wgInterwikiMagic, $wgAllowExternalImages, // $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion, // $wgMaxArticleSize, $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth, // $wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit, // $wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion, // $wgEnableMagicLinks; -// -// // *UPDATE* ParserOptions::matches() if any of this changes as needed + + // *UPDATE* ParserOptions::matches() if any of this changes as needed // this.mInterwikiMagic = $wgInterwikiMagic; // this.mAllowExternalImages = $wgAllowExternalImages; // this.mAllowExternalImagesFrom = $wgAllowExternalImagesFrom; // this.mEnableImageWhitelist = $wgEnableImageWhitelist; // this.mAllowSpecialInclusion = $wgAllowSpecialInclusion; -// this.mMaxIncludeSize = $wgMaxArticleSize * 1024; + this.mMaxIncludeSize = XomwDefaultSettings.wgMaxArticleSize * 1024; // this.mMaxPPNodeCount = $wgMaxPPNodeCount; // this.mMaxGeneratedPPNodeCount = $wgMaxGeneratedPPNodeCount; // this.mMaxPPExpandDepth = $wgMaxPPExpandDepth; @@ -719,7 +721,7 @@ public class XomwParserOptions { // this.mThumbSize = $user->getOption( 'thumbsize' ); // this.mStubThreshold = $user->getStubThreshold(); // this.mUserLang = $lang; -// } + } // // /** // * Check if these options match that of another options set diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java similarity index 69% rename from 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr.java rename to 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java index 1fb751cc5..2f3a9e944 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor.java @@ -13,18 +13,155 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.mediawiki.includes.parsers.prepros; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +package gplx.xowa.mediawiki.includes.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.core.btries.*; -public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls - private final Bry_bfr tmp_bfr = Bry_bfr_.New(); +import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; +/** +* @ingroup Parser +*/ +public abstract class XomwPreprocessor { + +// private static final int CACHE_VERSION = 1; + +// /** +// * @var array Brace matching rules. +// */ +// protected $rules = [ +// '{' => [ +// 'end' => '}', +// 'names' => [ +// 2 => 'template', +// 3 => 'tplarg', +// ], +// 'min' => 2, +// 'max' => 3, +// ], +// '[' => [ +// 'end' => ']', +// 'names' => [ 2 => null ], +// 'min' => 2, +// 'max' => 2, +// ], +// '-{' => [ +// 'end' => '}-', +// 'names' => [ 1 => null ], +// 'min' => 1, +// 'max' => 1, +// ], +// ]; +// +// /** +// * Store a document tree in the cache. +// * +// * @param String $text +// * @param int $flags +// */ +// protected function cacheSetTree($text, $flags, $tree) { +// $config = RequestContext::getMain()->getConfig(); +// +// $length = strlen($text); +// $threshold = $config->get('PreprocessorCacheThreshold'); +// if ($threshold === false || $length < $threshold || $length > 1e6) { +// return false; +// } +// +// $key = wfMemcKey( +// defined('static::CACHE_PREFIX') ? static::CACHE_PREFIX : static::class, +// md5($text), $flags); +// $value = sprintf("%08d", static::CACHE_VERSION) . $tree; +// +// $cache = ObjectCache::getInstance($config->get('MainCacheType')); +// $cache->set($key, $value, 86400); +// +// LoggerFactory::getInstance('Preprocessor') +// ->info("Cached preprocessor output (key: $key)"); +// } +// +// /** +// * Attempt to load a precomputed document tree for some given wikitext +// * from the cache. +// * +// * @param String $text +// * @param int $flags +// * @return PPNode_Hash_Tree|boolean +// */ +// protected function cacheGetTree($text, $flags) { +// $config = RequestContext::getMain()->getConfig(); +// +// $length = strlen($text); +// $threshold = $config->get('PreprocessorCacheThreshold'); +// if ($threshold === false || $length < $threshold || $length > 1e6) { +// return false; +// } +// +// $cache = ObjectCache::getInstance($config->get('MainCacheType')); +// +// $key = wfMemcKey( +// defined('static::CACHE_PREFIX') ? static::CACHE_PREFIX : static::class, +// md5($text), $flags); +// +// $value = $cache->get($key); +// if (!$value) { +// return false; +// } +// +// $version = intval(substr($value, 0, 8)); +// if ($version !== static::CACHE_VERSION) { +// return false; +// } +// +// LoggerFactory::getInstance('Preprocessor') +// ->info("Loaded preprocessor output from cache (key: $key)"); +// +// return substr($value, 8); +// } + + /** + * Create a new top-level frame for expansion of a page + * + * @return PPFrame + */ + public abstract XomwPPFrame newFrame(); + + /** + * Create a new custom frame for programmatic use of parameter replacement + * as used in some extensions. + * + * @param array $args + * + * @return PPFrame + */ + public abstract XomwPPFrame newCustomFrame(XomwPPFrame args); + +// /** +// * Create a new custom node for programmatic use of parameter replacement +// * as used in some extensions. +// * +// * @param array $values +// */ +// abstract public function newPartNodeArray($values); + + /** + * Preprocess text to a PPNode + * + * @param String $text + * @param int $flags + * + * @return PPNode + */ + public abstract XomwPPNode preprocessToObj(String text, int flags); + private final List_adp comments_list = List_adp_.New(); private final Btrie_slim_mgr elements_trie__y = Btrie_slim_mgr.ci_a7(), elements_trie__n = Btrie_slim_mgr.ci_a7(); private final Hash_adp_bry xmlish_allow_missing_end_tag = Hash_adp_bry.cs().Add_many_str("includeonly", "noinclude", "onlyinclude"); private final Hash_adp_bry no_more_closing_tag = Hash_adp_bry.cs(); - private final Xomw_prepro_stack stack = new Xomw_prepro_stack(); + private final XomwPPDStack stack; private final Btrie_rv trv = new Btrie_rv(); - private Bry_bfr accum = Bry_bfr_.New(); + private Xomw_prepro_accum accum = null; + public XomwPreprocessor() { + this.stack = new XomwPPDStack(this.Factory__accum()); + } public void Init_by_wiki(String... xmlish_elems_ary) { Elements_trie__init_by_wiki(elements_trie__y, ignored_tags_y, xmlish_elems_ary, "noinclude"); Elements_trie__init_by_wiki(elements_trie__n, ignored_tags_n, xmlish_elems_ary, "includeonly"); @@ -50,7 +187,13 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls private static void Elements_trie__add(Btrie_slim_mgr trie, boolean type_is_comment, String hook, String name) { trie.Add_obj(hook, new Xomw_prepro_elem(type_is_comment ? Xomw_prepro_elem.Type__comment : Xomw_prepro_elem.Type__other, Bry_.new_a7(name))); } - public byte[] Preprocess_to_xml(byte[] src, boolean for_inclusion) { + + /** + * @param String $text + * @param int $flags + * @return String + */ + public byte[] preprocessToXml(byte[] src, boolean for_inclusion) { // RELIC.PROC_VAR: forInclusion = $flags & Parser::PTD_FOR_INCLUSION; // RELIC.INIT_BY_WIKI: $xmlishElements = parser->getStripList(); // RELIC.CLASS_VAR: $xmlishAllowMissingEndTag = [ 'includeonly', 'noinclude', 'onlyinclude' ]; @@ -97,18 +240,18 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls int i = 0; // Current accumulator - accum = stack.Get_accum(); - accum.Add_str_a7(""); + accum = this.Accum__set(stack.Get_accum()); + this.preprocessToObj_root(); // True to find equals signs in arguments - boolean find_equals = false; + boolean findEquals = false; // True to take notice of pipe characters - boolean find_pipe = false; + boolean findPipe = false; int heading_index = 1; // True if $i is inside a possible heading - boolean in_heading = false; + boolean inHeading = false; // True if there are no more greater-than (>) signs right of $i boolean no_more_gt = false; @@ -136,11 +279,11 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls int start_pos = Bry_find_.Find_fwd(src, Bry__only_include_bgn, i, src_len); if (start_pos == Bry_find_.Not_found) { // Ignored section runs to the end - accum.Add_str_a7("").Add_bry_escape_html(src, i, src_len).Add_str_a7(""); + this.preprocessToObj_ignore(src, i, src_len); break; } int tag_end_pos = start_pos + Bry__only_include_bgn.length; // past-the-end - accum.Add_str_a7("").Add_bry_escape_html(src, i, tag_end_pos).Add_str_a7(""); + this.preprocessToObj_ignore(src, i, tag_end_pos); i = tag_end_pos; find_only_include = false; } @@ -159,10 +302,10 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls cur_closing = stack.top.close; // RELIC.REGEX: $search .= $currentClosing; } - if (find_pipe) { + if (findPipe) { // RELIC.REGEX: $search .= '|'; } - if (find_equals) { + if (findEquals) { // First equals will be for the template // RELIC.REGEX: $search .= '='; } @@ -181,11 +324,11 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls case Byte_ascii.Nl: loop_stop = true; break; - case Byte_ascii.Pipe: // handle "find_pipe" - if (find_pipe) loop_stop = true; + case Byte_ascii.Pipe: // handle "findPipe" + if (findPipe) loop_stop = true; break; - case Byte_ascii.Eq: // handle "find_equals" - if (find_equals) loop_stop = true; + case Byte_ascii.Eq: // handle "findEquals" + if (findEquals) loop_stop = true; break; default: // handle "cur_closing"; specified by piece.close and rule.close, so "\n", "}", "]" and "}-" if (cur_closing != Bry_.Empty) { @@ -209,7 +352,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls literal_len++; } if (literal_len > 0) { - accum.Add_bry_escape_html(src, i, i + literal_len); + this.preprocessToObj_literal(src, i, i + literal_len); i += literal_len; } if (i >= src_len) { @@ -232,7 +375,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls case Byte_ascii.Pipe: found = Found__pipe; break; case Byte_ascii.Eq: found = Found__equals; break; case Byte_ascii.Angle_bgn: found = Found__angle; break; - case Byte_ascii.Nl: found = in_heading ? Found__line_end : Found__line_bgn; break; + case Byte_ascii.Nl: found = inHeading ? Found__line_end : Found__line_bgn; break; // PORTED: "elseif ( $curChar == $currentClosing )" case Byte_ascii.Curly_end: found = Found__close; break; @@ -265,7 +408,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls Xomw_prepro_elem element = (Xomw_prepro_elem)elements_trie.Match_at(trv, src, i + 1, src_len); if (element == null) { // Element name missing or not listed - accum.Add(Bry__escaped_lt); + this.preprocessToObj_literal(Byte_ascii.Lt_bry); i++; continue; } @@ -281,7 +424,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls int end_pos = Bry_find_.Find_fwd(src, Bry__comment_end, i + 4, src_len); if (end_pos == Bry_find_.Not_found) { // Unclosed comment in input, runs to end - accum.Add_str_a7("").Add_bry_escape_html(src, i, src_len).Add_str_a7(""); + this.preprocessToObj_comment(src, i, src_len); i = src_len; } else { @@ -318,11 +461,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // Remove leading whitespace from the end of the accumulator // Sanity check first though int ws_len = i - ws_bgn; - int accum_len = accum.Len(); - if ( ws_len > 0 - && XophpString.strspn_fwd__space_or_tab(accum.Bfr(), accum_len - ws_len, -1, accum_len) == ws_len) { - accum.Del_by(ws_len); - } + this.preprocessToObj_removeLeadingWhitespaceFromEnd(ws_len); // Dump all but the last comment to the accumulator int comments_list_len = comments_list.Len(); @@ -334,7 +473,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls break; } inner = Bry_.Mid(src, bgn_pos, end_pos); - accum.Add_str_a7("").Add_bry_escape_html(inner).Add_str_a7(""); + this.preprocessToObj_comment(inner); } // Do a line-start run next time to look for headings after the comment @@ -347,16 +486,16 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls } if (stack.top != null) { - Xomw_prepro_part part = stack.top.Get_current_part(); - if (!(part.comment_end != -1 && part.comment_end == ws_bgn - 1)) { - part.visual_end = ws_bgn; + XomwPPDPart part = stack.top.Get_current_part(); + if (!(part.commentEnd != -1 && part.commentEnd == ws_bgn - 1)) { + part.visualEnd = ws_bgn; } // Else comments abutting, no change in visual end - part.comment_end = end_pos; + part.commentEnd = end_pos; } i = end_pos + 1; inner = Bry_.Mid(src, bgn_pos, end_pos + 1); - accum.Add_str_a7("").Add_bry_escape_html(inner).Add_str_a7(""); + this.preprocessToObj_comment(inner); } continue; } @@ -371,26 +510,26 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // Infinite backtrack // Disable tag search to prevent worst-case O(N^2) performance no_more_gt = true; - accum.Add(Bry__escaped_lt); + this.preprocessToObj_literal(Byte_ascii.Lt_bry); i++; continue; } // Handle ignored tags if (ignored_tags.Has(name)) { - accum.Add_str_a7("").Add_bry_escape_html(src, i, tag_end_pos + 1).Add_str_a7(""); + this.preprocessToObj_ignore(src, i, tag_end_pos + 1); i = tag_end_pos + 1; continue; } int tag_bgn_pos = i; int atr_end = -1; - byte[] close = null; + byte[] close = this.preprocessToObj_close_init(); if (src[tag_end_pos - 1] == Byte_ascii.Slash) { atr_end = tag_end_pos - 1; inner = null; i = tag_end_pos + 1; - close = Bry_.Empty; + close = this.preprocessToObj_close_init(); } else { atr_end = tag_end_pos; @@ -429,8 +568,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls && elem_end_found) { inner = Bry_.Mid(src, tag_end_pos + 1, elem_end_lhs); i = elem_end_rhs; - tmp_bfr.Add_str_a7("").Add_bry_escape_html(src, elem_end_lhs, elem_end_rhs).Add_str_a7(""); - close = tmp_bfr.To_bry_and_clear(); + close = this.preprocessToObj_close_make(src, elem_end_lhs, elem_end_rhs); } else { // No end tag @@ -443,7 +581,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls else { // Don't match the tag, treat opening tag as literal and resume parsing. i = tag_end_pos + 1; - accum.Add_bry_escape_html(src, tag_bgn_pos, tag_end_pos + 1); + this.preprocessToObj_literal(src, tag_bgn_pos, tag_end_pos + 1); // Cache results, otherwise we have O(N^2) performance for input like ... no_more_closing_tag.Add_if_dupe_use_nth(name, name); continue; @@ -453,28 +591,11 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // and just become tags if (ignored_elements.Has(name)) { - accum.Add_str_a7("").Add_bry_escape_html(src, tag_bgn_pos, i).Add_str_a7(""); + this.preprocessToObj_ignore(src, tag_bgn_pos, i); continue; } - accum.Add_str_a7(""); - // PORTED: - // if ( $attrEnd <= $attrStart ) { - // $attr = ''; - // } else { - // $attr = substr( $text, $attrStart, $attrEnd - $attrStart ); - // } - accum.Add_str_a7("").Add(name).Add_str_a7(""); - // Note that the attr element contains the whitespace between name and attribute, - // this is necessary for precise reconstruction during pre-save transform. - accum.Add_str_a7(""); - if (atr_end > atr_bgn) - accum.Add_bry_escape_html(src, atr_bgn, atr_end); - accum.Add_str_a7(""); - if (inner != null) { - accum.Add_str_a7("").Add_bry_escape_html(inner).Add_str_a7(""); - } - accum.Add(close).Add_str_a7(""); + this.preprocessToObj_ext(src, name, atr_bgn, atr_end, inner, close); } else if (found == Found__line_bgn) { // Is this the start of a heading? @@ -482,12 +603,12 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls if (fake_line_start) { fake_line_start = false; } else { - accum.Add(cur_char); + this.preprocessToObj_literal(cur_char); i++; } int count = XophpString.strspn_fwd__byte(src, Byte_ascii.Eq, i, 6, src_len); - if (count == 1 && find_equals) { // EX: "{{a|\n=b=\n" + if (count == 1 && findEquals) { // EX: "{{a|\n=b=\n" // DWIM: This looks kind of like a name/value separator. // Let's let the equals handler have it and break the // potential heading. This is heuristic, but AFAICT the @@ -495,14 +616,14 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // complex. } else if (count > 0) { - Xomw_prepro_piece piece = new Xomw_prepro_piece(Byte_ascii.Nl_bry, Byte_ascii.Nl_bry, count, i, false); + Xomw_prepro_piece piece = new Xomw_prepro_piece(Factory__part(), Byte_ascii.Nl_bry, Byte_ascii.Nl_bry, count, i, false); piece.Add_part(Bry_.Repeat(Byte_ascii.Eq, count)); stack.Push(piece); - accum = stack.Get_accum(); + accum = this.Accum__set(stack.Get_accum()); Xomw_prepro_flags flags = stack.Get_flags(); - find_pipe = flags.Find_pipe; - find_equals = flags.Find_eq; - in_heading = flags.In_heading; + findPipe = flags.findPipe; + findEquals = flags.findEquals; + inHeading = flags.inHeading; i += count; } } @@ -510,7 +631,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls Xomw_prepro_piece piece = stack.top; // A heading must be open, otherwise \n wouldn't have been in the search list if (!Bry_.Eq(piece.open, Byte_ascii.Nl_bry)) throw Err_.new_wo_type("assertion:piece must start with \\n"); - Xomw_prepro_part part = piece.Get_current_part(); + XomwPPDPart part = piece.Get_current_part(); // Search back through the input to see if it has a proper close. // Do this using the reversed String since the other solutions @@ -518,17 +639,17 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls int ws_len = XophpString.strspn_bwd__space_or_tab(src, src_len - i, -1); int search_bgn = i - ws_len; - if (part.comment_end != -1 && search_bgn -1 == part.comment_end) { + if (part.commentEnd != -1 && search_bgn -1 == part.commentEnd) { // Comment found at line end // Search for equals signs before the comment - search_bgn = part.visual_end; + search_bgn = part.visualEnd; search_bgn = Bry_find_.Find_bwd__while_space_or_tab(src, search_bgn, 0); search_bgn -= XophpString.strspn_bwd__space_or_tab(src, search_bgn, -1); } int count = piece.count; int eq_len = XophpString.strspn_bwd__byte(src, Byte_ascii.Eq, search_bgn, -1); - byte[] element = Bry_.Empty; + Xomw_prepro_accum element = null; if (eq_len > 0) { if (search_bgn - eq_len == piece.start_pos) { // This is just a single String of equals signs on its own line @@ -548,29 +669,29 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls } if (count > 0) { // Normal match, output - element = tmp_bfr.Add_str_a7("").Add_bfr_and_preserve(accum).Add_str_a7("").To_bry_and_clear(); + element = this.preprocessToObj_heading_init(count, heading_index); heading_index++; } else { // Single equals sign on its own line, count=0 - element = accum.To_bry(); + element = accum; } } else { // No match, no , just pass down the inner src - element = accum.To_bry(); + element = accum; } // Unwind the stack stack.Pop(); - accum = stack.Get_accum(); + this.accum = this.Accum__set(stack.Get_accum()); Xomw_prepro_flags flags = stack.Get_flags(); - find_pipe = flags.Find_pipe; - find_equals = flags.Find_eq; - in_heading = flags.In_heading; + findPipe = flags.findPipe; + findEquals = flags.findEquals; + inHeading = flags.inHeading; // Append the result to the enclosing accumulator - accum.Add(element); + this.preprocessToObj_heading_end(element); // Note that we do NOT increment the input pointer. // This is because the closing linebreak could be the opening linebreak of // another heading. Infinite loops are avoided because the next iteration MUST @@ -584,19 +705,19 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // we need to add to stack only if opening brace count is enough for one of the rules if (count >= rule.min) { // Add it to the stack - Xomw_prepro_piece piece = new Xomw_prepro_piece(cur_char, rule.end, count, -1, i > 0 && src[i - 1] == Byte_ascii.Nl); + Xomw_prepro_piece piece = new Xomw_prepro_piece(Factory__part(), cur_char, rule.end, count, -1, i > 0 && src[i - 1] == Byte_ascii.Nl); stack.Push(piece); - accum = stack.Get_accum(); + this.accum = this.Accum__set(stack.Get_accum()); Xomw_prepro_flags flags = stack.Get_flags(); - find_pipe = flags.Find_pipe; - find_equals = flags.Find_eq; - in_heading = flags.In_heading; + findPipe = flags.findPipe; + findEquals = flags.findEquals; + inHeading = flags.inHeading; } else { // Add literal brace(s) for (int j = 0; j < count; j++) - accum.Add_bry_escape_html(cur_char); + this.preprocessToObj_literal(cur_char); } i += count; } @@ -628,55 +749,20 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // No matching element found in callback array // Output a literal closing brace and continue for (int j = 0; j < count; j++) - accum.Add_bry_escape_html(cur_char); + this.preprocessToObj_literal(cur_char); i += count; continue; } + int name_type = rule.names[matching_count]; - byte[] element = null; + Xomw_prepro_accum element = null; if (name_type == Xomw_prepro_rule.Name__null) { // No element, just literal text - tmp_bfr.Add(piece.Break_syntax(tmp_bfr, matching_count)); - element = tmp_bfr.Add(Bry_.Repeat_bry(rule.end, matching_count)).To_bry_and_clear(); + element = this.preprocessToObj_text(element, piece, rule.end, matching_count); } else { // Create XML element - // Note: $parts is already XML, does not need to be encoded further - List_adp parts = piece.parts; - byte[] title = ((Xomw_prepro_part)parts.Get_at(0)).bfr.To_bry_and_clear(); - parts.Del_at(0); - - // The invocation is at the start of the line if lineStart is set in - // the stack, and all opening brackets are used up. - byte[] attr = null; - if (max_count == matching_count && piece.line_start) { // RELIC:!empty( $piece->lineStart ) - attr = Bry_.new_a7(" lineStart=\"1\""); - } - else { - attr = Bry_.Empty; - } - - byte[] name_bry = Xomw_prepro_rule.Name(name_type); - tmp_bfr.Add_str_a7("<").Add(name_bry).Add(attr).Add_str_a7(">"); - tmp_bfr.Add_str_a7("").Add(title).Add_str_a7(""); - - int arg_idx = 1; - int parts_len = parts.Len(); - for (int j = 0; j < parts_len; j++) { - Xomw_prepro_part part = (Xomw_prepro_part)parts.Get_at(j); - if (part.Eqpos != -1) { - Bry_bfr part_bfr = part.bfr; - byte[] part_bfr_bry = part_bfr.Bfr(); - tmp_bfr.Add_str_a7("").Add_mid(part_bfr_bry, 0, part.Eqpos); - tmp_bfr.Add_str_a7("=").Add_mid(part_bfr_bry, part.Eqpos + 1, part_bfr.Len()); - tmp_bfr.Add_str_a7(""); - } - else { - tmp_bfr.Add_str_a7("").Add(part.bfr.To_bry()).Add_str_a7(""); - arg_idx++; - } - } - element = tmp_bfr.Add_str_a7("").To_bry_and_clear(); + element = this.preprocessToObj_xml(piece, Xomw_prepro_rule.Name(name_type), max_count, matching_count); } // Advance input pointer @@ -684,7 +770,7 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls // Unwind the stack stack.Pop(); - accum = stack.Get_accum(); + this.accum = this.Accum__set(stack.Get_accum()); // Re-add the old stack element if it still has unmatched opening characters remaining if (matching_count < piece.count) { @@ -695,45 +781,38 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls int min = Get_rule(piece.open).min; if (piece.count >= min) { stack.Push(piece); - accum = stack.Get_accum(); + this.accum = this.Accum__set(stack.Get_accum()); } else { - accum.Add(Bry_.Repeat_bry(piece.open, piece.count)); + this.preprocessToObj_literal(Bry_.Repeat_bry(piece.open, piece.count)); } } Xomw_prepro_flags flags = stack.Get_flags(); - find_pipe = flags.Find_pipe; - find_equals = flags.Find_eq; - in_heading = flags.In_heading; + findPipe = flags.findPipe; + findEquals = flags.findEquals; + inHeading = flags.inHeading; // Add XML element to the enclosing accumulator - accum.Add(element); + this.preprocessToObj_add_element(element); } else if (found == Found__pipe) { - find_equals = true; // shortcut for getFlags() + findEquals = true; // shortcut for getFlags() stack.Add_part(Bry_.Empty); - accum = stack.Get_accum(); + this.accum = this.Accum__set(stack.Get_accum()); i++; } else if (found == Found__equals) { - find_equals = false; // shortcut for getFlags() - stack.Get_current_part().Eqpos = accum.Len(); - accum.Add_byte(Byte_ascii.Eq); + findEquals = false; // shortcut for getFlags() + this.preprocessToObj_equals(stack); i++; } } // Output any remaining unclosed brackets - Bry_bfr root_accum = stack.Get_root_accum(); - int stack_len = stack.stack.Len(); - for (int j = 0; j < stack_len; j++) { - Xomw_prepro_piece piece = (Xomw_prepro_piece)stack.stack.Get_at(j); - root_accum.Add(piece.Break_syntax(tmp_bfr, -1)); - } - root_accum.Add_str_a7(""); - return root_accum.To_bry_and_clear(); + return (byte[])this.preprocessToObj_term(stack); } + private Xomw_prepro_rule Get_rule(byte[] bry) { if (Bry_.Eq(bry, rule_curly.bgn)) return rule_curly; else if (Bry_.Eq(bry, rule_brack.bgn)) return rule_brack; @@ -759,7 +838,6 @@ public class Xomw_prepro_wkr { // THREAD.UNSAFE: caching for repeated calls , Bry__only_include_end = Bry_.new_a7("") , Bry__comment_bgn = Bry_.new_a7("") - , Bry__escaped_lt = Bry_.new_a7("<") , Bry__end_lhs = Bry_.new_a7(""); + } + @Override protected void preprocessToObj_ignore(byte[] src, int bgn, int end) { + accum_dom.Add_str_literal("").Add_str_escaped(src, bgn, end).Add_str_literal(""); + } + @Override protected void preprocessToObj_comment(byte[] src, int bgn, int end) { + accum_dom.Add_str_literal("").Add_str_escaped(src, bgn, end).Add_str_literal(""); + } + @Override protected void preprocessToObj_literal(byte[] src, int bgn, int end) { + accum_dom.Add_str_escaped(src, bgn, end); + } + @Override protected void preprocessToObj_removeLeadingWhitespaceFromEnd(int ws_len) { + int accum_dom_len = accum_dom.Len(); + if ( ws_len > 0 + && XophpString.strspn_fwd__space_or_tab(accum_dom.Bfr_bry(), accum_dom_len - ws_len, -1, accum_dom_len) == ws_len) { + accum_dom.Del_at_end(ws_len); + } + } + @Override protected byte[] preprocessToObj_close_init() {return Bry_.Empty;} + @Override protected byte[] preprocessToObj_close_make(byte[] src, int bgn, int end) { + return tmp_bfr.Add_str_a7("").Add_bry_escape_html(src, bgn, end).Add_str_a7("").To_bry_and_clear(); + } + @Override protected void preprocessToObj_ext(byte[] src, byte[] name, int atr_bgn, int atr_end, byte[] inner, byte[] close) { + accum_dom.Add_str_literal(""); + // PORTED: + // if ( $attrEnd <= $attrStart ) { + // $attr = ''; + // } else { + // $attr = substr( $text, $attrStart, $attrEnd - $attrStart ); + // } + accum_dom.Add_str_literal("").Add_bry(name).Add_str_literal(""); + // Note that the attr element contains the whitespace between name and attribute, + // this is necessary for precise reconstruction during pre-save transform. + accum_dom.Add_str_literal(""); + if (atr_end > atr_bgn) + accum_dom.Add_str_escaped(src, atr_bgn, atr_end); + accum_dom.Add_str_literal(""); + if (inner != null) { + accum_dom.Add_str_literal("").Add_str_escaped(inner, 0, inner.length).Add_str_literal(""); + } + accum_dom.Add_bry(close).Add_str_literal(""); + } + @Override protected Xomw_prepro_accum preprocessToObj_heading_init(int count, int heading_index) { + byte[] rv = tmp_bfr.Add_str_a7("").Add_str_u8(accum_dom.To_str()).Add_str_a7("").To_bry_and_clear(); + return new Xomw_prepro_accum__dom(String_.new_u8(rv)); + } + @Override protected void preprocessToObj_heading_end(Xomw_prepro_accum element) { + accum_dom.Add_bry(((Xomw_prepro_accum__dom)element).To_bry()); + } + @Override protected Xomw_prepro_accum preprocessToObj_text(Xomw_prepro_accum element_obj, Xomw_prepro_piece piece, byte[] rule_end, int matching_count) { + Xomw_prepro_accum__dom element = (Xomw_prepro_accum__dom)element_obj; + tmp_bfr.Add(piece.Break_syntax(tmp_bfr, matching_count)); + if (element != null) + tmp_bfr.Add(element.To_bry()); + tmp_bfr.Add(Bry_.Repeat_bry(rule_end, matching_count)); + byte[] rv = tmp_bfr.To_bry_and_clear(); + return new Xomw_prepro_accum__dom(String_.new_u8(rv)); + } + @Override protected Xomw_prepro_accum preprocessToObj_xml(Xomw_prepro_piece piece, byte[] name_bry, int max_count, int matching_count) { + // Note: $parts is already XML, does not need to be encoded further + List_adp parts = piece.parts; + byte[] title = ((XomwPPDPart_DOM)parts.Get_at(0)).To_bry(); + parts.Del_at(0); + + // The invocation is at the start of the line if lineStart is set in + // the stack, and all opening brackets are used up. + byte[] attr = null; + if (max_count == matching_count && piece.line_start) { // RELIC:!empty( $piece->lineStart ) + attr = Bry_.new_a7(" lineStart=\"1\""); + } + else { + attr = Bry_.Empty; + } + + tmp_bfr.Add_str_a7("<").Add(name_bry).Add(attr).Add_str_a7(">"); + tmp_bfr.Add_str_a7("").Add(title).Add_str_a7(""); + + int arg_idx = 1; + int parts_len = parts.Len(); + for (int j = 0; j < parts_len; j++) { + XomwPPDPart_DOM part = (XomwPPDPart_DOM)parts.Get_at(j); + if (part.eqpos != -1) { + byte[] part_bfr_bry = part.To_bry(); + tmp_bfr.Add_str_a7("").Add_mid(part_bfr_bry, 0, part.eqpos); + tmp_bfr.Add_str_a7("=").Add_mid(part_bfr_bry, part.eqpos + 1, part.Len()); + tmp_bfr.Add_str_a7(""); + } + else { + tmp_bfr.Add_str_a7("").Add(part.To_bry()).Add_str_a7(""); + arg_idx++; + } + } + byte[] element = tmp_bfr.Add_str_a7("").To_bry_and_clear(); + return new Xomw_prepro_accum__dom(String_.new_u8(element)); + } + @Override protected void preprocessToObj_add_element(Xomw_prepro_accum element) { + accum_dom.Add_bry(((Xomw_prepro_accum__dom)element).To_bry()); + } + @Override protected void preprocessToObj_equals(XomwPPDStack stack) { + stack.Get_current_part().eqpos = accum_dom.Len(); + accum_dom.Add_bry(Byte_ascii.Eq_bry); + } + @Override protected Object preprocessToObj_term(XomwPPDStack stack) { + Bry_bfr root_accum = Bry_bfr_.New().Add_str_u8(((Xomw_prepro_accum__dom)stack.Get_root_accum()).To_str()); + int stack_len = stack.stack.Len(); + for (int j = 0; j < stack_len; j++) { + Xomw_prepro_piece piece = (Xomw_prepro_piece)stack.stack.Get_at(j); + root_accum.Add(piece.Break_syntax(tmp_bfr, -1)); + } + root_accum.Add_str_a7(""); + return root_accum.To_bry_and_clear(); + } + + @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_DOM();} + public static final XomwPreprocessor Instance = new XomwPreprocessor_DOM(); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr__tst.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM__tst.java similarity index 92% rename from 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr__tst.java rename to 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM__tst.java index daba00703..6e4e33baf 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_wkr__tst.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_DOM__tst.java @@ -13,10 +13,10 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.mediawiki.includes.parsers.prepros; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +package gplx.xowa.mediawiki.includes.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import org.junit.*; -public class Xomw_prepro_wkr__tst { - private final Xomw_prepro_wkr__fxt fxt = new Xomw_prepro_wkr__fxt(); +public class XomwPreprocessor_DOM__tst { + private final XomwPreprocessor_DOM__fxt fxt = new XomwPreprocessor_DOM__fxt(); @Test public void Text() { fxt.Test__parse("abc", "abc"); } @@ -218,16 +218,16 @@ public class Xomw_prepro_wkr__tst { fxt.Test__parse("abc", "a<noinclude>b</noinclude>c"); } } -class Xomw_prepro_wkr__fxt { - private final Xomw_prepro_wkr wkr = new Xomw_prepro_wkr(); +class XomwPreprocessor_DOM__fxt { + private final XomwPreprocessor_DOM wkr = new XomwPreprocessor_DOM(); private boolean for_inclusion = false; - public Xomw_prepro_wkr__fxt() { + public XomwPreprocessor_DOM__fxt() { wkr.Init_by_wiki("pre"); } public void Init__for_inclusion_(boolean v) {for_inclusion = v;} public void Test__parse(String src_str, String expd) { byte[] src_bry = Bry_.new_u8(src_str); - byte[] actl = wkr.Preprocess_to_xml(src_bry, for_inclusion); + byte[] actl = wkr.preprocessToXml(src_bry, for_inclusion); Tfds.Eq_str_lines(expd, String_.new_u8(actl), src_str); } } diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java new file mode 100644 index 000000000..9e6ab0dc1 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/XomwPreprocessor_Hash.java @@ -0,0 +1,187 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; +import gplx.xowa.mediawiki.includes.parsers.preprocessors.*; +class XomwPreprocessor_Hash extends XomwPreprocessor { private XophpArray accum = new XophpArray(); + @Override public XomwPPNode preprocessToObj(String text, int flags) { + return null; + } + + @Override public XomwPPFrame newFrame() { + return null; + } + + @Override public XomwPPFrame newCustomFrame(XomwPPFrame args) { + return null; + } + + @Override protected Xomw_prepro_accum Factory__accum() {return Xomw_prepro_accum__hash.Instance;} + @Override protected XomwPPDPart Factory__part() {return new XomwPPDPart_Hash("");} + @Override protected Xomw_prepro_accum Accum__set(Xomw_prepro_accum accum) {return accum;} + + @Override protected void preprocessToObj_root() {} // NOTE: deliberately empty; + + @Override protected void preprocessToObj_ignore(byte[] src, int bgn, int end) { + accum.Add(XophpArray.New("ignore", XophpString.substr(src, bgn, end))); + } + @Override protected void preprocessToObj_literal(byte[] src, int bgn, int end) { + addLiteral(accum, XophpString.substr(src, bgn, end)); + } + @Override protected void preprocessToObj_comment(byte[] src, int bgn, int end) { + accum.Add(XophpArray.New("comment", XophpString.substr(src, bgn, end))); + } + @Override protected void preprocessToObj_removeLeadingWhitespaceFromEnd(int ws_len) { + int endIndex = accum.Len() - 1; + if ( ws_len > 0 + && endIndex >= 0) { + Object itm_obj = accum.Get(endIndex); + if (Type_.Eq_by_obj(itm_obj, Bry_.Cls_ref_type)) { + byte[] itm = (byte[])itm_obj; + if (XophpString.strspn_fwd__space_or_tab(itm, 0, itm.length, itm.length) == ws_len) { + accum.Set(endIndex, XophpString.substr(itm, 0, -ws_len)); + } + } + } + } + @Override protected byte[] preprocessToObj_close_init() {return null;} + @Override protected byte[] preprocessToObj_close_make(byte[] src, int bgn, int end) { + return Bry_.Mid(src, bgn, end); + } + @Override protected void preprocessToObj_ext(byte[] src, byte[] name, int atr_bgn, int atr_end, byte[] inner, byte[] close) { + XophpArray children = XophpArray.New(); + children.Add(XophpArray.New("name", name)); + children.Add(XophpArray.New("attr", Bry_.Mid(src, atr_bgn, atr_end))); + if (inner != null) + children.Add(XophpArray.New("inner", inner)); + if (close != null) + children.Add(XophpArray.New("close", close)); + accum.Add(XophpArray.New("ext", children)); + } + @Override protected Xomw_prepro_accum preprocessToObj_heading_init(int count, int heading_index) { + Xomw_prepro_accum__hash rv = new Xomw_prepro_accum__hash(); + rv.Ary().Add + ( XophpArray.New + ( "possible-h", + XophpArrayUtl.array_merge + ( XophpArray.New + ( XophpArray.New("@level", XophpArray.New(count)) + , XophpArray.New("@i" , XophpArray.New(heading_index)) + ) + , accum + ) + ) + ); + return rv; + } + @Override protected void preprocessToObj_heading_end(Xomw_prepro_accum element) { + XophpArrayUtl.array_splice(accum, accum.Len(), 0, ((Xomw_prepro_accum__hash)element).Ary()); + } + + @Override protected Xomw_prepro_accum preprocessToObj_text(Xomw_prepro_accum element_obj, Xomw_prepro_piece piece, byte[] rule_end, int matching_count) { + Xomw_prepro_accum__hash element = (Xomw_prepro_accum__hash)element_obj; + // element = piece.breakSyntax(matchingCount); + addLiteral(element.Ary(), String_.new_u8(Bry_.Repeat_bry(rule_end, matching_count))); + return element; + } + @Override protected Xomw_prepro_accum preprocessToObj_xml(Xomw_prepro_piece piece, byte[] name_bry, int max_count, int matching_count) { + List_adp parts = piece.parts; + byte[] title = ((XomwPPDPart_DOM)parts.Get_at(0)).To_bry(); + parts.Del_at(0); + + XophpArray children = XophpArray.New(); + + // The invocation is at the start of the line if lineStart is set in + // the stack, and all opening brackets are used up. + if (max_count == matching_count && piece.line_start) { // RELIC:!empty( $piece->lineStart ) + children.Add(XophpArray.New("@lineStart", XophpArray.New(1))); + } + XophpArray titleNode = XophpArray.New("title", title); + children.Add(titleNode); + + // int argIndex = 1; + int parts_len = parts.Len(); + for (int j = 0; j < parts_len; j++) { + XomwPPDPart part = (XomwPPDPart)parts.Get_at(j); + if (part.eqpos != -1) { + /* + Object equalsNode = part.Out()[part.eqpos]; + XophpArray nameNode = XophpArray.New("name" , XophpArrayUtl.array_splice(part.Out(), 0, part.eqpos)); + XophpArray valueNode = XophpArray.New("value", XophpArrayUtl.array_splice(part.Out(), part.eqpos + 1)); + XophpArray partNode = XophpArray.New("part", XophpArray.New(nameNode, equalsNode, valueNode)); + children.Add(partNode); + */ + } + else { + /* + XophpArray nameNode = XophpArray.New("name" , XophpArray.New(XophpArray.New("@index", XophpArray.New(argIndex++)))); + XophpArray valueNode = XophpArray.New("value", part.Out()); + XophpArray partNode = XophpArray.New("part", XophpArray.New(nameNode, valueNode)); + children.Add(partNode); + */ + } + } + // XophpArray element = XophpArray.New(XophpArray.New(name, children)); + // return new Xomw_prepro_piece__hash(element); + return null; + } + @Override protected void preprocessToObj_add_element(Xomw_prepro_accum element) { + XophpArrayUtl.array_splice(accum, accum.Len(), 0, ((Xomw_prepro_accum__hash)element).Ary()); + } + @Override protected void preprocessToObj_equals(XomwPPDStack stack) { + accum.Add(XophpArray.New("equals", XophpArray.New("="))); + stack.Get_current_part().eqpos = accum.Len() - 1; + } + @Override protected Object preprocessToObj_term(XomwPPDStack stack) { + // for ( $stack->stack as $piece ) { + // array_splice( $stack->rootAccum, count( $stack->rootAccum ), 0, $piece->breakSyntax() ); + // } + // + // # Enable top-level headings + // for ( $stack->rootAccum as &$node ) { + // if ( is_array( $node ) && $node[PPNode_Hash_Tree::NAME] === 'possible-h' ) { + // $node[PPNode_Hash_Tree::NAME] = 'h'; + // } + // } + // + // $rootStore = [ [ 'root', $stack->rootAccum ] ]; + // $rootNode = new PPNode_Hash_Tree( $rootStore, 0 ); + // + // // Cache + // $tree = json_encode( $rootStore, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); + // if ( $tree !== false ) { + // $this->cacheSetTree( $text, $flags, $tree ); + // } + // + // return $rootNode; + return null; + } + + private static void addLiteral(XophpArray accum, byte[] text) {addLiteral(accum, String_.new_u8(text));} + private static void addLiteral(XophpArray accum, String text) { + int n = accum.Len(); + if (n > 0) { + Object itm = accum.Get(n - 1); + if (itm != null) { + accum.Set(n - 1, ((String)itm) + text); + return; + } + } + accum.Add(text); + } + + @Override public XomwPreprocessor Make_new(XomwParser parser) {return new XomwPreprocessor_Hash();} + public static final XomwPreprocessor Instance = new XomwPreprocessor_Hash(); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart.java new file mode 100644 index 000000000..299867aa8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart.java @@ -0,0 +1,48 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:Preprocessor_DOM +/** +* @ingroup Parser +*/ +public abstract class XomwPPDPart { + /** + * @var String Output accumulator String + */ +// private final byte[] output; + + // Optional member variables: + // eqpos Position of equals sign in output accumulator + // commentEnd Past-the-end input pointer for the last comment encountered + // visualEnd Past-the-end input pointer for the end of the accumulator minus comments + public int eqpos = -1; + public int commentEnd = -1; + public int visualEnd = -1; + + public XomwPPDPart(String output) { +// accum.Add_bry(Bry_.new_u8(output)); +// bfr = ((Xomw_prepro_accum__dom)accum).Bfr(); + } +// private final Xomw_prepro_accum__dom accum = new Xomw_prepro_accum__dom(""); +// private final Bry_bfr bfr; + public abstract Xomw_prepro_accum Accum(); +// +// public Bry_bfr Bfr() {return bfr;} +// public int Len() {return bfr.Len();} +// public byte[] To_bry() {return bfr.To_bry();} + + public abstract XomwPPDPart Make_new(String val); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_DOM.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_DOM.java new file mode 100644 index 000000000..cf7622a49 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_DOM.java @@ -0,0 +1,35 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:NONE +public class XomwPPDPart_DOM extends XomwPPDPart { // @codingStandardsIgnoreEnd + private final Bry_bfr bfr; + private final Xomw_prepro_accum__dom accum = new Xomw_prepro_accum__dom(""); + public XomwPPDPart_DOM(String output) {super(output); + bfr = accum.Bfr(); + if (output != String_.Empty) { + bfr.Add_str_u8(output); + } + } + @Override public Xomw_prepro_accum Accum() {return accum;} + public Bry_bfr Bfr() {return bfr;} + public int Len() {return bfr.Len();} + public byte[] To_bry() {return bfr.To_bry();} + + @Override public XomwPPDPart Make_new(String val) { + return new XomwPPDPart_DOM(val); + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_Hash.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_Hash.java new file mode 100644 index 000000000..7b0ff80f8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDPart_Hash.java @@ -0,0 +1,33 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:Preprocessor_Hash +/** +* @ingroup Parser +*/ +// @codingStandardsIgnoreStart Squiz.Classes.ValidClassName.NotCamelCaps +public class XomwPPDPart_Hash extends XomwPPDPart { // @codingStandardsIgnoreEnd + private final Xomw_prepro_accum__hash accum = new Xomw_prepro_accum__hash(); + public XomwPPDPart_Hash(String output) {super(output); + if (output != String_.Empty) { + accum.Ary().Add(output); + } + } + @Override public Xomw_prepro_accum Accum() {return accum;} + @Override public XomwPPDPart Make_new(String val) { + return new XomwPPDPart_Hash(val); + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDStack.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDStack.java new file mode 100644 index 000000000..084df6546 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPDStack.java @@ -0,0 +1,94 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:Preprocessor_DOM +/** +* Stack class to help Preprocessor::preprocessToObj() +* @ingroup Parser +*/ +public class XomwPPDStack { + public final List_adp stack = List_adp_.New(); + public Xomw_prepro_piece top; + private final Xomw_prepro_flags flags = new Xomw_prepro_flags(); + private Xomw_prepro_accum root_accum, accum; + + public XomwPPDStack(Xomw_prepro_accum prototype) { + root_accum = prototype.Make_new(); + accum = root_accum; + } + public void Clear() { + stack.Clear(); + accum.Clear(); + top = null; + } + public int Count() {return stack.Len();} + + public Xomw_prepro_accum Get_accum() {return accum;} + public Xomw_prepro_accum Get_root_accum() {return root_accum;} + + public XomwPPDPart Get_current_part() { + if (top == null) { + return null; + } + else { + return top.Get_current_part(); + } + } + + public void Push(Xomw_prepro_piece item) { + stack.Add(item); + this.top = (Xomw_prepro_piece)stack.Get_at(stack.Len() - 1); + accum = top.Get_accum(); + } + + public Xomw_prepro_piece Pop() { + int len = stack.Count(); + if (len == 0) { + throw Err_.new_wo_type("XomwPPDStack: no elements remaining"); + } + + Xomw_prepro_piece rv = (Xomw_prepro_piece)stack.Get_at(len - 1); + stack.Del_at(len - 1); + len--; + + if (len > 0) { + this.top = (Xomw_prepro_piece)stack.Get_at(stack.Len() - 1); + this.accum = top.Get_accum(); + } else { + this.top = null; + this.accum = root_accum; + } + return rv; + } + + public void Add_part(byte[] bry) { + top.Add_part(bry); + accum = top.Get_accum(); + } + + public Xomw_prepro_flags Get_flags() { + if (stack.Count() == 0) { + flags.findEquals = false; + flags.findPipe = false; + flags.inHeading = false; + return flags; + } + else { + top.Set_flags(flags); + return flags; + } + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java new file mode 100644 index 000000000..d7c39bff3 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPFrame.java @@ -0,0 +1,199 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:Preprocessor +/** +* @ingroup Parser +*/ +public abstract class XomwPPFrame { + public static final int NO_ARGS = 1; + public static final int NO_TEMPLATES = 2; + public static final int STRIP_COMMENTS = 4; + public static final int NO_IGNORE = 8; + public static final int RECOVER_COMMENTS = 16; + public static final int NO_TAGS = 32; + + public static final int RECOVER_ORIG = 59; // = 1|2|8|16|32 no constant expression support in PHP yet + + /** This constant exists when $indexOffset is supported in newChild() */ + public static final int SUPPORTS_INDEX_OFFSET = 1; + + /** + * Create a child frame + * + * @param array|boolean $args + * @param boolean|Title $title + * @param int $indexOffset A number subtracted from the index attributes of the arguments + * + * @return PPFrame + */ + public abstract XomwPPFrame newChild(Object args, XomwTitle title, int indexOffset); + + /** + * Expand a document tree node, caching the result on its parent with the given key + * @param String|int $key + * @param String|PPNode $root + * @param int $flags + * @return String + */ + public abstract String cachedExpand(String key, XomwPPNode root, int flags); + + /** + * Expand a document tree node + * @param String|PPNode $root + * @param int $flags + * @return String + */ + public abstract String expand(XomwPPNode root, int flags); + + /** + * Implode with flags for expand() + * @param String $sep + * @param int $flags + * @param String|PPNode $args,... + * @return String + */ + public abstract String implodeWithFlags(String sep, int flags, Object... args); + + /** + * Implode with no flags specified + * @param String $sep + * @param String|PPNode $args,... + * @return String + */ + public abstract String implode(String sep, Object... args); + + /** + * Makes an Object that, when expand()ed, will be the same as one obtained + * with implode() + * @param String $sep + * @param String|PPNode $args,... + * @return PPNode + */ + public abstract XomwPPNode virtualImplode(String sep, Object... args); + + /** + * Virtual implode with brackets + * @param String $start + * @param String $sep + * @param String $end + * @param String|PPNode $args,... + * @return PPNode + */ + public abstract XomwPPNode virtualBracketedImplode(String start, String sep, String end, Object... args); + + /** + * Returns true if there are no arguments in this frame + * + * @return boolean + */ + public abstract boolean isEmpty(); + + /** + * Returns all arguments of this frame + * @return array + */ + public abstract Object[] getArguments(); + + /** + * Returns all numbered arguments of this frame + * @return array + */ + public abstract Object[] getNumberedArguments(); + + /** + * Returns all named arguments of this frame + * @return array + */ + public abstract Object[] getNamedArguments(); + + /** + * Get an argument to this frame by name + * @param int|String $name + * @return String|boolean + */ + public abstract String getArgument(String name); + + /** + * Returns true if the infinite loop check is OK, false if a loop is detected + * + * @param Title $title + * @return boolean + */ + public abstract boolean loopCheck(XomwTitle title); + + /** + * Return true if the frame is a template frame + * @return boolean + */ + public abstract boolean isTemplate(); + + /** + * Set the "volatile" flag. + * + * Note that this is somewhat of a "hack" in order to make extensions + * with side effects (such as Cite) work with the PHP parser. New + * extensions should be written in a way that they do not need this + * function, because other parsers (such as Parsoid) are not guaranteed + * to respect it, and it may be removed in the future. + * + * @param boolean $flag + */ + public abstract void setVolatile(boolean flag); + + /** + * Get the "volatile" flag. + * + * Callers should avoid caching the result of an expansion if it has the + * volatile flag set. + * + * @see self::setVolatile() + * @return boolean + */ + public abstract boolean isVolatile(); + + /** + * Get the TTL of the frame's output. + * + * This is the maximum amount of time, in seconds, that this frame's + * output should be cached for. A value of null indicates that no + * maximum has been specified. + * + * Note that this TTL only applies to caching frames as parts of pages. + * It is not relevant to caching the entire rendered output of a page. + * + * @return int|null + */ + public abstract int getTTL(); + + /** + * Set the TTL of the output of this frame and all of its ancestors. + * Has no effect if the new TTL is greater than the one already set. + * Note that it is the caller's responsibility to change the cache + * expiry of the page as a whole, if such behavior is desired. + * + * @see self::getTTL() + * @param int $ttl + */ + public abstract void setTTL(int ttl); + + /** + * Get a title of frame + * + * @return Title + */ + public abstract XomwTitle getTitle(); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode.java new file mode 100644 index 000000000..3d5101091 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/XomwPPNode.java @@ -0,0 +1,108 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +// MW.FILE:Preprocessor +/** +* There are three types of nodes: +* * Tree nodes, which have a name and contain other nodes as children +* * Array nodes, which also contain other nodes but aren't considered part of a tree +* * Leaf nodes, which contain the actual data +* +* This interface provides access to the tree structure and to the contents of array nodes, +* but it does not provide access to the @gplx.Internal protected structure of leaf nodes. Access to leaf +* data is provided via two means: +* * PPFrame::expand(), which provides expanded text +* * The PPNode::split*() functions, which provide metadata about certain types of tree node +* @ingroup Parser +*/ +public abstract class XomwPPNode { + /** + * Get an array-type node containing the children of this node. + * Returns false if this is not a tree node. + * @return PPNode + */ + public abstract XomwPPNode[] getChildren(); + + /** + * Get the first child of a tree node. False if there isn't one. + * + * @return PPNode + */ + public abstract XomwPPNode getFirstChild(); + + /** + * Get the next sibling of any node. False if there isn't one + * @return PPNode + */ + public abstract XomwPPNode getNextSibling(); + + /** + * Get all children of this tree node which have a given name. + * Returns an array-type node, or false if this is not a tree node. + * @param String $type + * @return boolean|PPNode + */ + public abstract XomwPPNode getChildrenOfType(String type); + + /** + * Returns the length of the array, or false if this is not an array-type node + */ + public abstract int getLength(); + + /** + * Returns an item of an array-type node + * @param int $i + * @return boolean|PPNode + */ + public abstract XomwPPNode item(int i); + + /** + * Get the name of this node. The following names are defined here: + * + * h A heading node. + * template A double-brace node. + * tplarg A triple-brace node. + * title The first argument to a template or tplarg node. + * part Subsequent arguments to a template or tplarg node. + * #nodelist An array-type node + * + * The subclass may define various other names for tree and leaf nodes. + * @return String + */ + public abstract String getName(); + + /** + * Split a "" node into an associative array containing: + * name PPNode name + * index String index + * value PPNode value + * @return array + */ + public abstract Hash_adp splitArg(); + + /** + * Split an "" node into an associative array containing name, attr, inner and close + * All values in the resulting array are PPNodes. Inner and close are optional. + * @return array + */ + public abstract Hash_adp splitExt(); + + /** + * Split an "" node + * @return array + */ + public abstract Hash_adp splitHeading(); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_itm.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_itm.java similarity index 75% rename from 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_itm.java rename to 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_itm.java index 22fd37e03..11958d910 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_itm.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_itm.java @@ -13,7 +13,7 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.mediawiki.includes.parsers.prepros; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; public class Xomw_frame_itm { public byte[] Expand(byte[] ttl) { return null; diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_wkr.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_wkr.java similarity index 96% rename from 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_wkr.java rename to 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_wkr.java index df12cb72f..907c52f00 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_frame_wkr.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_frame_wkr.java @@ -13,7 +13,7 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.mediawiki.includes.parsers.prepros; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; // public class Xomw_frame_wkr { // THREAD.UNSAFE: caching for repeated calls // private final Xomw_parser parser; // public Xomw_frame_wkr(Xomw_parser parser) { diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum.java new file mode 100644 index 000000000..5bd6e2657 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum.java @@ -0,0 +1,20 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public interface Xomw_prepro_accum { + void Clear(); + Xomw_prepro_accum Make_new(); +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__dom.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__dom.java new file mode 100644 index 000000000..0c7fe6338 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__dom.java @@ -0,0 +1,54 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public class Xomw_prepro_accum__dom implements Xomw_prepro_accum { + private final Bry_bfr bfr = Bry_bfr_.New(); + public Xomw_prepro_accum__dom(String val) { + this.Add_str_literal(val); + } + public Xomw_prepro_accum__dom Add_str_literal(String val) { + bfr.Add_str_u8(val); + return this; + } + public Bry_bfr Bfr() {return bfr;} + public byte[] Bfr_bry() {return bfr.Bfr();} + public int Len() {return bfr.Len();} + public void Clear() {bfr.Clear();} + public Xomw_prepro_accum__dom Add_str_escaped(byte[] src, int bgn, int end) { + bfr.Add_bry_escape_html(src, bgn, end); + return this; + } + public Xomw_prepro_accum__dom Add_bry(byte[] val) { + bfr.Add(val); + return this; + } + public Xomw_prepro_accum__dom Add_bry(byte[] val, int bgn, int end) { + bfr.Add_mid(val, bgn, end); + return this; + } + public void Del_at_end(int count) { + bfr.Del_by(count); + } + public String To_str() { + return bfr.To_str(); + } + public byte[] To_bry() { + return bfr.To_bry(); + } + + public static final Xomw_prepro_accum__dom Instance = new Xomw_prepro_accum__dom(""); + public Xomw_prepro_accum Make_new() {return new Xomw_prepro_accum__dom("");} +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__hash.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__hash.java new file mode 100644 index 000000000..1d85cd589 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_accum__hash.java @@ -0,0 +1,25 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public class Xomw_prepro_accum__hash implements Xomw_prepro_accum { + public Xomw_prepro_accum__hash() { + } + public XophpArray Ary() {return ary;} private final XophpArray ary = new XophpArray(); + public void Clear() {ary.Clear();} + + public static final Xomw_prepro_accum__hash Instance = new Xomw_prepro_accum__hash(); + public Xomw_prepro_accum Make_new() {return new Xomw_prepro_accum__hash();} +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_curchar_itm.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_curchar_itm.java new file mode 100644 index 000000000..803ea29fd --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_curchar_itm.java @@ -0,0 +1,24 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public class Xomw_prepro_curchar_itm { + public Xomw_prepro_curchar_itm(byte[] bry, byte type) { + this.bry = bry; + this.type = type; + } + public byte[] bry; + public byte type; +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_elem.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_elem.java new file mode 100644 index 000000000..36eb8d108 --- /dev/null +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_elem.java @@ -0,0 +1,28 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public class Xomw_prepro_elem { + private static final byte[] Bry__tag_end = Bry_.new_a7(" 1 && ((XomwPPDPart)parts.Get_at(parts_len - 1)).eqpos != -1; + flags.inHeading = open_is_nl; + } + // Get the output String that would result if the close is not found. + public byte[] Break_syntax(Bry_bfr tmp_bfr, int opening_count) { + byte[] rv = Bry_.Empty; + if (Bry_.Eq(open, Byte_ascii.Nl_bry)) { + rv = ((XomwPPDPart_DOM)parts.Get_at(0)).To_bry(); + } + else { + if (opening_count == -1) { + opening_count = count; + } + tmp_bfr.Add(Bry_.Repeat_bry(open, opening_count)); + + // concat parts with "|" + boolean first = true; + int len = parts.Len(); + for (int i = 0; i < len; i++) { + XomwPPDPart part = (XomwPPDPart)parts.Get_at(i); + if (first) { + first = false; + } + else { + tmp_bfr.Add_byte_pipe(); + } + tmp_bfr.Add(((XomwPPDPart_DOM)part).To_bry()); + } + rv = tmp_bfr.To_bry_and_clear(); + } + return rv; + } +} diff --git a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_rule.java b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_rule.java similarity index 63% rename from 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_rule.java rename to 400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_rule.java index c6029bb3a..667fe7f66 100644 --- a/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/prepros/Xomw_prepro_rule.java +++ b/400_xowa/src/gplx/xowa/mediawiki/includes/parsers/preprocessors/Xomw_prepro_rule.java @@ -13,8 +13,8 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.mediawiki.includes.parsers.prepros; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; -class Xomw_prepro_rule { +package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*; import gplx.xowa.mediawiki.includes.parsers.*; +public class Xomw_prepro_rule { public Xomw_prepro_rule(byte[] bgn, byte[] end, int min, int max, int[] names) { this.bgn = bgn; this.end = end; @@ -42,23 +42,3 @@ class Xomw_prepro_rule { } } } -class Xomw_prepro_elem { - private static final byte[] Bry__tag_end = Bry_.new_a7(" 0) { - this.top = (Xomw_prepro_piece)stack.Get_at(stack.Len() - 1); - accum = top.Get_accum(); - } else { - this.top = null; - this.accum = root_accum; - } - return rv; - } - - public void Add_part(byte[] bry) { - top.Add_part(bry); - accum = top.Get_accum(); - } - - public Xomw_prepro_flags Get_flags() { - if (stack.Count() == 0) { - flags.Find_eq = false; - flags.Find_pipe = false; - flags.In_heading = false; - return flags; - } - else { - top.Set_flags(flags); - return flags; - } - } -} -class Xomw_prepro_flags { - public boolean Find_pipe; - public boolean Find_eq; - public boolean In_heading; -} -class Xomw_prepro_piece { - public final byte[] open; // Opening character (\n for heading) - public final byte[] close; // Matching closing char; - public int count; // Number of opening characters found (number of "=" for heading) - public final boolean line_start; // True if the open char appeared at the start of the input line; Not set for headings. - public final int start_pos; - public List_adp parts = List_adp_.New(); - public Xomw_prepro_piece(byte[] open, byte[] close, int count, int start_pos, boolean line_start) { - this.open = open; - this.close = close; - this.count = count; - this.start_pos = start_pos; - this.line_start = line_start; - parts.Add(new Xomw_prepro_part(Bry_.Empty)); - } - public void Parts__renew() { - parts.Clear(); - this.Add_part(Bry_.Empty); - } - public Xomw_prepro_part Get_current_part() { - return (Xomw_prepro_part)parts.Get_at(parts.Len() - 1); - } - public Bry_bfr Get_accum() { - return Get_current_part().bfr; - } - public void Add_part(byte[] bry) { - parts.Add(new Xomw_prepro_part(bry)); - } - public static final byte[] Brack_bgn_bry = Bry_.new_a7("["); - public void Set_flags(Xomw_prepro_flags flags) { - int parts_len = parts.Len(); - boolean open_is_nl = Bry_.Eq(open, Byte_ascii.Nl_bry); - boolean find_pipe = !open_is_nl && !Bry_.Eq(open, Brack_bgn_bry); - flags.Find_pipe = find_pipe; - flags.Find_eq = find_pipe && parts_len > 1 && ((Xomw_prepro_part)parts.Get_at(parts_len - 1)).Eqpos != -1; - flags.In_heading = open_is_nl; - } - // Get the output String that would result if the close is not found. - public byte[] Break_syntax(Bry_bfr tmp_bfr, int opening_count) { - byte[] rv = Bry_.Empty; - if (Bry_.Eq(open, Byte_ascii.Nl_bry)) { - rv = ((Xomw_prepro_part)parts.Get_at(0)).bfr.To_bry(); - } - else { - if (opening_count == -1) { - opening_count = count; - } - tmp_bfr.Add(Bry_.Repeat_bry(open, opening_count)); - - // concat parts with "|" - boolean first = true; - int len = parts.Len(); - for (int i = 0; i < len; i++) { - Xomw_prepro_part part = (Xomw_prepro_part)parts.Get_at(i); - if (first) { - first = false; - } - else { - tmp_bfr.Add_byte_pipe(); - } - tmp_bfr.Add(part.bfr.To_bry()); - } - rv = tmp_bfr.To_bry_and_clear(); - } - return rv; - } -} -class Xomw_prepro_part { - public Xomw_prepro_part(byte[] bry) { - bfr.Add(bry); - } - public final Bry_bfr bfr = Bry_bfr_.New(); - public int Eqpos = -1; - public int comment_end = -1; - public int visual_end = -1; -}