mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
XomwTemplateParser: Port XomwPPTemplateFrame_Hash [#632]
This commit is contained in:
parent
b56673c56e
commit
9809dfd6c7
@ -16,17 +16,34 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
||||||
import gplx.core.strings.*;
|
import gplx.core.strings.*;
|
||||||
public class XophpArray_ {
|
public class XophpArray_ {
|
||||||
|
// REF.PHP:https://www.php.net/manual/en/function.array-merge.php
|
||||||
public static XophpArray array_merge(XophpArray... vals) {
|
public static XophpArray array_merge(XophpArray... vals) {
|
||||||
XophpArray rv = new XophpArray();
|
XophpArray rv = new XophpArray();
|
||||||
for (XophpArray ary : vals) {
|
for (XophpArray ary : vals) {
|
||||||
XophpArrayItm[] itms = ary.To_ary();
|
XophpArrayItm[] itms = ary.To_ary();
|
||||||
for (XophpArrayItm itm : itms) {
|
for (XophpArrayItm itm : itms) {
|
||||||
array_add(rv, itm);
|
array_itm_add(rv, itm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
private static void array_add(XophpArray ary, XophpArrayItm itm) {
|
// REF.PHP:https://www.php.net/manual/en/function.array-merge.php
|
||||||
|
// "If you want to append array elements from the second array to the first array while not overwriting the elements from the first array and not re-indexing, use the + array union operator:"
|
||||||
|
public static XophpArray array_add(XophpArray lhs, XophpArray... vals) {
|
||||||
|
for (XophpArray ary : vals) {
|
||||||
|
XophpArrayItm[] itms = ary.To_ary();
|
||||||
|
for (XophpArrayItm itm : itms) {
|
||||||
|
if (lhs.Has(itm.Key())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.Add(itm.Key(), itm.Val());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
private static void array_itm_add(XophpArray ary, XophpArrayItm itm) {
|
||||||
if (itm.Key_is_int())
|
if (itm.Key_is_int())
|
||||||
ary.Add(itm.Val());
|
ary.Add(itm.Val());
|
||||||
else
|
else
|
||||||
@ -51,14 +68,14 @@ public class XophpArray_ {
|
|||||||
|
|
||||||
// add src from 0 to bgn
|
// add src from 0 to bgn
|
||||||
for (int i = 0; i < bgn; i++) {
|
for (int i = 0; i < bgn; i++) {
|
||||||
array_add(src, itms[i]);
|
array_itm_add(src, itms[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add repl
|
// add repl
|
||||||
if (repl != null) {
|
if (repl != null) {
|
||||||
XophpArrayItm[] repl_itms = repl.To_ary();
|
XophpArrayItm[] repl_itms = repl.To_ary();
|
||||||
for (XophpArrayItm itm : repl_itms) {
|
for (XophpArrayItm itm : repl_itms) {
|
||||||
array_add(src, itm);
|
array_itm_add(src, itm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,13 +96,13 @@ public class XophpArray_ {
|
|||||||
|
|
||||||
// add src from end to len
|
// add src from end to len
|
||||||
for (int i = end; i < src_len; i++) {
|
for (int i = end; i < src_len; i++) {
|
||||||
array_add(src, itms[i]);
|
array_itm_add(src, itms[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add del to rv
|
// add del to rv
|
||||||
XophpArray rv = new XophpArray();
|
XophpArray rv = new XophpArray();
|
||||||
for (int i = bgn; i < end; i++) {
|
for (int i = bgn; i < end; i++) {
|
||||||
array_add(rv, itms[i]);
|
array_itm_add(rv, itms[i]);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -100,6 +117,16 @@ public class XophpArray_ {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static XophpArray array_keys(XophpArray array) {
|
||||||
|
XophpArray rv = XophpArray.New();
|
||||||
|
int len = array.count();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
XophpArrayItm itm = array.Get_at_itm(i);
|
||||||
|
rv.Add(itm.Key());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// DEPRECATE:use XophpArray
|
// DEPRECATE:use XophpArray
|
||||||
public static boolean popBoolOrN(List_adp list) {return Bool_.Cast(List_adp_.Pop_or(list, false));}
|
public static boolean popBoolOrN(List_adp list) {return Bool_.Cast(List_adp_.Pop_or(list, false));}
|
||||||
public static byte[] popBryOrNull(List_adp list) {return (byte[])List_adp_.Pop_or(list, null);}
|
public static byte[] popBryOrNull(List_adp list) {return (byte[])List_adp_.Pop_or(list, null);}
|
||||||
|
@ -20,44 +20,51 @@ public class XophpArray__tst { // REF:https://www.php.net/manual/en/function.arr
|
|||||||
@Test public void array_merge__basic() {
|
@Test public void array_merge__basic() {
|
||||||
XophpArray ary1 = fxt.Make().Add("key1", "val1").Add("a");
|
XophpArray ary1 = fxt.Make().Add("key1", "val1").Add("a");
|
||||||
XophpArray ary2 = fxt.Make().Add("key2", "val2").Add("b");
|
XophpArray ary2 = fxt.Make().Add("key2", "val2").Add("b");
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add("key1", "val1").Add("a").Add("key2", "val2").Add("b")
|
( fxt.Make().Add("key1", "val1").Add("a").Add("key2", "val2").Add("b")
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_merge__same_key() {
|
@Test public void array_merge__same_key() {
|
||||||
XophpArray ary1 = fxt.Make().Add("key", "val1");
|
XophpArray ary1 = fxt.Make().Add("key", "val1");
|
||||||
XophpArray ary2 = fxt.Make().Add("key", "val2");
|
XophpArray ary2 = fxt.Make().Add("key", "val2");
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add("key", "val2")
|
( fxt.Make().Add("key", "val2")
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_merge__same_idx() {
|
@Test public void array_merge__same_idx() {
|
||||||
XophpArray ary1 = fxt.Make().Add(0, "a");
|
XophpArray ary1 = fxt.Make().Add(0, "a");
|
||||||
XophpArray ary2 = fxt.Make().Add(0, "b");
|
XophpArray ary2 = fxt.Make().Add(0, "b");
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add(0, "a").Add(1, "b")
|
( fxt.Make().Add(0, "a").Add(1, "b")
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_merge__renumber() {
|
@Test public void array_merge__renumber() {
|
||||||
XophpArray ary1 = fxt.Make().Add(3, "a");
|
XophpArray ary1 = fxt.Make().Add(3, "a");
|
||||||
XophpArray ary2 = fxt.Make().Add(2, "b");
|
XophpArray ary2 = fxt.Make().Add(2, "b");
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add(0, "a").Add(1, "b")
|
( fxt.Make().Add(0, "a").Add(1, "b")
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_merge__example_1() {
|
@Test public void array_merge__example_1() {
|
||||||
XophpArray ary1 = fxt.Make().Add("color", "red").Add_many(2, 4);
|
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);
|
XophpArray ary2 = fxt.Make().Add_many("a", "b").Add("color", "green").Add("shape", "trapezoid").Add(4);
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add("color", "green").Add_many(2, 4, "a", "b").Add("shape", "trapezoid").Add(4)
|
( fxt.Make().Add("color", "green").Add_many(2, 4, "a", "b").Add("shape", "trapezoid").Add(4)
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_merge__example_2() {
|
@Test public void array_merge__example_2() {
|
||||||
XophpArray ary1 = fxt.Make();
|
XophpArray ary1 = fxt.Make();
|
||||||
XophpArray ary2 = fxt.Make().Add(1, "data");
|
XophpArray ary2 = fxt.Make().Add(1, "data");
|
||||||
fxt.Test__array_merge
|
fxt.Test__eq
|
||||||
( fxt.Make().Add(0, "data")
|
( fxt.Make().Add(0, "data")
|
||||||
, ary1, ary2);
|
, XophpArray_.array_merge(ary1, ary2));
|
||||||
|
}
|
||||||
|
@Test public void array_add() {
|
||||||
|
XophpArray ary1 = fxt.Make().Add(0, "zero_a").Add(2, "two_a").Add(3, "three_a");
|
||||||
|
XophpArray ary2 = fxt.Make().Add(1, "one_b").Add(3, "three_b").Add(4, "four_b");
|
||||||
|
fxt.Test__eq
|
||||||
|
( fxt.Make().Add(0, "zero_a").Add(2, "two_a").Add(3, "three_a").Add(1, "one_b").Add(4, "four_b")
|
||||||
|
, XophpArray_.array_add(ary1, ary2));
|
||||||
}
|
}
|
||||||
@Test public void array_splice__bgn_is_positive() {
|
@Test public void array_splice__bgn_is_positive() {
|
||||||
XophpArray src = fxt.Make().Add_many("a", "b", "c", "d");
|
XophpArray src = fxt.Make().Add_many("a", "b", "c", "d");
|
||||||
@ -253,10 +260,6 @@ public class XophpArray__tst { // REF:https://www.php.net/manual/en/function.arr
|
|||||||
}
|
}
|
||||||
class XophpArray__fxt {
|
class XophpArray__fxt {
|
||||||
public XophpArray Make() {return new XophpArray();}
|
public XophpArray Make() {return new XophpArray();}
|
||||||
public void Test__array_merge(XophpArray expd, XophpArray... vals) {
|
|
||||||
XophpArray actl = XophpArray_.array_merge(vals);
|
|
||||||
Gftest.Eq__str(expd.To_str(), actl.To_str());
|
|
||||||
}
|
|
||||||
public void Test__eq(XophpArray expd, XophpArray actl) {
|
public void Test__eq(XophpArray expd, XophpArray actl) {
|
||||||
Gftest.Eq__str(expd.To_str(), actl.To_str());
|
Gftest.Eq__str(expd.To_str(), actl.To_str());
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ package gplx.xowa.mediawiki; import gplx.*; import gplx.xowa.*;
|
|||||||
public class XophpIo_ {
|
public class XophpIo_ {
|
||||||
public static String file_get_contents(String path) {
|
public static String file_get_contents(String path) {
|
||||||
String rv = Io_mgr.Instance.LoadFilStr(path);
|
String rv = Io_mgr.Instance.LoadFilStr(path);
|
||||||
return String_.Eq(rv, String_.Empty) ? XophpString_.Null : rv;
|
return String_.Eq(rv, String_.Empty) ? XophpString_.False : rv;
|
||||||
}
|
}
|
||||||
public static boolean file_exists(String path) {
|
public static boolean file_exists(String path) {
|
||||||
return Io_mgr.Instance.ExistsFil(Io_url_.new_fil_(path));
|
return Io_mgr.Instance.ExistsFil(Io_url_.new_fil_(path));
|
||||||
|
@ -19,7 +19,7 @@ import gplx.core.intls.*;
|
|||||||
import gplx.objects.strings.unicodes.*;
|
import gplx.objects.strings.unicodes.*;
|
||||||
import gplx.core.primitives.*;
|
import gplx.core.primitives.*;
|
||||||
public class XophpString_ implements XophpCallbackOwner {
|
public class XophpString_ implements XophpCallbackOwner {
|
||||||
public static final String Null = null;
|
public static final String False = null;
|
||||||
public static boolean is_true(String s) {return s != null;} // handles code like "if ($var)" where var is an Object;
|
public static boolean is_true(String s) {return s != null;} // handles code like "if ($var)" where var is an Object;
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/function.strpos.php
|
// REF.PHP: https://www.php.net/manual/en/function.strpos.php
|
||||||
@ -240,6 +240,9 @@ public class XophpString_ implements XophpCallbackOwner {
|
|||||||
public static byte[] str_replace(byte[] find, byte[] repl, byte[] src) {
|
public static byte[] str_replace(byte[] find, byte[] repl, byte[] src) {
|
||||||
return Bry_.Replace(src, find, repl);
|
return Bry_.Replace(src, find, repl);
|
||||||
}
|
}
|
||||||
|
public static String str_replace(String find, String repl, String src) {
|
||||||
|
return String_.Replace(src, find, repl);
|
||||||
|
}
|
||||||
public static byte[] strstr(byte[] src, byte[] find) {
|
public static byte[] strstr(byte[] src, byte[] find) {
|
||||||
int pos = Bry_find_.Find_fwd(src, find);
|
int pos = Bry_find_.Find_fwd(src, find);
|
||||||
return pos == Bry_find_.Not_found ? null : Bry_.Mid(src, pos, src.length);
|
return pos == Bry_find_.Not_found ? null : Bry_.Mid(src, pos, src.length);
|
||||||
@ -256,93 +259,135 @@ public class XophpString_ implements XophpCallbackOwner {
|
|||||||
, Int_obj_ref.New(Byte_ascii.Null)
|
, Int_obj_ref.New(Byte_ascii.Null)
|
||||||
, Int_obj_ref.New(Byte_ascii.Vertical_tab)
|
, Int_obj_ref.New(Byte_ascii.Vertical_tab)
|
||||||
);
|
);
|
||||||
public static String rtrim(String src) {return rtrim(src, null);}
|
public static String trim (String src) {return trim_outer( 0, src, null);}
|
||||||
public static String rtrim(String src_str, String pad_str) {
|
public static String trim (String src, String pad) {return trim_outer( 0, src, pad);}
|
||||||
Hash_adp pad_hash = null;
|
public static String ltrim(String src) {return trim_outer( 1, src, null);}
|
||||||
if (pad_str == null) pad_hash = trim_ws_hash;
|
public static String ltrim(String src, String pad) {return trim_outer( 1, src, pad);}
|
||||||
|
public static String rtrim(String src) {return trim_outer(-1, src, null);}
|
||||||
|
public static String rtrim(String src, String pad) {return trim_outer(-1, src, pad);}
|
||||||
|
private static String trim_outer(int type, String src_str, String pad_str) {
|
||||||
// init brys / lens
|
// init brys / lens
|
||||||
byte[] src_bry = Bry_.new_u8(src_str);
|
byte[] src_bry = Bry_.new_u8(src_str);
|
||||||
int src_len = src_bry.length;
|
int src_len = src_bry.length;
|
||||||
byte[] pad_bry = Bry_.new_u8(pad_str);
|
byte[] pad_bry = Bry_.new_u8(pad_str);
|
||||||
int pad_len = pad_bry.length;
|
int pad_len = pad_bry.length;
|
||||||
|
|
||||||
|
// create pad_hash if not ws_hash
|
||||||
|
// NOTE: this does not support mutlibyte chars, and PHP does not support multibyte chars; see TEST
|
||||||
|
Hash_adp pad_hash = null;
|
||||||
|
if (pad_len > 1) {
|
||||||
|
if (pad_str == null) {
|
||||||
|
pad_hash = trim_ws_hash;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pad_hash = Hash_adp_.New();
|
||||||
|
byte prv_byte = Byte_.Zero;
|
||||||
|
for (int i = 0; i < pad_len; i++) {
|
||||||
|
byte pad_byte = pad_bry[i];
|
||||||
|
if (pad_byte == Byte_ascii.Dot && i < pad_len - 1) {
|
||||||
|
byte nxt_byte = pad_bry[i + 1];
|
||||||
|
if (nxt_byte == Byte_ascii.Dot) {
|
||||||
|
if (i == 0) {
|
||||||
|
throw new XophpError(".. found but at start of String; src=" + pad_str);
|
||||||
|
}
|
||||||
|
else if (i == pad_len - 2) {
|
||||||
|
throw new XophpError(".. found but at end of String; src=" + pad_str);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nxt_byte = pad_bry[i + 2];
|
||||||
|
if (nxt_byte > prv_byte) {
|
||||||
|
for (byte j = prv_byte; j < nxt_byte; j++) {
|
||||||
|
Byte_obj_ref rng_obj = Byte_obj_ref.new_(j);
|
||||||
|
if (!pad_hash.Has(rng_obj))
|
||||||
|
pad_hash.Add_as_key_and_val(rng_obj);
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new XophpError(".. found but next byte must be greater than previous byte; src=" + pad_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prv_byte = pad_byte;
|
||||||
|
Byte_obj_ref pad_obj = Byte_obj_ref.new_(pad_byte);
|
||||||
|
if (!pad_hash.Has(pad_obj))
|
||||||
|
pad_hash.Add_as_key_and_val(pad_obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do trim
|
||||||
|
int[] rv = new int[2];
|
||||||
|
rv[0] = 0;
|
||||||
|
rv[1] = src_len;
|
||||||
|
if (type <= 0) { // trim or rtrim
|
||||||
|
trim_inner(Bool_.N, rv, src_bry, src_len, pad_bry, pad_len, pad_hash);
|
||||||
|
}
|
||||||
|
if (type >= 0) { // trim or ltrim
|
||||||
|
trim_inner(Bool_.Y, rv, src_bry, src_len, pad_bry, pad_len, pad_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return String
|
||||||
|
int trim_bgn = rv[0];
|
||||||
|
int trim_end = rv[1];
|
||||||
|
return trim_bgn == 0 && trim_end == src_len
|
||||||
|
? src_str
|
||||||
|
: String_.new_u8(Bry_.Mid(src_bry, trim_bgn, trim_end));
|
||||||
|
}
|
||||||
|
private static void trim_inner(boolean is_bos, int[] rv, byte[] src_bry, int src_len, byte[] pad_bry, int pad_len, Hash_adp pad_hash) {
|
||||||
// ----------------------
|
// ----------------------
|
||||||
// 0, 1 chars (optimized)
|
// init vars
|
||||||
// ----------------------
|
// ----------------------
|
||||||
int last = 0;
|
int rv_idx = 1;
|
||||||
|
int trim_bgn = src_len - 1;
|
||||||
|
int trim_end = -1;
|
||||||
|
int trim_add = -1;
|
||||||
|
int trim_adj = 1;
|
||||||
|
if (is_bos) {
|
||||||
|
rv_idx = 0;
|
||||||
|
trim_bgn = 0;
|
||||||
|
trim_end = src_len;
|
||||||
|
trim_add = 1;
|
||||||
|
trim_adj = 0;
|
||||||
|
}
|
||||||
|
int trim_pos = trim_end;
|
||||||
|
|
||||||
switch (pad_len) {
|
switch (pad_len) {
|
||||||
// pad is ""
|
// pad is 0 char; aka: ""
|
||||||
case 0:
|
case 0:
|
||||||
return src_str;
|
break;
|
||||||
// pad is 1 char
|
// pad is 1 char
|
||||||
case 1:
|
case 1:
|
||||||
last = src_len;
|
|
||||||
byte pad_byte = pad_bry[0];
|
byte pad_byte = pad_bry[0];
|
||||||
for (int i = src_len - 1; i > -1; i--) {
|
for (int i = trim_bgn; i != trim_end; i += trim_add) {
|
||||||
byte cur = src_bry[i];
|
byte cur = src_bry[i];
|
||||||
last = i + 1;
|
trim_pos = i + trim_adj;
|
||||||
if (cur != pad_byte) {
|
if (cur != pad_byte) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (last == src_len) ? src_str : String_.new_u8(Bry_.Mid(src_bry, 0, last));
|
break;
|
||||||
}
|
// pad is 2+ chars
|
||||||
|
default:
|
||||||
// --------
|
// loop src until non-matching pad int
|
||||||
// 2+ chars
|
Byte_obj_ref temp = Byte_obj_ref.zero_();
|
||||||
// --------
|
trim_pos = src_len;
|
||||||
// create pad_hash if not ws_hash
|
for (int i = trim_bgn; i != trim_end; i += trim_add) {
|
||||||
// NOTE: PHP does not support multibyte strings; see TEST
|
temp.Val_(src_bry[i]);
|
||||||
if (pad_hash == null) {
|
trim_pos = i + trim_adj;
|
||||||
pad_hash = Hash_adp_.New();
|
if (!pad_hash.Has(temp)) {
|
||||||
byte prv_byte = Byte_.Zero;
|
break;
|
||||||
for (int i = 0; i < pad_len; i++) {
|
|
||||||
byte pad_byte = pad_bry[i];
|
|
||||||
if (pad_byte == Byte_ascii.Dot && i < pad_len - 1) {
|
|
||||||
byte nxt_byte = pad_bry[i + 1];
|
|
||||||
if (nxt_byte == Byte_ascii.Dot) {
|
|
||||||
if (i == 0) {
|
|
||||||
throw new XophpError(".. found but at start of String; src=" + pad_str);
|
|
||||||
}
|
|
||||||
else if (i == pad_len - 2) {
|
|
||||||
throw new XophpError(".. found but at end of String; src=" + pad_str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nxt_byte = pad_bry[i + 2];
|
|
||||||
if (nxt_byte > prv_byte) {
|
|
||||||
for (byte j = prv_byte; j < nxt_byte; j++) {
|
|
||||||
Byte_obj_ref rng_obj = Byte_obj_ref.new_(j);
|
|
||||||
if (!pad_hash.Has(rng_obj))
|
|
||||||
pad_hash.Add_as_key_and_val(rng_obj);
|
|
||||||
}
|
|
||||||
i += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new XophpError(".. found but next byte must be greater than previous byte; src=" + pad_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prv_byte = pad_byte;
|
break;
|
||||||
Byte_obj_ref pad_obj = Byte_obj_ref.new_(pad_byte);
|
|
||||||
if (!pad_hash.Has(pad_obj))
|
|
||||||
pad_hash.Add_as_key_and_val(pad_obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop src until non-matching pad int
|
// set return
|
||||||
Byte_obj_ref temp = Byte_obj_ref.zero_();
|
if (trim_pos != trim_end) {
|
||||||
last = src_len;
|
rv[rv_idx] = trim_pos;
|
||||||
for (int i = src_len - 1; i > -1; i--) {
|
|
||||||
temp.Val_(src_bry[i]);
|
|
||||||
last = i + 1;
|
|
||||||
if (!pad_hash.Has(temp)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (last == src_len) ? src_str : String_.new_u8(Bry_.Mid(src_bry, 0, last));
|
|
||||||
}
|
}
|
||||||
public static String str_repeat(String val, int count) {
|
public static String str_repeat(String val, int count) {
|
||||||
int val_len = String_.Len(val);
|
int val_len = String_.Len(val);
|
||||||
|
@ -94,6 +94,48 @@ public class XophpString__tst {
|
|||||||
// REF.MW:https://www.php.net/manual/en/function.trim.php
|
// REF.MW:https://www.php.net/manual/en/function.trim.php
|
||||||
fxt.Test__rtrim("\u00A0µ déjà\u00A0", "\u00A0", "\u00A0µ déj<C3A9>");// NOTE: technically should be "...j\xC3", but String_.new_u8 ignores invalid bytes
|
fxt.Test__rtrim("\u00A0µ déjà\u00A0", "\u00A0", "\u00A0µ déj<C3A9>");// NOTE: technically should be "...j\xC3", but String_.new_u8 ignores invalid bytes
|
||||||
}
|
}
|
||||||
|
@Test public void ltrim() {
|
||||||
|
// pad is 0, 1 char
|
||||||
|
fxt.Test__ltrim("0010", "", "0010"); // empty pad returns String
|
||||||
|
fxt.Test__ltrim("010", "0", "10"); // basic test; trim 1;
|
||||||
|
fxt.Test__ltrim("0010", "0", "10"); // basic test; trim 2;
|
||||||
|
fxt.Test__ltrim("10", "0", "10"); // nothing to trim
|
||||||
|
|
||||||
|
// pad is 2+char
|
||||||
|
fxt.Test__ltrim("10ab10", "01", "ab10"); // basic test
|
||||||
|
fxt.Test__ltrim("10ab10", "34", "10ab10"); // nothing to trim
|
||||||
|
fxt.Test__ltrim("10ab10", "010", "ab10"); // don't fail if repeated chars
|
||||||
|
|
||||||
|
// pad has ..
|
||||||
|
fxt.Test__ltrim("23ab23", "0..4", "ab23"); // basic test
|
||||||
|
fxt.Test__ltrim(".23ab23", "0.4", "23ab23"); // single dot is not range
|
||||||
|
|
||||||
|
// PHP samples
|
||||||
|
fxt.Test__ltrim("\t\tThese are a few words :) ... ", " \t.", "These are a few words :) ... ");
|
||||||
|
fxt.Test__ltrim("Hello World", "Hdle", "o World");
|
||||||
|
fxt.Test__ltrim("\u0009Example String\n", "\u0000..\u001F", "Example String\n");
|
||||||
|
}
|
||||||
|
@Test public void trim() {
|
||||||
|
// pad is 0, 1 char
|
||||||
|
fxt.Test__trim("0010", "", "0010"); // empty pad returns String
|
||||||
|
fxt.Test__trim("010", "0", "1"); // basic test; trim 1;
|
||||||
|
fxt.Test__trim("00100", "0", "1"); // basic test; trim 2;
|
||||||
|
fxt.Test__trim("10", "0", "1"); // nothing to trim
|
||||||
|
|
||||||
|
// pad is 2+char
|
||||||
|
fxt.Test__trim("10ab10", "01", "ab"); // basic test
|
||||||
|
fxt.Test__trim("10ab10", "34", "10ab10"); // nothing to trim
|
||||||
|
fxt.Test__trim("10ab10", "010", "ab"); // don't fail if repeated chars
|
||||||
|
|
||||||
|
// pad has ..
|
||||||
|
fxt.Test__trim("23ab23", "0..4", "ab"); // basic test
|
||||||
|
fxt.Test__trim(".23ab23.", "0.4", "23ab23"); // single dot is not range
|
||||||
|
|
||||||
|
// PHP samples
|
||||||
|
fxt.Test__trim("\t\tThese are a few words :) ... ", " \t.", "These are a few words :)");
|
||||||
|
fxt.Test__trim("Hello World", "Hdle", "o Wor");
|
||||||
|
fxt.Test__trim("\u0009Example String\n", "\u0000..\u001F", "Example String");
|
||||||
|
}
|
||||||
@Test public void ord() {
|
@Test public void ord() {
|
||||||
fxt.Test__ord("a", 97); // 1 char
|
fxt.Test__ord("a", 97); // 1 char
|
||||||
fxt.Test__ord("abc", 97); // 2+ chars takes first
|
fxt.Test__ord("abc", 97); // 2+ chars takes first
|
||||||
@ -168,6 +210,12 @@ class XophpString__fxt {
|
|||||||
}
|
}
|
||||||
Gftest.Fail("expected failure, but got none: " + character_mask);
|
Gftest.Fail("expected failure, but got none: " + character_mask);
|
||||||
}
|
}
|
||||||
|
public void Test__ltrim(String str, String character_mask, String expd) {
|
||||||
|
Gftest.Eq__str(expd, XophpString_.ltrim(str, character_mask));
|
||||||
|
}
|
||||||
|
public void Test__trim(String str, String character_mask, String expd) {
|
||||||
|
Gftest.Eq__str(expd, XophpString_.trim(str, character_mask));
|
||||||
|
}
|
||||||
public void Test__ord(String str, int expd) {
|
public void Test__ord(String str, int expd) {
|
||||||
Gftest.Eq__int(expd, XophpString_.ord(str));
|
Gftest.Eq__int(expd, XophpString_.ord(str));
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
|
|||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected XophpArray childExpansionCache;
|
public XophpArray childExpansionCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new preprocessor frame.
|
* Construct a new preprocessor frame.
|
||||||
@ -64,7 +64,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
|
|||||||
this.preprocessor = preprocessor;
|
this.preprocessor = preprocessor;
|
||||||
this.parser = preprocessor.Parser();
|
this.parser = preprocessor.Parser();
|
||||||
this.title = this.parser.mTitle;
|
this.title = this.parser.mTitle;
|
||||||
this.titleCache = XophpArray.New().Add(XophpObject_.is_true(this.title) ? this.title.getPrefixedDBkeyStr() : XophpString_.Null);
|
this.titleCache = XophpArray.New().Add(XophpObject_.is_true(this.title) ? this.title.getPrefixedDBkeyStr() : XophpString_.False);
|
||||||
this.loopCheckHash = XophpArray.New();
|
this.loopCheckHash = XophpArray.New();
|
||||||
this.depth = 0;
|
this.depth = 0;
|
||||||
this.childExpansionCache = XophpArray.New();
|
this.childExpansionCache = XophpArray.New();
|
||||||
@ -214,7 +214,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object newIterator = XophpObject_.False;
|
Object newIterator = XophpObject_.False;
|
||||||
String contextName = XophpString_.Null;
|
String contextName = XophpString_.False;
|
||||||
XophpArray contextChildren = XophpArray.False;
|
XophpArray contextChildren = XophpArray.False;
|
||||||
|
|
||||||
if (!XophpObject_.is_true(contextNode)) {
|
if (!XophpObject_.is_true(contextNode)) {
|
||||||
@ -523,7 +523,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
|
|||||||
return this.title.getPrefixedDBkeyStr();
|
return this.title.getPrefixedDBkeyStr();
|
||||||
} else {
|
} else {
|
||||||
// return isset( $this->titleCache[$level] ) ? $this->titleCache[$level] : false;
|
// return isset( $this->titleCache[$level] ) ? $this->titleCache[$level] : false;
|
||||||
return this.titleCache.count() > 0 ? ((String)this.titleCache.Get_at(0)) : XophpString_.Null;
|
return this.titleCache.count() > 0 ? ((String)this.titleCache.Get_at(0)) : XophpString_.False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,7 +562,7 @@ class XomwPPFrame_Hash extends XomwPPFrame { /**
|
|||||||
* @return boolean Always false in this implementation.
|
* @return boolean Always false in this implementation.
|
||||||
*/
|
*/
|
||||||
@Override public String getArgument(String name) {
|
@Override public String getArgument(String name) {
|
||||||
return XophpString_.Null;
|
return XophpString_.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,181 +18,188 @@ package gplx.xowa.mediawiki.includes.parsers.preprocessors; import gplx.*; impor
|
|||||||
// * Expansion frame with template arguments
|
// * Expansion frame with template arguments
|
||||||
// * @ingroup Parser
|
// * @ingroup Parser
|
||||||
// */
|
// */
|
||||||
//// @codingStandardsIgnoreStart Squiz.Classes.ValidClassName.NotCamelCaps
|
class XomwPPTemplateFrame_Hash extends XomwPPFrame_Hash { public XophpArray numberedArgs, namedArgs;
|
||||||
// extends PPFrame_Hash
|
public XomwPPFrame_Hash parent;
|
||||||
class XomwPPTemplateFrame_Hash extends XomwPPFrame { // // @codingStandardsIgnoreEnd
|
public XophpArray numberedExpansionCache, namedExpansionCache;
|
||||||
//
|
|
||||||
// public $numberedArgs, $namedArgs, $parent;
|
/**
|
||||||
// public $numberedExpansionCache, $namedExpansionCache;
|
* @param Preprocessor $preprocessor
|
||||||
//
|
* @param boolean|PPFrame $parent
|
||||||
// /**
|
* @param array $numberedArgs
|
||||||
// * @param Preprocessor $preprocessor
|
* @param array $namedArgs
|
||||||
// * @param boolean|PPFrame $parent
|
* @param boolean|Title $title
|
||||||
// * @param array $numberedArgs
|
*/
|
||||||
// * @param array $namedArgs
|
// parent = false, numberedArgs = [], namedArgs = []; titl = false
|
||||||
// * @param boolean|Title $title
|
public XomwPPTemplateFrame_Hash(XomwPreprocessor preprocessor, XomwPPFrame_Hash parent, XophpArray numberedArgs,
|
||||||
// */
|
XophpArray namedArgs, XomwTitle title
|
||||||
// public function __construct($preprocessor, $parent = false, $numberedArgs = [],
|
) {super(preprocessor);
|
||||||
// $namedArgs = [], $title = false
|
this.parent = parent;
|
||||||
// ) {
|
this.numberedArgs = numberedArgs;
|
||||||
// parent::__construct($preprocessor);
|
this.namedArgs = namedArgs;
|
||||||
//
|
this.title = title;
|
||||||
// this.parent = $parent;
|
String pdbk = title != null ? title.getPrefixedDBkeyStr() : XophpString_.False;
|
||||||
// this.numberedArgs = $numberedArgs;
|
this.titleCache = parent.titleCache;
|
||||||
// this.namedArgs = $namedArgs;
|
this.titleCache.Add(pdbk);
|
||||||
// this.title = $title;
|
this.loopCheckHash = /*clone*/ parent.loopCheckHash;
|
||||||
// $pdbk = $title ? $title.getPrefixedDBkey() : false;
|
if (pdbk != XophpString_.False) {
|
||||||
// this.titleCache = $parent.titleCache;
|
this.loopCheckHash.Add(pdbk, true);
|
||||||
// this.titleCache[] = $pdbk;
|
}
|
||||||
// this.loopCheckHash = /*clone*/ $parent.loopCheckHash;
|
this.depth = parent.depth + 1;
|
||||||
// if ($pdbk !== false) {
|
this.numberedExpansionCache = this.namedExpansionCache = XophpArray.New();
|
||||||
// this.loopCheckHash[$pdbk] = true;
|
}
|
||||||
// }
|
|
||||||
// this.depth = $parent.depth + 1;
|
@Override public String toString() {
|
||||||
// this.numberedExpansionCache = this.namedExpansionCache = [];
|
String s = "tplframe{";
|
||||||
// }
|
boolean first = true;
|
||||||
//
|
XophpArray args = XophpArray_.array_add(this.numberedArgs, this.namedArgs);
|
||||||
// public function __toString() {
|
int args_len = args.count();
|
||||||
// $s = 'tplframe{';
|
for (int i = 0; i < args_len; i++) {
|
||||||
// $first = true;
|
XophpArrayItm itm = args.Get_at_itm(i);
|
||||||
// $args = this.numberedArgs + this.namedArgs;
|
if (first) {
|
||||||
// for each ($args as $name => $value) {
|
first = false;
|
||||||
// if ($first) {
|
} else {
|
||||||
// $first = false;
|
s += ", ";
|
||||||
// } else {
|
}
|
||||||
// $s .= ', ';
|
s += "\"" + itm.Key() + "\":\"" +
|
||||||
// }
|
XophpString_.str_replace("\"", "\\\"", itm.Val().toString()) + "\"";
|
||||||
// $s .= "\"$name\":\"" .
|
}
|
||||||
// str_replace('"', '\\"', $value.__toString()) . '"';
|
s += "}";
|
||||||
// }
|
return s;
|
||||||
// $s .= '}';
|
}
|
||||||
// return $s;
|
|
||||||
// }
|
/**
|
||||||
//
|
* @throws MWException
|
||||||
// /**
|
* @param String|int $key
|
||||||
// * @throws MWException
|
* @param String|PPNode $root
|
||||||
// * @param String|int $key
|
* @param int $flags
|
||||||
// * @param String|PPNode $root
|
* @return String
|
||||||
// * @param int $flags
|
*/
|
||||||
// * @return String
|
@Override public String cachedExpand(String key, XomwPPNode root, int flags) { // flags = 0
|
||||||
// */
|
if (XophpObject_.isset_obj(this.parent.childExpansionCache.Get_by(key))) {
|
||||||
// public function cachedExpand($key, $root, $flags = 0) {
|
return this.parent.childExpansionCache.Get_by_str(key);
|
||||||
// if (isset(this.parent.childExpansionCache[$key])) {
|
}
|
||||||
// return this.parent.childExpansionCache[$key];
|
String retval = this.expand(root, flags);
|
||||||
// }
|
if (!this.isVolatile()) {
|
||||||
// $retval = this.expand($root, $flags);
|
this.parent.childExpansionCache.Set(key, retval);
|
||||||
// if (!this.isVolatile()) {
|
}
|
||||||
// this.parent.childExpansionCache[$key] = $retval;
|
return retval;
|
||||||
// }
|
}
|
||||||
// return $retval;
|
|
||||||
// }
|
/**
|
||||||
//
|
* Returns true if there are no arguments in this frame
|
||||||
// /**
|
*
|
||||||
// * Returns true if there are no arguments in this frame
|
* @return boolean
|
||||||
// *
|
*/
|
||||||
// * @return boolean
|
@Override public boolean isEmpty() {
|
||||||
// */
|
return !this.numberedArgs.count_bool() && !this.namedArgs.count_bool();
|
||||||
// public function isEmpty() {
|
}
|
||||||
// return !count(this.numberedArgs) && !count(this.namedArgs);
|
|
||||||
// }
|
/**
|
||||||
//
|
* @return array
|
||||||
// /**
|
*/
|
||||||
// * @return array
|
@Override public XophpArray getArguments() {
|
||||||
// */
|
XophpArray arguments = XophpArray.New();
|
||||||
// public function getArguments() {
|
XophpArray merged = XophpArray_.array_merge(
|
||||||
// $arguments = [];
|
XophpArray_.array_keys(this.numberedArgs),
|
||||||
// for each (array_merge(
|
XophpArray_.array_keys(this.namedArgs));
|
||||||
// array_keys(this.numberedArgs),
|
int merged_len = merged.count();
|
||||||
// array_keys(this.namedArgs)) as $key) {
|
for (int i = 0; i < merged_len; i++) {
|
||||||
// $arguments[$key] = this.getArgument($key);
|
String key = merged.Get_at_str(i);
|
||||||
// }
|
arguments.Set(key, this.getArgument(key));
|
||||||
// return $arguments;
|
}
|
||||||
// }
|
return arguments;
|
||||||
//
|
}
|
||||||
// /**
|
|
||||||
// * @return array
|
/**
|
||||||
// */
|
* @return array
|
||||||
// public function getNumberedArguments() {
|
*/
|
||||||
// $arguments = [];
|
@Override public XophpArray getNumberedArguments() {
|
||||||
// for each (array_keys(this.numberedArgs) as $key) {
|
XophpArray arguments = XophpArray.New();
|
||||||
// $arguments[$key] = this.getArgument($key);
|
XophpArray temp = XophpArray_.array_keys(this.numberedArgs);
|
||||||
// }
|
int temp_len = temp.count();
|
||||||
// return $arguments;
|
for (int i = 0; i < temp_len; i++) {
|
||||||
// }
|
String key = temp.Get_at_str(i);
|
||||||
//
|
arguments.Set(key, this.getArgument(key));
|
||||||
// /**
|
}
|
||||||
// * @return array
|
return arguments;
|
||||||
// */
|
}
|
||||||
// public function getNamedArguments() {
|
|
||||||
// $arguments = [];
|
/**
|
||||||
// for each (array_keys(this.namedArgs) as $key) {
|
* @return array
|
||||||
// $arguments[$key] = this.getArgument($key);
|
*/
|
||||||
// }
|
@Override public XophpArray getNamedArguments() {
|
||||||
// return $arguments;
|
XophpArray arguments = XophpArray.New();
|
||||||
// }
|
XophpArray temp = XophpArray_.array_keys(this.namedArgs);
|
||||||
//
|
int temp_len = temp.count();
|
||||||
// /**
|
for (int i = 0; i < temp_len; i++) {
|
||||||
// * @param int $index
|
String key = temp.Get_at_str(i);
|
||||||
// * @return String|boolean
|
arguments.Set(key, this.getArgument(key));
|
||||||
// */
|
}
|
||||||
// public function getNumberedArgument($index) {
|
return arguments;
|
||||||
// if (!isset(this.numberedArgs[$index])) {
|
}
|
||||||
// return false;
|
|
||||||
// }
|
/**
|
||||||
// if (!isset(this.numberedExpansionCache[$index])) {
|
* @param int $index
|
||||||
// # No trimming for unnamed arguments
|
* @return String|boolean
|
||||||
// this.numberedExpansionCache[$index] = this.parent.expand(
|
*/
|
||||||
// this.numberedArgs[$index],
|
public String getNumberedArgument(int index) {
|
||||||
// PPFrame::STRIP_COMMENTS
|
if (!XophpObject_.isset_obj(this.numberedArgs.Get_at(index))) {
|
||||||
// );
|
return XophpString_.False;
|
||||||
// }
|
}
|
||||||
// return this.numberedExpansionCache[$index];
|
if (!XophpObject_.isset_obj(this.numberedExpansionCache.Get_at(index))) {
|
||||||
// }
|
// No trimming for unnamed arguments
|
||||||
//
|
this.numberedExpansionCache.Set(index, this.parent.expand(
|
||||||
// /**
|
(XomwPPNode)this.numberedArgs.Get_at(index),
|
||||||
// * @param String $name
|
XomwPPFrame.STRIP_COMMENTS
|
||||||
// * @return String|boolean
|
));
|
||||||
// */
|
}
|
||||||
// public function getNamedArgument($name) {
|
return this.numberedExpansionCache.Get_at_str(index);
|
||||||
// if (!isset(this.namedArgs[$name])) {
|
}
|
||||||
// return false;
|
|
||||||
// }
|
/**
|
||||||
// if (!isset(this.namedExpansionCache[$name])) {
|
* @param String $name
|
||||||
// # Trim named arguments post-expand, for backwards compatibility
|
* @return String|boolean
|
||||||
// this.namedExpansionCache[$name] = trim(
|
*/
|
||||||
// this.parent.expand(this.namedArgs[$name], PPFrame::STRIP_COMMENTS));
|
public String getNamedArgument(String name) {
|
||||||
// }
|
if (!XophpObject_.isset_obj(this.namedArgs.Get_by_str(name))) {
|
||||||
// return this.namedExpansionCache[$name];
|
return XophpString_.False;
|
||||||
// }
|
}
|
||||||
//
|
if (!XophpObject_.isset_obj(this.namedExpansionCache.Get_by_str(name))) {
|
||||||
// /**
|
// Trim named arguments post-expand, for backwards compatibility
|
||||||
// * @param int|String $name
|
this.namedExpansionCache.Set(name, XophpString_.trim(
|
||||||
// * @return String|boolean
|
this.parent.expand((XomwPPNode)this.namedArgs.Get_by(name), XomwPPFrame.STRIP_COMMENTS)));
|
||||||
// */
|
}
|
||||||
// public function getArgument($name) {
|
return this.namedExpansionCache.Get_by_str(name);
|
||||||
// $text = this.getNumberedArgument($name);
|
}
|
||||||
// if ($text === false) {
|
|
||||||
// $text = this.getNamedArgument($name);
|
/**
|
||||||
// }
|
* @param int|String $name
|
||||||
// return $text;
|
* @return String|boolean
|
||||||
// }
|
*/
|
||||||
//
|
public String getArgument(Object name) {
|
||||||
// /**
|
String text = this.getNumberedArgument((int)name);
|
||||||
// * Return true if the frame is a template frame
|
if (String_.Eq(text, XophpString_.False)) {
|
||||||
// *
|
text = this.getNamedArgument((String)name);
|
||||||
// * @return boolean
|
}
|
||||||
// */
|
return text;
|
||||||
// public function isTemplate() {
|
}
|
||||||
// return true;
|
|
||||||
// }
|
/**
|
||||||
//
|
* Return true if the frame is a template frame
|
||||||
// public function setVolatile($flag = true) {
|
*
|
||||||
// parent::setVolatile($flag);
|
* @return boolean
|
||||||
// this.parent.setVolatile($flag);
|
*/
|
||||||
// }
|
@Override public boolean isTemplate() {
|
||||||
//
|
return true;
|
||||||
// public function setTTL($ttl) {
|
}
|
||||||
// parent::setTTL($ttl);
|
|
||||||
// this.parent.setTTL($ttl);
|
@Override public void setVolatile(boolean flag) { // flag = true
|
||||||
// }
|
super.setVolatile(flag);
|
||||||
|
this.parent.setVolatile(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setTTL(int ttl) {
|
||||||
|
super.setTTL(ttl);
|
||||||
|
this.parent.setTTL(ttl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user