2020-05-01 13:01:40 +00:00
|
|
|
/*
|
|
|
|
XOWA: the XOWA Offline Wiki Application
|
2020-05-07 12:58:15 +00:00
|
|
|
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
2020-05-01 13:01:40 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2020-05-07 12:58:15 +00:00
|
|
|
package gplx.xowa.mediawiki;
|
|
|
|
|
|
|
|
import gplx.Bool_;
|
|
|
|
import gplx.Bry_bfr;
|
|
|
|
import gplx.Bry_bfr_;
|
|
|
|
import gplx.Char_;
|
|
|
|
import gplx.Int_;
|
|
|
|
import gplx.Object_;
|
|
|
|
import gplx.Ordered_hash;
|
|
|
|
import gplx.Ordered_hash_;
|
|
|
|
import gplx.Type_;
|
2019-07-12 03:17:06 +00:00
|
|
|
import gplx.core.brys.*;
|
2020-05-07 12:58:15 +00:00
|
|
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
|
|
// REF.PHP: https://www.php.net/manual/en/language.types.array.php
|
2020-01-05 13:52:37 +00:00
|
|
|
// Will also will have static functions but "array_" will be stripped; REF.PHP: https://www.php.net/manual/en/ref.array.php
|
2020-05-07 12:58:15 +00:00
|
|
|
public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|
|
|
private final Ordered_hash hash = Ordered_hash_.New();
|
|
|
|
private int newMemberIdx;
|
|
|
|
|
|
|
|
public void Clear() {
|
|
|
|
hash.Clear();
|
|
|
|
newMemberIdx = 0;
|
|
|
|
internalPointerIndex = 0;
|
|
|
|
}
|
2020-04-03 10:39:35 +00:00
|
|
|
public int Len() {return hash.Len();}
|
2020-01-05 13:52:37 +00:00
|
|
|
public int count() {return hash.Len();}
|
|
|
|
public boolean count_bool() {return hash.Len() > 0;}
|
|
|
|
public boolean isset(String key) {return hash.Has(key);}
|
|
|
|
public boolean isset(int idx) {return idx >= 0 && idx < hash.Count();}
|
|
|
|
public boolean in_array(String v) {return Has(v);}
|
|
|
|
public Object end() {
|
|
|
|
int len = hash.Len();
|
|
|
|
return len == 0 ? null : ((XophpArrayItm)hash.Get_at(len - 1)).Val();
|
|
|
|
}
|
2020-04-09 12:10:22 +00:00
|
|
|
public boolean Eq_to_new() {return hash.Count() == 0;}// same as "array === []"
|
2020-01-05 13:52:37 +00:00
|
|
|
public void unset(int key) {unset(Int_.To_str(key));}
|
|
|
|
public void unset(String key) {
|
|
|
|
hash.Del(key);
|
|
|
|
}
|
|
|
|
public Object pop() {// "array_pop"
|
|
|
|
int pos = this.count() - 1;
|
|
|
|
if (pos < 0) return null;
|
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_at(pos);
|
|
|
|
this.Del_at(pos);
|
|
|
|
return itm.Val();
|
|
|
|
}
|
|
|
|
// REF.PHP: https://www.php.net/manual/en/function.array-values.php
|
|
|
|
public XophpArray values() {
|
|
|
|
XophpArray rv = new XophpArray();
|
|
|
|
int len = this.count();
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
rv.Add(i, this.Get_at(i));
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
2019-07-12 03:17:06 +00:00
|
|
|
public XophpArray Add(Object val) {
|
2020-05-07 12:58:15 +00:00
|
|
|
int key = newMemberIdx++;
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_int(key, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
public XophpArray Add(int key, Object val) {
|
2020-05-07 12:58:15 +00:00
|
|
|
newMemberIdx = key + 1;
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_int(key, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
public XophpArray Add(double key, Object val) {
|
|
|
|
int key_as_int = (int)key;
|
2020-05-07 12:58:15 +00:00
|
|
|
newMemberIdx = key_as_int + 1;
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_int(key_as_int, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
public XophpArray Add(boolean key, Object val) {
|
|
|
|
int key_as_int = key ? 1 : 0;
|
2020-05-07 12:58:15 +00:00
|
|
|
newMemberIdx = key_as_int + 1;
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_int(key_as_int, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
public XophpArray Add(String key, Object val) {
|
|
|
|
int key_as_int = Int_.Parse_or(key, Int_.Min_value);
|
|
|
|
if (key_as_int == Int_.Min_value) {
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_str(key, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-07-22 02:09:21 +00:00
|
|
|
Set(XophpArrayItm.New_int(key_as_int, val));
|
2020-05-07 12:58:15 +00:00
|
|
|
newMemberIdx = key_as_int + 1;
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
2020-01-04 09:14:36 +00:00
|
|
|
public XophpArray Add_as_key_and_val_many(String... val) {
|
|
|
|
for (String itm : val) {
|
|
|
|
Add(itm, itm);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
public XophpArray Add_many(Object... val) {
|
|
|
|
for (Object itm : val) {
|
|
|
|
Add(itm);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
2020-04-09 12:10:22 +00:00
|
|
|
public void Concat_str(int i, String s) {
|
|
|
|
this.Set(i, this.Get_at_str(i) + s);
|
|
|
|
}
|
|
|
|
public XophpArray Get_at_ary_or_null(int i) {
|
|
|
|
Object rv = Get_at(i);
|
|
|
|
return Type_.Eq_by_obj(rv, XophpArray.class) ? (XophpArray)rv : null;
|
|
|
|
}
|
2019-07-22 02:09:21 +00:00
|
|
|
public XophpArray Get_at_ary(int i) {return (XophpArray)Get_at(i);}
|
2020-04-09 12:10:22 +00:00
|
|
|
public boolean Get_at_bool(int i) {return Bool_.Cast(Get_at(i));}
|
2019-12-07 13:13:52 +00:00
|
|
|
public int Get_at_int(int i) {return Int_.Cast(Get_at(i));}
|
2020-04-09 12:10:22 +00:00
|
|
|
public String Get_at_str(int i) {return (String)Get_at(i);}
|
2019-07-22 02:09:21 +00:00
|
|
|
public Object Get_at(int i) {
|
|
|
|
if (i < 0 || i >= hash.Len()) return null;
|
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_at(i);
|
|
|
|
return itm == null ? null : itm.Val();
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
2020-01-04 09:14:36 +00:00
|
|
|
public XophpArrayItm Get_at_itm(int i) {
|
|
|
|
if (i < 0 || i >= hash.Len()) return null;
|
|
|
|
return (XophpArrayItm)hash.Get_at(i);
|
|
|
|
}
|
2019-07-12 03:17:06 +00:00
|
|
|
public void Del_at(int i) {
|
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_at(i);
|
|
|
|
if (itm != null) {
|
2019-07-22 02:09:21 +00:00
|
|
|
hash.Del(itm.Key());
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-22 02:09:21 +00:00
|
|
|
public Object Get_by_obj(Object key) {return Get_by(Object_.Xto_str_strict_or_null(key));}
|
|
|
|
public Object Get_by(int key) {return Get_by(Int_.To_str(key));}
|
2020-04-09 12:10:22 +00:00
|
|
|
public boolean Get_by_bool_or(String key, boolean or) {Object rv = this.Get_by(key); return rv == null ? or : Bool_.Cast(rv);}
|
2020-01-04 09:14:36 +00:00
|
|
|
public boolean Get_by_bool(String key) {return Bool_.Cast(this.Get_by(key));}
|
2020-04-09 12:10:22 +00:00
|
|
|
public int Get_by_int_or(String key, int or) {Object rv = this.Get_by(key); return rv == null ? or : Int_.Cast(rv);}
|
2019-12-07 13:13:52 +00:00
|
|
|
public int Get_by_int(String key) {return Int_.Cast(this.Get_by(key));}
|
2020-05-03 13:19:47 +00:00
|
|
|
public XophpArray Xet_by_ary(String key) {
|
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key);
|
|
|
|
if (itm == null) {
|
|
|
|
XophpArray val = new XophpArray();
|
|
|
|
this.Set(key, val);
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (XophpArray)itm.Val();
|
|
|
|
}
|
|
|
|
}
|
2020-04-09 12:10:22 +00:00
|
|
|
public XophpArray Get_by_ary_or(String key, XophpArray or) {Object rv = this.Get_by(key); return rv == null ? or : (XophpArray)rv;}
|
2020-01-04 09:14:36 +00:00
|
|
|
public XophpArray Get_by_ary(String key) {return (XophpArray)this.Get_by(key);}
|
|
|
|
public String Get_by_str(char key) {return (String)this.Get_by(Char_.To_str(key));}
|
2020-04-09 12:10:22 +00:00
|
|
|
public String Get_by_str(int key) {return (String)this.Get_by(Int_.To_str(key));}
|
|
|
|
public String Get_by_str_or(String key, String or) {Object rv = this.Get_by(key); return rv == null ? or : (String)rv;}
|
2020-01-04 09:14:36 +00:00
|
|
|
public String Get_by_str(String key) {return (String)this.Get_by(key);}
|
2019-07-22 02:09:21 +00:00
|
|
|
public Object Get_by(String key) {
|
2019-07-12 03:17:06 +00:00
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key);
|
2020-01-04 09:14:36 +00:00
|
|
|
return itm == null ? null : itm.Val();
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
|
|
|
public void Set(int key, Object val) {
|
2019-07-22 02:09:21 +00:00
|
|
|
this.Set(XophpArrayItm.New_int(key, val));
|
2019-07-12 03:17:06 +00:00
|
|
|
}
|
2020-01-04 09:14:36 +00:00
|
|
|
public void Set(String key, Object val) {
|
|
|
|
this.Set(XophpArrayItm.New_str(key, val));
|
|
|
|
}
|
2019-07-22 02:09:21 +00:00
|
|
|
public boolean Has_obj(Object key) {return Has(Object_.Xto_str_strict_or_null(key));}
|
|
|
|
public boolean Has(String key) {
|
2019-07-12 03:17:06 +00:00
|
|
|
return hash.Has(key);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2019-07-22 02:09:21 +00:00
|
|
|
private void Set(XophpArrayItm itm) {
|
|
|
|
String key = itm.Key();
|
|
|
|
XophpArrayItm cur = (XophpArrayItm)hash.Get_by(key);
|
|
|
|
if (cur == null) {
|
|
|
|
hash.Add(key, itm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cur.Val_(itm.Val());
|
|
|
|
}
|
|
|
|
}
|
2019-12-07 13:13:52 +00:00
|
|
|
public void Itm_str_concat_end(int idx, String v) {
|
|
|
|
String itm = (String)this.Get_at(idx);
|
|
|
|
itm += v;
|
|
|
|
this.Set(idx, itm);
|
|
|
|
}
|
2020-05-04 12:29:37 +00:00
|
|
|
|
2020-01-04 09:14:36 +00:00
|
|
|
public XophpArray Clone() {
|
|
|
|
XophpArray rv = new XophpArray();
|
|
|
|
int len = hash.Len();
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_at(i);
|
|
|
|
rv.Add(itm.Key(), itm.Val());
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
2020-04-09 12:10:22 +00:00
|
|
|
@Override public boolean equals(Object obj) {
|
|
|
|
if (obj == null) return false;
|
|
|
|
if (!Type_.Eq_by_obj(obj, XophpArray.class)) return false;
|
|
|
|
XophpArray comp = (XophpArray)obj;
|
|
|
|
|
|
|
|
// compare lens
|
|
|
|
int this_len = this.Len();
|
|
|
|
int comp_len = comp.Len();
|
|
|
|
if (this_len != comp_len) return false;
|
|
|
|
|
|
|
|
// loop items
|
|
|
|
for (int i = 0; i < this_len; i++) {
|
|
|
|
XophpArrayItm this_itm = this.Get_at_itm(i);
|
|
|
|
XophpArrayItm comp_itm = comp.Get_at_itm(i);
|
|
|
|
if (!Object_.Eq(this_itm, comp_itm))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
@Override public int hashCode() {
|
|
|
|
int rv = 0;
|
|
|
|
int len = this.Len();
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
XophpArrayItm itm = this.Get_at_itm(i);
|
|
|
|
rv = (31 * rv) + itm.hashCode();
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2020-05-07 12:58:15 +00:00
|
|
|
@Override
|
|
|
|
public Iterator iterator() {
|
|
|
|
return new XophpArrayIterator(hash);
|
|
|
|
}
|
|
|
|
class XophpArrayIterator implements Iterator<T> {
|
|
|
|
private final Ordered_hash hash;
|
|
|
|
private int curIdx;
|
|
|
|
private int len;
|
|
|
|
public XophpArrayIterator(Ordered_hash hash) {
|
|
|
|
this.hash = hash;
|
|
|
|
this.len = hash.Len();
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
public boolean hasNext() {
|
|
|
|
return curIdx < len;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public T next() {
|
|
|
|
return (T) hash.Get_at(curIdx++);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void remove() {
|
|
|
|
throw new XophpRuntimeException("remove not supported");
|
|
|
|
}
|
2017-10-24 00:50:50 +00:00
|
|
|
}
|
2020-05-04 12:29:37 +00:00
|
|
|
|
|
|
|
// REF.PHP:https://www.php.net/manual/en/function.reset.php
|
|
|
|
private int internalPointerIndex = 0;
|
|
|
|
private Object internalPointerAdd(int v) {
|
|
|
|
internalPointerIndex += v;
|
|
|
|
return internalPointerGetOrNull();
|
|
|
|
}
|
|
|
|
private Object internalPointerReset() {
|
|
|
|
internalPointerIndex = 0;
|
|
|
|
return internalPointerGetOrNull();
|
|
|
|
}
|
|
|
|
private Object internalPointerGetOrNull() {return hash.Len() == 0 ? null : this.Get_at(internalPointerIndex);}
|
|
|
|
public static Object reset(XophpArray array) {return array.internalPointerReset();}
|
|
|
|
public static Object current(XophpArray array) {return array.internalPointerGetOrNull();}
|
|
|
|
public static Object next(XophpArray array) {
|
|
|
|
return array.internalPointerAdd(1);
|
|
|
|
}
|
|
|
|
|
2020-05-07 12:58:15 +00:00
|
|
|
public static boolean is_array(Object val) {
|
|
|
|
return Type_.Eq_by_obj(val, XophpArray.class);
|
|
|
|
}
|
|
|
|
public static final XophpArray False = null; // handles code like "if ($var === false)" where var is an Object;
|
|
|
|
public static XophpArray New(Object... vals) {
|
|
|
|
XophpArray rv = new XophpArray();
|
|
|
|
for (Object val : vals)
|
|
|
|
rv.Add(val);
|
|
|
|
return rv;
|
|
|
|
}
|
2017-10-24 00:50:50 +00:00
|
|
|
}
|