mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.9.1.1
This commit is contained in:
@@ -164,6 +164,10 @@ public class Scrib_invoke_func_fxt {
|
||||
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
|
||||
return (KeyVal[])actl[0].Val();
|
||||
}
|
||||
public Object Test_scrib_proc_rv_as_obj(Scrib_lib lib, String proc_name, Object[] args) {
|
||||
KeyVal[] actl = Test_scrib_proc_rv(lib, proc_name, Scrib_kv_utl_.base1_many_(args));
|
||||
return actl[0].Val();
|
||||
}
|
||||
private KeyVal[] Test_scrib_proc_rv(Scrib_lib lib, String proc_name, KeyVal[] args) {
|
||||
Scrib_proc proc = lib.Procs().Get_by_key(proc_name);
|
||||
Scrib_proc_rslt proc_rslt = new Scrib_proc_rslt();
|
||||
|
||||
@@ -21,9 +21,10 @@ public class Scrib_proc_args {
|
||||
public Scrib_proc_args(KeyVal[] v) {Init(v);}
|
||||
public int Len() {return ary_len;}
|
||||
public KeyVal[] Ary() {return ary;}
|
||||
public boolean Pull_bool(int i) {Object rv = Get_or_fail(i); return Bool_.cast(rv);}
|
||||
public String Pull_str(int i) {Object rv = Get_or_fail(i); return String_.cast(rv);}
|
||||
public byte[] Pull_bry(int i) {Object rv = Get_or_fail(i); return Bry_.new_u8(String_.cast(rv));}
|
||||
public boolean Pull_bool(int i) {return Bool_.cast(Get_or_fail(i));}
|
||||
public String Pull_str(int i) {return String_.cast(Get_or_fail(i));}
|
||||
public byte[] Pull_bry(int i) {return Bry_.new_u8(String_.cast(Get_or_fail(i)));}
|
||||
public KeyVal[] Pull_kv_ary(int i) {return (KeyVal[])Get_or_fail(i);}
|
||||
public int Pull_int(int i) {Object rv = Get_or_fail(i);
|
||||
try {return Int_.coerce_(rv);} // coerce to handle "1" and 1; will still fail if "abc" is passed
|
||||
catch (Exception e) {
|
||||
@@ -43,6 +44,7 @@ public class Scrib_proc_args {
|
||||
}
|
||||
}
|
||||
}
|
||||
public Object Pull_obj(int i) {return Get_or_fail(i);}
|
||||
public String Cast_str_or_null(int i) {Object rv = Get_or_null(i); return rv == null ? null : String_.cast (rv);}
|
||||
public byte[] Cast_bry_or_null(int i) {Object rv = Get_or_null(i); return rv == null ? null : Bry_.new_u8(String_.cast (rv));} // NOTE: cast is deliberate; Scrib call checkType whi
|
||||
public byte[] Cast_bry_or_empty(int i) {Object rv = Get_or_null(i); return rv == null ? Bry_.Empty : Bry_.new_u8(String_.cast (rv));}
|
||||
@@ -54,10 +56,6 @@ public class Scrib_proc_args {
|
||||
public String Xstr_str_or_null(int i) {Object rv = Get_or_null(i); return rv == null ? null : Object_.Xto_str_loose_or(rv, null);} // NOTE: Modules can throw exceptions in which return value is nothing; do not fail; return ""; EX: -logy; DATE:2013-10-14
|
||||
public byte[] Xstr_bry_or_null(int i) {Object rv = Get_or_null(i); return rv == null ? null : Bry_.new_u8(Object_.Xto_str_loose_or(rv, null));}
|
||||
public KeyVal[] Cast_kv_ary_or_null(int i) {Object rv = Get_or_null(i); return rv == null ? null : (KeyVal[])rv;}
|
||||
public KeyVal[] Pull_kv_ary(int i) {
|
||||
Object rv = Get_or_fail(i);
|
||||
return (KeyVal[])rv;
|
||||
}
|
||||
public byte[][] Cast_params_as_bry_ary_or_rest_of_ary(int params_idx) { // PAGE:ru.w:Ленин,_Владимир_Ильич; DATE:2014-07-01 MW:LanguageLibrary.php|ConvertPlural: if (is_array($args[0])) $args = $args[0]; $forms = array_values(array_map('strval', $args));
|
||||
if (params_idx < 0 || params_idx >= ary_len) return Bry_.Ary_empty;
|
||||
Object o = ary[params_idx].Val();
|
||||
|
||||
@@ -59,7 +59,7 @@ class Gfo_fld_crt implements Criteria {
|
||||
}
|
||||
public void Val_from_args(Hash_adp args) {throw Err_.new_unimplemented();}
|
||||
public void Val_as_obj_(Object v) {throw Err_.new_unimplemented();}
|
||||
public String To_str() {return String_.Concat(Byte_.Xto_str(fld_idx), " ", crt.To_str());}
|
||||
public String To_str() {return String_.Concat(Byte_.To_str(fld_idx), " ", crt.To_str());}
|
||||
public static Gfo_fld_crt new_(byte fld_idx, Criteria crt) {
|
||||
Gfo_fld_crt rv = new Gfo_fld_crt();
|
||||
rv.fld_idx = fld_idx; rv.crt = crt;
|
||||
|
||||
@@ -27,8 +27,9 @@ class Kv_ary_utl {
|
||||
}
|
||||
public static KeyVal[] new_kvs(KeyVal... vals) {return vals;}
|
||||
public static String Ary_to_str(Json_wtr wtr, KeyVal[] ary) {
|
||||
wtr.Doc_nde_bgn();
|
||||
Ary_to_str(wtr, 0, ary);
|
||||
return wtr.To_str_and_clear();
|
||||
return wtr.Doc_nde_end().To_str_and_clear();
|
||||
}
|
||||
private static void Ary_to_str(Json_wtr wtr, int indent, KeyVal[] ary) {
|
||||
int len = ary.length;
|
||||
@@ -44,7 +45,7 @@ class Kv_ary_utl {
|
||||
if (Type_adp_.Eq(val_type, KeyVal[].class))
|
||||
Ary_to_str__nde(wtr, indent, itm.Key(), (KeyVal[])itm.Val());
|
||||
else if (Type_adp_.Is_array(val_type))
|
||||
Ary_to_str__ary(wtr, indent, itm.Key(), Array_.cast(itm.Val()));
|
||||
Ary_to_str__ary(wtr, indent, itm.Key(), Array_.cast(val));
|
||||
else
|
||||
throw Err_.new_unhandled(type_tid);
|
||||
}
|
||||
@@ -70,7 +71,7 @@ class Kv_ary_utl {
|
||||
if (itm_type_tid == Type_adp_.Tid__obj) {
|
||||
if (Type_adp_.Eq(itm_type, KeyVal.class))
|
||||
Ary_to_str__itm(wtr, indent + 1, (KeyVal)itm);
|
||||
if (Type_adp_.Is_array(itm_type))
|
||||
else if (Type_adp_.Is_array(itm_type))
|
||||
Ary_to_str__ary_itms(wtr, indent + 1, Array_.cast(itm));
|
||||
else
|
||||
throw Err_.new_unhandled(itm_type);
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||
public class Scrib_lib_text implements Scrib_lib {
|
||||
private final Scrib_lib_text__json_util json_util = new Scrib_lib_text__json_util();
|
||||
private final Scrib_lib_text__reindex_data reindex_data = new Scrib_lib_text__reindex_data();
|
||||
public Scrib_lib_text(Scrib_core core) {this.core = core;} private Scrib_core core;
|
||||
public Scrib_lua_mod Mod() {return mod;} private Scrib_lua_mod mod;
|
||||
public Scrib_lib Init() {procs.Init_by_lib(this, Proc_names); return this;}
|
||||
@@ -27,7 +28,7 @@ public class Scrib_lib_text implements Scrib_lib {
|
||||
notify_wiki_changed_fnc = mod.Fncs_get_by_key("notify_wiki_changed");
|
||||
return mod;
|
||||
} private Scrib_lua_proc notify_wiki_changed_fnc;
|
||||
public Scrib_proc_mgr Procs() {return procs;} private Scrib_proc_mgr procs = new Scrib_proc_mgr();
|
||||
public Scrib_proc_mgr Procs() {return procs;} private final Scrib_proc_mgr procs = new Scrib_proc_mgr();
|
||||
public boolean Procs_exec(int key, Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||
switch (key) {
|
||||
case Proc_unstrip: return Unstrip(args, rslt);
|
||||
@@ -51,14 +52,55 @@ public class Scrib_lib_text implements Scrib_lib {
|
||||
if (Html_entity_ == null) Html_entity_ = Scrib_lib_text_html_entities.new_();
|
||||
return rslt.Init_obj(Html_entity_);
|
||||
} private static KeyVal[] Html_entity_;
|
||||
// public boolean JsonEncode(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||
// Object itm = args.Pull_obj(0);
|
||||
// Class<?> itm_type = itm.getClass();
|
||||
// KeyVal[] itm_as_kvy = null;
|
||||
// Object itm_as_ary = null;
|
||||
// if (Type_adp_.Eq(itm_type, typeof(KeyVal[]))) itm_as_kvy = (KeyVal[])itm;
|
||||
// else if (Type_adp_.Is_array(itm_type)) itm_as_ary = Array_.cast(itm);
|
||||
// int flags = args.Cast_int_or(1, 0);
|
||||
// if (itm_as_kvy != null && !Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__preserve_keys))
|
||||
// itm_as_kvy = json_util.Reindex_arrays(itm_as_kvy, true);
|
||||
// byte[] rv = null;
|
||||
// if (itm_as_kvy != null)
|
||||
// rv = json_util.Encode_as_nde(itm_as_kvy, flags & Scrib_lib_text__json_util.Flag__pretty, Scrib_lib_text__json_util.Skip__all);
|
||||
// else if (itm_as_ary != null)
|
||||
// rv = json_util.Encode_as_ary(itm_as_ary, flags & Scrib_lib_text__json_util.Flag__pretty, Scrib_lib_text__json_util.Skip__all);;
|
||||
// if (rv == null) throw Err_.new_("scribunto", "mw.text.jsonEncode: Unable to encode value");
|
||||
// return rslt.Init_obj(rv);
|
||||
// }
|
||||
public boolean JsonEncode(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||
KeyVal[] kv_ary = args.Pull_kv_ary(0);
|
||||
Object itm = args.Pull_obj(0);
|
||||
Class<?> itm_type = itm.getClass();
|
||||
KeyVal[] itm_as_kvy = null;
|
||||
Object itm_as_ary = null;
|
||||
if (Type_adp_.Eq(itm_type, KeyVal[].class)) itm_as_kvy = (KeyVal[])itm;
|
||||
else if (Type_adp_.Is_array(itm_type)) itm_as_ary = Array_.cast(itm);
|
||||
int flags = args.Cast_int_or(1, 0);
|
||||
if (!Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__preserve_keys))
|
||||
kv_ary = json_util.Reindex_arrays(kv_ary, true);
|
||||
byte[] rv = json_util.Encode(kv_ary, flags & Scrib_lib_text__json_util.Flag__pretty, Scrib_lib_text__json_util.Skip__all);
|
||||
if (rv == null) throw Err_.new_("scribunto", "mw.text.jsonEncode: Unable to encode value");
|
||||
return rslt.Init_obj(rv);
|
||||
synchronized (reindex_data) {
|
||||
if ( itm_as_kvy != null
|
||||
&& itm_as_kvy.length > 0
|
||||
&& !Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__preserve_keys)
|
||||
) {
|
||||
json_util.Reindex_arrays(reindex_data, itm_as_kvy, true);
|
||||
if (reindex_data.Rv_is_kvy()) {
|
||||
itm_as_kvy = reindex_data.Rv_as_kvy();
|
||||
itm_as_ary = null;
|
||||
}
|
||||
else {
|
||||
itm_as_ary = reindex_data.Rv_as_ary();
|
||||
itm_as_kvy = null;
|
||||
}
|
||||
}
|
||||
byte[] rv = null;
|
||||
if (itm_as_kvy != null)
|
||||
rv = json_util.Encode_as_nde(itm_as_kvy, flags & Scrib_lib_text__json_util.Flag__pretty, Scrib_lib_text__json_util.Skip__all);
|
||||
else
|
||||
rv = json_util.Encode_as_ary(itm_as_ary, flags & Scrib_lib_text__json_util.Flag__pretty, Scrib_lib_text__json_util.Skip__all);
|
||||
if (rv == null) throw Err_.new_("scribunto", "mw.text.jsonEncode: Unable to encode value");
|
||||
return rslt.Init_obj(rv);
|
||||
}
|
||||
}
|
||||
public boolean JsonDecode(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||
byte[] json = args.Pull_bry(0);
|
||||
@@ -66,11 +108,19 @@ public class Scrib_lib_text implements Scrib_lib {
|
||||
int opts = Scrib_lib_text__json_util.Opt__force_assoc;
|
||||
if (Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__try_fixing))
|
||||
opts = Enm_.Add_int(opts, Scrib_lib_text__json_util.Flag__try_fixing);
|
||||
KeyVal[] rv = json_util.Decode(core.App().Utl__json_parser(), json, opts);
|
||||
if (rv == null) throw Err_.new_("scribunto", "mw.text.jsonEncode: Unable to decode String " + String_.new_u8(json));
|
||||
if (!(Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__preserve_keys)))
|
||||
rv = json_util.Reindex_arrays(rv, false);
|
||||
return rslt.Init_obj(rv);
|
||||
synchronized (procs) {
|
||||
byte rv_tid = json_util.Decode(core.App().Utl__json_parser(), json, opts);
|
||||
if (rv_tid == Bool_.__byte) throw Err_.new_("scribunto", "mw.text.jsonEncode: Unable to decode String " + String_.new_u8(json));
|
||||
if (rv_tid == Bool_.Y_byte && !(Enm_.Has_int(flags, Scrib_lib_text__json_util.Flag__preserve_keys))) {
|
||||
KeyVal[] rv_as_kvy = (KeyVal[])json_util.Decode_rslt_as_nde();
|
||||
synchronized (reindex_data) {
|
||||
json_util.Reindex_arrays(reindex_data, rv_as_kvy, false);
|
||||
return rslt.Init_obj(reindex_data.Rv_is_kvy() ? reindex_data.Rv_as_kvy() : reindex_data.Rv_as_ary());
|
||||
}
|
||||
}
|
||||
else
|
||||
return rslt.Init_obj(json_util.Decode_rslt_as_ary());
|
||||
}
|
||||
}
|
||||
public void Notify_wiki_changed() {if (notify_wiki_changed_fnc != null) core.Interpreter().CallFunction(notify_wiki_changed_fnc.Id(), KeyVal_.Ary_empty);}
|
||||
public boolean Init_text_for_wiki(Scrib_proc_args args, Scrib_proc_rslt rslt) {
|
||||
@@ -82,7 +132,6 @@ public class Scrib_lib_text implements Scrib_lib {
|
||||
rv[3] = KeyVal_.new_("nowiki_protocols", KeyVal_.Ary_empty); // NOTE: code implemented, but waiting for it to be used; DATE:2014-03-20
|
||||
return rslt.Init_obj(rv);
|
||||
}
|
||||
public void Init_for_tests() {json_util.Init_for_tests();}
|
||||
private String Init_lib_text_get_msg(Xow_msg_mgr msg_mgr, String msg_key) {
|
||||
return String_.new_u8(msg_mgr.Val_by_key_obj(Bry_.new_u8(msg_key)));
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@ package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import
|
||||
import gplx.core.json.*;
|
||||
class Scrib_lib_text__json_util {
|
||||
private final Json_wtr wtr = new Json_wtr();
|
||||
public void Init_for_tests() {wtr.Opt_quote_byte_(Byte_ascii.Apos);}
|
||||
public KeyVal[] Reindex_arrays(KeyVal[] kv_ary, boolean is_encoding) {
|
||||
public void Reindex_arrays(Scrib_lib_text__reindex_data rv, KeyVal[] kv_ary, boolean is_encoding) {
|
||||
int next = 0;
|
||||
if (is_encoding) {
|
||||
// ksort( $arr, SORT_NUMERIC );
|
||||
Array_.Sort(kv_ary, KeyVal__sorter__key_is_numeric.I);
|
||||
next = 1;
|
||||
}
|
||||
boolean is_sequence = true;
|
||||
@@ -31,56 +30,91 @@ class Scrib_lib_text__json_util {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
KeyVal kv = kv_ary[i];
|
||||
Object kv_val = kv.Val();
|
||||
if (kv_val != null && Type_adp_.Eq(kv_val.getClass(), KeyVal[].class))
|
||||
kv_val = Reindex_arrays((KeyVal[])kv_val, is_encoding);
|
||||
if (kv_val != null && Type_adp_.Eq(kv_val.getClass(), KeyVal[].class)) {
|
||||
Reindex_arrays(rv, (KeyVal[])kv_val, is_encoding);
|
||||
if (!rv.Rv_is_kvy())
|
||||
kv.Val_(rv.Rv_as_ary());
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (kv.Key_tid() == Type_adp_.Tid__int) {
|
||||
int kv_key_as_int = Int_.cast(kv.Key_as_obj());
|
||||
is_sequence = next++ == kv_key_as_int;
|
||||
// } elseif ( $isEncoding && ctype_digit( $k ) ) {
|
||||
// // json_decode currently doesn't return integer keys for {}
|
||||
// $isSequence = $next++ === (int)$k;
|
||||
} else {
|
||||
is_sequence = false;
|
||||
}
|
||||
else {
|
||||
int kv_key_to_int = Bry_.To_int_or__strict(Bry_.new_a7(kv.Key()), -1); // NOTE: a7 b/c proc is only checking for digits; none a7 bytes will be replaced by ?
|
||||
if (is_encoding && kv_key_to_int != -1) {
|
||||
is_sequence = next == kv_key_to_int;
|
||||
++next;
|
||||
}
|
||||
else
|
||||
is_sequence = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_sequence) {
|
||||
if (is_encoding) {
|
||||
// return array_values( $arr );
|
||||
Object rv_as_ary = To_array_values(kv_ary);
|
||||
rv.Init(Bool_.N, null, rv_as_ary);
|
||||
return;
|
||||
} else {
|
||||
// return $arr ? array_combine( range( 1, count( $arr ) ), $arr ) : $arr;
|
||||
Convert_to_base1(kv_ary); // PHP: return $arr ? array_combine( range( 1, count( $arr ) ), $arr ) : $arr;
|
||||
}
|
||||
}
|
||||
return kv_ary;
|
||||
rv.Init(Bool_.Y, kv_ary, null);
|
||||
}
|
||||
public KeyVal[] Decode(Json_parser parser, byte[] src, int flag) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
Json_nde root = jdoc.Root_nde();
|
||||
int len = root.Len();
|
||||
KeyVal[] rv = new KeyVal[len];
|
||||
private static Object[] To_array_values(KeyVal[] ary) {
|
||||
int len = ary.length;
|
||||
Object[] rv = new Object[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv json_kv = root.Get_at_as_kv(i);
|
||||
String kv_str = json_kv.Key_as_str();
|
||||
Object kv_val = Decode_obj(json_kv.Val());
|
||||
rv[i] = KeyVal_.new_(kv_str, kv_val);
|
||||
KeyVal itm = ary[i];
|
||||
rv[i] = itm.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void Convert_to_base1(KeyVal[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
KeyVal itm = ary[i];
|
||||
itm.Key_(i + 1);
|
||||
}
|
||||
}
|
||||
public KeyVal[] Decode_rslt_as_nde() {return decode_rslt_as_nde;} private KeyVal[] decode_rslt_as_nde;
|
||||
public Object Decode_rslt_as_ary() {return decode_rslt_as_ary;} private Object decode_rslt_as_ary;
|
||||
public byte Decode(Json_parser parser, byte[] src, int flag) {
|
||||
synchronized (wtr) {
|
||||
Json_doc jdoc = parser.Parse(src);
|
||||
if (jdoc.Root_grp().Tid() == Json_itm_.Tid__ary) {
|
||||
this.decode_rslt_as_ary = Decode_ary(jdoc.Root_ary());
|
||||
return Bool_.N_byte;
|
||||
}
|
||||
else {
|
||||
Json_nde root = (Json_nde)jdoc.Root_grp();
|
||||
int len = root.Len();
|
||||
this.decode_rslt_as_nde = new KeyVal[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_kv json_kv = root.Get_at_as_kv(i);
|
||||
String kv_str = json_kv.Key_as_str();
|
||||
Object kv_val = Decode_obj(json_kv.Val());
|
||||
decode_rslt_as_nde[i] = KeyVal_.new_(kv_str, kv_val);
|
||||
}
|
||||
return Bool_.Y_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
private Object Decode_obj(Json_itm itm) {
|
||||
int itm_tid = itm.Tid();
|
||||
switch (itm_tid) {
|
||||
case Json_itm_.Tid__ary: return Decode_ary(Json_ary.cast(itm));
|
||||
case Json_itm_.Tid__nde: return Decode_nde(Json_nde.cast(itm));
|
||||
case Json_itm_.Tid__nde: return Decode_nde(Json_nde.cast(itm));
|
||||
default: return itm.Data();
|
||||
}
|
||||
}
|
||||
private Object Decode_ary(Json_ary ary) {
|
||||
int len = ary.Len();
|
||||
Object rv = Array_.Create(int.class, len);
|
||||
Object rv = Array_.Create(Object.class, len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Json_itm itm = ary.Get_at(i);
|
||||
Array_.Set(rv, i, Decode_obj(itm));
|
||||
Array_.Set_at(rv, i, Decode_obj(itm));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -93,11 +127,18 @@ class Scrib_lib_text__json_util {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public byte[] Encode(KeyVal[] kv_ary, int flag, int skip) {
|
||||
public byte[] Encode_as_nde(KeyVal[] itm, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_bgn();
|
||||
Encode_kv_ary(kv_ary);
|
||||
return wtr.Doc_end().To_bry_and_clear();
|
||||
wtr.Clear().Doc_nde_bgn();
|
||||
Encode_kv_ary(itm);
|
||||
return wtr.Doc_nde_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public byte[] Encode_as_ary(Object ary, int flag, int skip) {
|
||||
synchronized (wtr ) {
|
||||
wtr.Clear().Doc_ary_bgn();
|
||||
Encode_ary(ary);
|
||||
return wtr.Doc_ary_end().To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
private void Encode_kv_ary(KeyVal[] kv_ary) {
|
||||
@@ -117,10 +158,7 @@ class Scrib_lib_text__json_util {
|
||||
}
|
||||
else if (Type_adp_.Is_array(type)) { // encode as array
|
||||
wtr.Ary_bgn(kv.Key());
|
||||
Object ary = Array_.cast(kv_val);
|
||||
int ary_len = Array_.Len(ary);
|
||||
for (int j = 0; j < ary_len; ++j)
|
||||
wtr.Ary_itm_obj(Array_.Get_at(ary, j));
|
||||
Encode_ary(kv_val);
|
||||
wtr.Ary_end();
|
||||
}
|
||||
else if (Type_adp_.Eq(type, Int_.Cls_ref_type)) wtr.Kv_int(kv.Key(), Int_.cast(kv_val));
|
||||
@@ -129,9 +167,15 @@ class Scrib_lib_text__json_util {
|
||||
else if (Type_adp_.Eq(type, Double_.Cls_ref_type)) wtr.Kv_double(kv.Key(), Double_.cast(kv_val));
|
||||
else if (Type_adp_.Eq(type, Bool_.Cls_ref_type)) wtr.Kv_bool(kv.Key(), Bool_.cast(kv_val));
|
||||
else wtr.Kv_str(kv.Key(), Object_.Xto_str_strict_or_null(kv_val));
|
||||
}
|
||||
}
|
||||
private void Encode_ary(Object ary) {
|
||||
int ary_len = Array_.Len(ary);
|
||||
for (int j = 0; j < ary_len; ++j)
|
||||
wtr.Ary_itm_obj(Array_.Get_at(ary, j));
|
||||
}
|
||||
public static final int
|
||||
Flag__preserve_keys = 1
|
||||
Flag__none = 0
|
||||
, Flag__preserve_keys = 1
|
||||
, Flag__try_fixing = 2
|
||||
, Flag__pretty = 4
|
||||
;
|
||||
@@ -144,3 +188,23 @@ class Scrib_lib_text__json_util {
|
||||
Opt__force_assoc = 1
|
||||
;
|
||||
}
|
||||
class KeyVal__sorter__key_is_numeric implements gplx.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
KeyVal lhs_itm = (KeyVal)lhsObj;
|
||||
KeyVal rhs_itm = (KeyVal)rhsObj;
|
||||
int lhs_int = Int_.parse_or(lhs_itm.Key(), Int_.Min_value);
|
||||
int rhs_int = Int_.parse_or(rhs_itm.Key(), Int_.Min_value);
|
||||
return CompareAble_.Compare(lhs_int, rhs_int);
|
||||
}
|
||||
public static final KeyVal__sorter__key_is_numeric I = new KeyVal__sorter__key_is_numeric(); KeyVal__sorter__key_is_numeric() {}
|
||||
}
|
||||
class Scrib_lib_text__reindex_data {
|
||||
public boolean Rv_is_kvy() {return rv_is_kvy;} private boolean rv_is_kvy;
|
||||
public KeyVal[] Rv_as_kvy() {return rv_as_kvy;} private KeyVal[] rv_as_kvy;
|
||||
public Object Rv_as_ary() {return rv_as_ary;} private Object rv_as_ary;
|
||||
public void Init(boolean rv_is_kvy, KeyVal[] rv_as_kvy, Object rv_as_ary) {
|
||||
this.rv_is_kvy = rv_is_kvy;
|
||||
this.rv_as_kvy = rv_as_kvy;
|
||||
this.rv_as_ary = rv_as_ary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.scribunto.*;
|
||||
import org.junit.*; import gplx.core.json.*;
|
||||
public class Scrib_lib_text_json_tst {
|
||||
private Scrib_invoke_func_fxt fxt = new Scrib_invoke_func_fxt(); private Scrib_lib_text lib;
|
||||
private Scrib_lib_json_fxt json_fxt = new Scrib_lib_json_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Clear_for_lib();
|
||||
lib = fxt.Core().Lib_text();
|
||||
lib.Init();
|
||||
}
|
||||
@Test public void Nde__empty() { // NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{"
|
||||
, "}"
|
||||
)
|
||||
, KeyVal_.Ary_empty
|
||||
);
|
||||
}
|
||||
@Test public void Nde__key_obj__primitives() { // NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{ 'int':1"
|
||||
, ", 'String':'abc'"
|
||||
, ", 'true':true"
|
||||
, ", 'array':"
|
||||
, " [ 1"
|
||||
, " , 2"
|
||||
, " , 3"
|
||||
, " ]"
|
||||
, ", 'node':"
|
||||
, " { 'key':'val'"
|
||||
, " }"
|
||||
, "}"
|
||||
)
|
||||
, KeyVal_.Ary
|
||||
( KeyVal_.new_("int", 1)
|
||||
, KeyVal_.new_("String", "abc")
|
||||
, KeyVal_.new_("true", true)
|
||||
, KeyVal_.new_("array", new int[] {1, 2, 3})
|
||||
, KeyVal_.new_("node", KeyVal_.Ary(KeyVal_.new_("key", "val")))
|
||||
));
|
||||
}
|
||||
@Test public void Nde__obj_in_obj() {
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{ 'x':"
|
||||
, " [ 1"
|
||||
, " , 2"
|
||||
, " , { 'y':'x'"
|
||||
, " }"
|
||||
, " ]"
|
||||
, "}"
|
||||
)
|
||||
, KeyVal_.Ary
|
||||
( KeyVal_.new_("x", new Object[]
|
||||
{ 1, 2, KeyVal_.Ary
|
||||
( KeyVal_.new_("y", "x")
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Nde__ary_in_obj() { // NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{ 'x':"
|
||||
, " [ 1"
|
||||
, " , 2"
|
||||
, " , { 'y':"
|
||||
, " [ 3"
|
||||
, " , 4"
|
||||
, " ]"
|
||||
, " }"
|
||||
, " ]"
|
||||
, "}"
|
||||
)
|
||||
, KeyVal_.Ary
|
||||
( KeyVal_.new_("x"
|
||||
, new Object[] {1, 2, KeyVal_.Ary
|
||||
( KeyVal_.new_("y"
|
||||
, new Object[] {3, 4}
|
||||
))}))
|
||||
);
|
||||
}
|
||||
@Test public void Nde__key_int__mixed() {// NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{ 'x':'x'"
|
||||
, ", '1':1"
|
||||
, ", '2':2"
|
||||
, "}"
|
||||
)
|
||||
, KeyVal_.Ary
|
||||
( KeyVal_.new_("x", "x")
|
||||
, KeyVal_.new_("1", 1)
|
||||
, KeyVal_.new_("2", 2)
|
||||
));
|
||||
}
|
||||
@Test public void Nde__key_int__auto() {// NOTE: based on MW
|
||||
json_fxt.Test_json_encode(fxt, lib
|
||||
, Scrib_lib_text__json_util.Flag__preserve_keys
|
||||
, Kv_ary_utl.new_(Bool_.Y, new Object[]
|
||||
{ 1
|
||||
, "abc"
|
||||
, true
|
||||
, false
|
||||
})
|
||||
, Json_doc.Make_str_by_apos // NOTE: numbering is done by Kv_ary_utl, not Reindex_arrays
|
||||
( "{ '1':1"
|
||||
, ", '2':'abc'"
|
||||
, ", '3':true"
|
||||
, ", '4':false"
|
||||
, "}"
|
||||
)
|
||||
);
|
||||
json_fxt.Test_json_decode(fxt, lib
|
||||
, Scrib_lib_text__json_util.Flag__preserve_keys
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "[ 1"
|
||||
, ", 'abc'"
|
||||
, ", true"
|
||||
, ", false"
|
||||
, "]"
|
||||
)
|
||||
, new Object[]
|
||||
{ 1
|
||||
, "abc"
|
||||
, true
|
||||
, false
|
||||
}
|
||||
);
|
||||
}
|
||||
@Test public void Ary__empty() { // NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "["
|
||||
, "]"
|
||||
)
|
||||
, Object_.Ary_empty
|
||||
);
|
||||
}
|
||||
@Test public void Ary__obj() { // NOTE: based on MW
|
||||
json_fxt.Test_json_encode(fxt, lib, Scrib_lib_text__json_util.Flag__none
|
||||
, Kv_ary_utl.new_(Bool_.Y, 1, "abc", true)
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "[ 1"
|
||||
, ", 'abc'"
|
||||
, ", true"
|
||||
, "]"
|
||||
)
|
||||
);
|
||||
}
|
||||
@Test public void Ary__nested() { // NOTE: based on MW
|
||||
json_fxt.Test_json_roundtrip(fxt, lib
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "[ 1"
|
||||
, ", 2"
|
||||
, ", 3"
|
||||
, ", "
|
||||
, " [ 4"
|
||||
, " , 5"
|
||||
, " , "
|
||||
, " [ 6"
|
||||
, " , 7"
|
||||
, " , 8"
|
||||
, " ]"
|
||||
, " , 9"
|
||||
, " ]"
|
||||
, "]"
|
||||
)
|
||||
, new Object[] {1, 2, 3, new Object[] {4, 5, new Object[] {6, 7, 8}, 9}}
|
||||
);
|
||||
}
|
||||
@Test public void Nde__smoke() {
|
||||
json_fxt.Test_json_encode(fxt, lib
|
||||
, Scrib_lib_text__json_util.Flag__none
|
||||
, KeyVal_.Ary
|
||||
( KeyVal_.new_("axes", KeyVal_.Ary
|
||||
( KeyVal_.int_(1, KeyVal_.Ary
|
||||
( KeyVal_.new_("type", "x")
|
||||
))
|
||||
, KeyVal_.int_(2, KeyVal_.Ary
|
||||
( KeyVal_.new_("type", "y")
|
||||
))
|
||||
))
|
||||
)
|
||||
, Json_doc.Make_str_by_apos
|
||||
( "{ 'axes':"
|
||||
, " ["
|
||||
, " { 'type':'x'"
|
||||
, " }"
|
||||
, " , { 'type':'y'"
|
||||
, " }"
|
||||
, " ]"
|
||||
, "}"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
class Scrib_lib_json_fxt {
|
||||
private final Json_wtr wtr = new Json_wtr();
|
||||
public void Test_json_roundtrip(Scrib_invoke_func_fxt fxt, Scrib_lib_text lib, String json, Object obj) {
|
||||
Test_json_decode(fxt, lib, Scrib_lib_text__json_util.Flag__none, json, obj);
|
||||
Test_json_encode(fxt, lib, Scrib_lib_text__json_util.Flag__none, obj, json);
|
||||
}
|
||||
public void Test_json_decode(Scrib_invoke_func_fxt fxt, Scrib_lib_text lib, int flag, String raw, Object expd) {
|
||||
Object actl = fxt.Test_scrib_proc_rv_as_obj(lib, Scrib_lib_text.Invk_jsonDecode, Object_.Ary(raw, flag));
|
||||
Tfds.Eq_str_lines(To_str(expd), To_str(actl), raw);
|
||||
}
|
||||
public void Test_json_encode(Scrib_invoke_func_fxt fxt, Scrib_lib_text lib, int flag, Object raw, String expd) {
|
||||
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_text.Invk_jsonEncode, Object_.Ary(raw, flag), "1=" + String_.Replace(expd, "'", "\""));
|
||||
}
|
||||
private String To_str(Object o) {
|
||||
if (o == null) return "<< NULL >>";
|
||||
Class<?> type = o.getClass();
|
||||
if (Type_adp_.Eq(type, KeyVal[].class)) return Kv_ary_utl.Ary_to_str(wtr, (KeyVal[])o);
|
||||
else if (Type_adp_.Is_array(type)) return Array_.To_str_nested_obj(o);
|
||||
else return Object_.Xto_str_strict_or_null(o);
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,10 @@ package gplx.xowa.xtns.scribunto.libs; import gplx.*; import gplx.xowa.*; import
|
||||
import org.junit.*; import gplx.core.json.*;
|
||||
public class Scrib_lib_text_tst {
|
||||
private Scrib_invoke_func_fxt fxt = new Scrib_invoke_func_fxt(); private Scrib_lib_text lib;
|
||||
private Scrib_lib_json_fxt json_fxt = new Scrib_lib_json_fxt();
|
||||
@Before public void init() {
|
||||
fxt.Clear_for_lib();
|
||||
lib = fxt.Core().Lib_text();
|
||||
lib.Init();
|
||||
lib.Init_for_tests();
|
||||
}
|
||||
@Test public void Unstrip() {
|
||||
fxt.Test_scrib_proc_str(lib, Scrib_lib_text.Invk_unstrip, Object_.Ary("a"), "a");
|
||||
@@ -33,106 +31,4 @@ public class Scrib_lib_text_tst {
|
||||
KeyVal[] actl = fxt.Test_scrib_proc_rv_as_kv_ary(lib, Scrib_lib_text.Invk_getEntityTable, Object_.Ary());
|
||||
Tfds.Eq(1510, actl.length); // large result; only test # of entries
|
||||
}
|
||||
@Test public void JsonEncode() {
|
||||
json_fxt.Test_json_encode(fxt, lib, Kv_ary_utl.new_
|
||||
( true
|
||||
, true
|
||||
, 1
|
||||
, "a"
|
||||
, new int[] {1, 2, 3}
|
||||
, Kv_ary_utl.new_(true, "b")
|
||||
), String_.Concat_lines_nl_skip_last
|
||||
( "1="
|
||||
+ "{ '1':true"
|
||||
, ", '2':1"
|
||||
, ", '3':'a'"
|
||||
, ", '4':"
|
||||
, " [ 1"
|
||||
, " , 2"
|
||||
, " , 3"
|
||||
, " ]"
|
||||
, ", '5':"
|
||||
, " { '1':'b'"
|
||||
, " }"
|
||||
, "}"
|
||||
));
|
||||
}
|
||||
@Test public void JsonDecode() {
|
||||
json_fxt.Test_json_decode(fxt, lib
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "{ '1':true"
|
||||
, ", '2':1"
|
||||
, ", '3':'a'"
|
||||
, ", '4':"
|
||||
, " [ 1"
|
||||
, " , 2"
|
||||
, " , 3"
|
||||
, " ]"
|
||||
, ", '5':"
|
||||
, " { '1':'b'"
|
||||
, " }"
|
||||
, "}"
|
||||
)
|
||||
, Kv_ary_utl.new_
|
||||
( true
|
||||
, true
|
||||
, 1
|
||||
, "a"
|
||||
, new int[] {1, 2, 3}
|
||||
, Kv_ary_utl.new_(true, "b")
|
||||
));
|
||||
}
|
||||
@Test public void JsonDecode__primitives() {
|
||||
json_fxt.Test_json_decode(fxt, lib
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "{ 'int':1"
|
||||
, ", 'String':'abc'"
|
||||
, ", 'true':true"
|
||||
, "}"
|
||||
)
|
||||
, Kv_ary_utl.new_kvs
|
||||
( KeyVal_.new_("int", 1)
|
||||
, KeyVal_.new_("String", "abc")
|
||||
, KeyVal_.new_("true", true)
|
||||
));
|
||||
}
|
||||
@Test public void JsonDecode__numeric_keys() {
|
||||
json_fxt.Test_json_decode(fxt, lib
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "{ 'x':'x'"
|
||||
, ", '1':1"
|
||||
, ", '2':2"
|
||||
, "}"
|
||||
)
|
||||
, Kv_ary_utl.new_kvs
|
||||
( KeyVal_.new_("x", "x")
|
||||
, KeyVal_.new_("1", 1)
|
||||
, KeyVal_.new_("2", 2)
|
||||
));
|
||||
}
|
||||
// @Test public void JsonDecode__array() {
|
||||
// json_fxt.Test_json_decode(fxt, lib
|
||||
// , String_.Concat_lines_nl_skip_last
|
||||
// ( "[ 1"
|
||||
// , ", 2"
|
||||
// , ", 3"
|
||||
// , "]"
|
||||
// )
|
||||
// , Kv_ary_utl.new_kvs
|
||||
// ( KeyVal_.new_("int", 1)
|
||||
// , KeyVal_.new_("String", "abc")
|
||||
// , KeyVal_.new_("true", true)
|
||||
// ));
|
||||
// }
|
||||
}
|
||||
class Scrib_lib_json_fxt {
|
||||
private final Json_wtr wtr = new Json_wtr().Opt_quote_byte_(Byte_ascii.Apos);
|
||||
public void Test_json_decode(Scrib_invoke_func_fxt fxt, Scrib_lib_text lib, String raw, KeyVal[] expd) {
|
||||
raw = String_.Replace(raw, "'", "\"");
|
||||
KeyVal[] actl = fxt.Test_scrib_proc_rv_as_kv_ary(lib, Scrib_lib_text.Invk_jsonDecode, Object_.Ary(raw));
|
||||
Tfds.Eq_str_lines(Kv_ary_utl.Ary_to_str(wtr, expd), Kv_ary_utl.Ary_to_str(wtr, actl), raw);
|
||||
}
|
||||
public void Test_json_encode(Scrib_invoke_func_fxt fxt, Scrib_lib_text lib, KeyVal[] raw, String expd) {
|
||||
fxt.Test_scrib_proc_str_ary(lib, Scrib_lib_text.Invk_jsonEncode, Object_.Ary((Object)raw), expd);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user