1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-08-30 22:57:59 -04:00
parent ed911e3de5
commit 5fc4eb41ec
579 changed files with 2460 additions and 1564 deletions

View File

@@ -24,7 +24,7 @@ public class Bry_rdr_tst {
fxt.Test_read_int(12);
fxt.Test_read_int(3456);
fxt.Test_read_int(789);
fxt.Test_read_int(Int_.MinValue);
fxt.Test_read_int(Int_.Min_value);
}
@Test public void Int_negative() {
fxt.Init_src("-1|-2");

View File

@@ -18,13 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_ary extends Json_itm_base implements Json_grp {
public Json_ary(int src_bgn, int src_end) {this.Ctor(src_bgn, src_end);}
@Override public byte Tid() {return Json_itm_.Tid_array;}
@Override public byte Tid() {return Json_itm_.Tid__ary;}
public void Src_end_(int v) {this.src_end = v;}
@Override public Object Data() {return null;}
@Override public byte[] Data_bry() {return null;}
public int Len() {return subs_len;} private int subs_len = 0, subs_max = 0;
public Json_nde Get_at_as_nde(int i) {
Json_itm rv = subs[i]; if (rv.Tid() != Json_itm_.Tid_nde) throw Err_.new_("json", "itm is not nde", "type", rv.Tid(), "i", i);
Json_itm rv = subs[i]; if (rv.Tid() != Json_itm_.Tid__nde) throw Err_.new_("json", "itm is not nde", "type", rv.Tid(), "i", i);
return (Json_nde)rv;
}
public Json_itm Get_at(int i) {return subs[i];}
@@ -71,9 +71,9 @@ public class Json_ary extends Json_itm_base implements Json_grp {
return rv;
}
private Json_itm[] subs = Json_itm_.Ary_empty;
public static Json_ary cast_or_null(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid_array ? null : (Json_ary)v;}
public static Json_ary cast_or_null(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__ary ? null : (Json_ary)v;}
public static Json_ary cast(Json_itm v) {
if (v == null || v.Tid() != Json_itm_.Tid_array) throw Err_.new_("json", "itm is not array");
if (v == null || v.Tid() != Json_itm_.Tid__ary) throw Err_.new_("json", "itm is not array");
return (Json_ary)v;
}
}

View File

@@ -17,27 +17,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_doc {
private final byte[][] tmp_qry_bry = new byte[1][];
public void Ctor(byte[] src, Json_nde root) {this.src = src; this.root = root;}
public Bry_bfr Bfr() {return bfr;} Bry_bfr bfr = Bry_bfr.new_();
public Number_parser Utl_num_parser() {return utl_num_parser;} Number_parser utl_num_parser = new Number_parser();
public byte[] Str_u8_bry() {return str_u8_bry;} private byte[] str_u8_bry = new byte[6];
public byte[] Src() {return src;} private byte[] src;
public Json_nde Root() {return root;} Json_nde root;
public Json_nde Root_nde() {return root;} private Json_nde root;
public Bry_bfr Bfr() {return bfr;} private final Bry_bfr bfr = Bry_bfr.new_();
public Number_parser Utl_num_parser() {return utl_num_parser;} private final Number_parser utl_num_parser = new Number_parser();
public byte[] Tmp_u8_bry() {return tmp_u8_bry;} private final byte[] tmp_u8_bry = new byte[6]; // tmp bry[] for decoding sequences like \u0008
public byte[] Get_val_as_bry_or(byte[] qry_bry, byte[] or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_bry_or(tmp_qry_bry, or);}
public byte[] Get_val_as_bry_or(byte[][] qry_bry, byte[] or) {
Json_itm nde = Find_nde(root, qry_bry, qry_bry.length - 1, 0);
return nde == null || nde.Tid() != Json_itm_.Tid_string ? or : nde.Data_bry();
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : nde.Data_bry();
}
public String Get_val_as_str_or(byte[] qry_bry, String or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_str_or(tmp_qry_bry, or);}
public String Get_val_as_str_or(byte[][] qry_bry, String or) {
Json_itm nde = Find_nde(root, qry_bry, qry_bry.length - 1, 0);
return nde == null || nde.Tid() != Json_itm_.Tid_string ? or : (String)nde.Data();
return nde == null || nde.Tid() != Json_itm_.Tid__str ? or : (String)nde.Data();
}
public Json_grp Get_grp(byte[] qry_bry) {
tmp_qry_bry[0] = qry_bry;
Json_itm rv = Find_nde(root, tmp_qry_bry, 0, 0); if (rv == null) return null;
return (Json_grp)rv;
} private byte[][] tmp_qry_bry = new byte[1][];
}
public Json_grp Get_grp(byte[][] qry_bry) {
Json_itm rv = Find_nde(root, qry_bry, qry_bry.length - 1, 0); if (rv == null) return null;
return (Json_grp)rv;
@@ -50,18 +51,12 @@ public class Json_doc {
byte[] path = paths[paths_idx];
int subs_len = owner.Len();
for (int i = 0; i < subs_len; i++) {
Json_kv itm = Json_kv.cast_(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes
Json_kv itm = Json_kv.cast(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes
if (!itm.Key_eq(path)) continue;
if (paths_idx == paths_last) return itm.Val();
Json_nde sub_nde = Json_nde.cast_(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit
Json_nde sub_nde = Json_nde.cast(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit
return Find_nde(sub_nde, paths, paths_last, paths_idx + 1);
}
return null;
}
public static Json_doc new_apos_concat_nl(String... ary) {return new_apos_(String_.Concat_lines_nl(ary));}
public static Json_doc new_apos_(String v) {return new_(Bry_.Replace(Bry_.new_u8(v), Byte_ascii.Apos, Byte_ascii.Quote));}
public static Json_doc new_(String v) {return new_(Bry_.new_u8(v));}
public static Json_doc new_(byte[] v) {
synchronized (parser) {return parser.Parse(v);}
} private static final Json_parser parser = new Json_parser();
}

View File

@@ -61,10 +61,10 @@ public class Json_doc_srl {
private void Write_indent() {if (ws_enabled && indent > 0) bfr.Add_byte_repeat(Byte_ascii.Space, indent);}
private void Write_str(byte[] v) {
if (v == null)
bfr.Add(Bry_null);
bfr.Add(Object_.Bry__null);
else
bfr.Add_byte(Byte_ascii.Quote).Add(v).Add_byte(Byte_ascii.Quote);
} private static final byte[] Bry_null = Bry_.new_a7("null");
}
private void Write_comma(boolean comma) {
if (comma)
bfr.Add_byte(Byte_ascii.Comma);

View File

@@ -18,10 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.json; import gplx.*; import gplx.core.*;
import org.junit.*;
public class Json_doc_tst {
Json_qry_mgr_fxt fxt = new Json_qry_mgr_fxt();
@Before public void init() {}
private final Json_qry_mgr_fxt fxt = new Json_qry_mgr_fxt();
@Test public void Select() {
Json_doc doc = Json_doc.new_apos_(String_.Concat_lines_nl
Json_doc doc = fxt.Make_json
( "{'0':"
, " {'0_0':"
, " {'0_0_0':'000'"
@@ -31,13 +30,15 @@ public class Json_doc_tst {
, " }"
, " }"
, "}"
));
);
fxt.Test_get_val_as_str(doc, "0/0_0/0_0_0", "000");
fxt.Test_get_val_as_str(doc, "0/0_1/0_1_0", "010");
fxt.Test_get_val_as_str(doc, "x", null);
}
}
class Json_qry_mgr_fxt {
private final Json_parser json_parser = new Json_parser();
public Json_doc Make_json(String... ary) {return json_parser.Parse_by_apos_ary(ary);}
public void Test_get_val_as_str(Json_doc doc, String qry, String expd){
byte[][] qry_bry = Bry_.Split(Bry_.new_u8(qry), Byte_ascii.Slash);
Tfds.Eq(expd, doc.Get_val_as_str_or(qry_bry, null));

View File

@@ -30,11 +30,11 @@ public class Json_doc_wtr {
public Json_doc_wtr New_line() {bfr.Add_byte_nl(); return this;}
public Json_doc_wtr Str(byte[] v) {
if (v == null)
bfr.Add(Bry_null);
bfr.Add(Object_.Bry__null);
else
bfr.Add_byte(Byte_ascii.Quote).Add(v).Add_byte(Byte_ascii.Quote);
return this;
} private static final byte[] Bry_null = Bry_.new_a7("null");
}
public Json_doc_wtr Int(int v) {bfr.Add_int_variable(v); return this;}
public Json_doc_wtr Double(double v) {bfr.Add_double(v); return this;}
public Json_doc_wtr Comma() {Indent(); bfr.Add_byte(Byte_ascii.Comma).Add_byte_nl(); return this;}

View File

@@ -23,7 +23,7 @@ public class Json_factory {
public Json_itm_int Int(Json_doc doc, int bgn, int end) {return new Json_itm_int(doc, bgn, end);}
public Json_itm Decimal(Json_doc doc, int bgn, int end) {return new Json_itm_decimal(doc, bgn, end);}
public Json_itm Str(Json_doc doc, int bgn, int end, boolean exact) {return new Json_itm_str(doc, bgn, end, exact);}
public Json_kv Kv(Json_itm key, Json_itm val) {return new Json_kv(key, val);}
public Json_ary Ary(int bgn, int end) {return new Json_ary(bgn, end);}
public Json_kv Kv(Json_itm key, Json_itm val) {return new Json_kv(key, val);}
public Json_ary Ary(int bgn, int end) {return new Json_ary(bgn, end);}
public Json_nde Nde(Json_doc doc, int bgn) {return new Json_nde(doc, bgn);}
}

View File

@@ -24,7 +24,7 @@ public interface Json_grp extends Json_itm {
}
class Json_grp_ {
public static final Json_grp[] Ary_empty = new Json_grp[0];
public static void Print_nl(Bry_bfr bfr) { // \n\n can be caused by nested groups (EX: "[[]]"); only print 1
public static void Print_nl(Bry_bfr bfr) { // \n\n can be caused by nested groups (EX: "[[]]"); only print 1
if (bfr.Bfr()[bfr.Len() - 1] != Byte_ascii.Nl)
bfr.Add_byte_nl();
}

View File

@@ -17,100 +17,43 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.json; import gplx.*; import gplx.core.*;
public interface Json_itm {
byte Tid();
int Src_bgn();
int Src_end();
Object Data();
byte[] Data_bry();
void Print_as_json(Bry_bfr bfr, int depth);
boolean Data_eq(byte[] comp);
byte Tid();
int Src_bgn();
int Src_end();
Object Data();
byte[] Data_bry();
void Print_as_json(Bry_bfr bfr, int depth);
boolean Data_eq(byte[] comp);
}
class Json_itm_null extends Json_itm_base {
Json_itm_null() {this.Ctor(-1, -1);}
@Override public byte Tid() {return Json_itm_.Tid_null;}
@Override public byte Tid() {return Json_itm_.Tid__null;}
@Override public Object Data() {return null;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Bry_null);}
@Override public byte[] Data_bry() {return Bry_null;}
private static final byte[] Bry_null = Bry_.new_a7("null");
public static Json_itm_null Null = new Json_itm_null();
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Object_.Bry__null);}
@Override public byte[] Data_bry() {return Object_.Bry__null;}
public static final Json_itm_null Null = new Json_itm_null();
}
class Json_itm_bool extends Json_itm_base {
public Json_itm_bool(boolean data) {this.data = data; this.Ctor(-1, -1);} private boolean data;
@Override public byte Tid() {return Json_itm_.Tid_bool;}
private boolean data;
public Json_itm_bool(boolean data) {this.data = data; this.Ctor(-1, -1);}
@Override public byte Tid() {return Json_itm_.Tid__bool;}
@Override public Object Data() {return data;}
@Override public byte[] Data_bry() {return data ? Json_itm_.Const_true : Json_itm_.Const_false;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Const_true: Json_itm_.Const_false);}
public static Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
@Override public byte[] Data_bry() {return data ? Json_itm_.Bry__true : Json_itm_.Bry__false;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Bry__true: Json_itm_.Bry__false);}
public static final Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
}
class Json_itm_decimal extends Json_itm_base {
public Json_itm_decimal(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;} Json_doc doc;
@Override public byte Tid() {return Json_itm_.Tid_decimal;}
private final Json_doc doc; private Decimal_adp data; private byte[] data_bry;
public Json_itm_decimal(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;}
@Override public byte Tid() {return Json_itm_.Tid__decimal;}
@Override public Object Data() {
if (data == null)
data = Decimal_adp_.parse_(String_.new_a7(this.Data_bry()));
data = Decimal_adp_.parse(String_.new_a7(this.Data_bry()));
return data;
} Decimal_adp data;
}
@Override public byte[] Data_bry() {
if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end());
return data_bry;
} byte[] data_bry;
}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());}
}
class Json_itm_str extends Json_itm_base {
public Json_itm_str(Json_doc doc, int src_bgn, int src_end, boolean exact) {this.Ctor(src_bgn + 1, src_end - 1); this.doc = doc; this.exact = exact;} private boolean exact; Json_doc doc;
@Override public byte Tid() {return Json_itm_.Tid_string;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
bfr.Add_byte(Byte_ascii.Quote);
gplx.html.Html_utl.Escape_html_to_bfr(bfr, doc.Src(), this.Src_bgn(), this.Src_end(), true, true, true, true, false); // false to apos for backwards compatibility
bfr.Add_byte(Byte_ascii.Quote);
}
@Override public Object Data() {
if (data_str == null) {
if (data_bry == null)
data_bry = Data_make_bry();
data_str = String_.new_u8(data_bry);
}
return data_str;
} private String data_str;
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Data_make_bry(); return data_bry;}
@Override public boolean Data_eq(byte[] comp) {
if (exact) return Bry_.Eq(comp, doc.Src(), this.Src_bgn(), this.Src_end());
if (data_bry == null) data_bry = Data_make_bry();
return Bry_.Match(data_bry, comp);
} byte[] data_bry = null;
private byte[] Data_make_bry() {
byte[] src = doc.Src(); int bgn = this.Src_bgn(), end = this.Src_end();
if (exact) return Bry_.Mid(src, bgn, end);
Bry_bfr bfr = doc.Bfr();
byte[] utf8_bry = doc.Str_u8_bry();
for (int i = bgn; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Backslash:
b = src[++i];
switch (b) { // NOTE: must properly unescape chars; EX:wd.q:2; DATE:2014-04-23
case Byte_ascii.Ltr_t: bfr.Add_byte(Byte_ascii.Tab); break;
case Byte_ascii.Ltr_n: bfr.Add_byte(Byte_ascii.Nl); break;
case Byte_ascii.Ltr_r: bfr.Add_byte(Byte_ascii.Cr); break;
case Byte_ascii.Ltr_b: bfr.Add_byte(Byte_ascii.Backfeed); break;
case Byte_ascii.Ltr_f: bfr.Add_byte(Byte_ascii.Formfeed); break;
case Byte_ascii.Ltr_u:
int utf8_val = gplx.texts.HexDecUtl.parse_or_(src, i + 1, i + 5, -1);
int len = gplx.intl.Utf16_.Encode_int(utf8_val, utf8_bry, 0);
bfr.Add_mid(utf8_bry, 0, len);
i += 4;
break; // \uFFFF 4 hex-dec
case Byte_ascii.Backslash:
case Byte_ascii.Slash:
default:
bfr.Add_byte(b); break; // \? " \ / b f n r t
}
break;
default:
bfr.Add_byte(b);
break;
}
}
return bfr.Xto_bry_and_clear();
}
}

View File

@@ -18,9 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_itm_ {
public static final Json_itm[] Ary_empty = new Json_itm[0];
public static final byte Tid_unknown = 0, Tid_null = 1, Tid_bool = 2, Tid_int = 3, Tid_decimal = 4, Tid_string = 5, Tid_kv = 6, Tid_array = 7, Tid_nde = 8;
public static final byte[][] Names = Bry_.Ary("unknown", "null", "boolean", "int", "decimal", "string", "keyval", "array", "nde");
public static final byte[] Const_true = Bry_.new_a7("true"), Const_false = Bry_.new_a7("false"), Const_null = Bry_.new_a7("null");
public static final byte Tid__unknown = 0, Tid__null = 1, Tid__bool = 2, Tid__int = 3, Tid__decimal = 4, Tid__str = 5, Tid__kv = 6, Tid__ary = 7, Tid__nde = 8;
public static final byte[] Bry__true = Bool_.True_bry, Bry__false = Bool_.False_bry, Bry__null = Object_.Bry__null;
public static byte[] To_bry(Bry_bfr bfr, Json_itm itm) {
if (itm == null) return Bry_.Empty;
itm.Print_as_json(bfr, 0);

View File

@@ -17,8 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_itm_int extends Json_itm_base {
public Json_itm_int(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;} Json_doc doc;
@Override public byte Tid() {return Json_itm_.Tid_int;}
private final Json_doc doc;
private byte[] data_bry; private int data; private boolean data_is_null = true;
public Json_itm_int(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;}
@Override public byte Tid() {return Json_itm_.Tid__int;}
public int Data_as_int() {
if (data_is_null) {
data = doc.Utl_num_parser().Parse(doc.Src(), Src_bgn(), Src_end()).Rv_as_int();
@@ -26,8 +28,8 @@ public class Json_itm_int extends Json_itm_base {
}
return data;
}
@Override public Object Data() {return Data_as_int();} int data; boolean data_is_null = true;
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); return data_bry;} private byte[] data_bry;
@Override public Object Data() {return Data_as_int();}
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); return data_bry;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());}
public static Json_itm_int cast_(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid_int ? null : (Json_itm_int)v;}
public static Json_itm_int cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__int ? null : (Json_itm_int)v;}
}

View File

@@ -0,0 +1,78 @@
/*
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.core.json; import gplx.*; import gplx.core.*;
class Json_itm_str extends Json_itm_base {
private final boolean exact; private final Json_doc doc;
private String data_str; private byte[] data_bry = null;
public Json_itm_str(Json_doc doc, int src_bgn, int src_end, boolean exact) {this.Ctor(src_bgn + 1, src_end - 1); this.doc = doc; this.exact = exact;}
@Override public byte Tid() {return Json_itm_.Tid__str;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
bfr.Add_byte(Byte_ascii.Quote);
gplx.html.Html_utl.Escape_html_to_bfr(bfr, doc.Src(), this.Src_bgn(), this.Src_end(), true, true, true, true, false); // false to apos for backwards compatibility
bfr.Add_byte(Byte_ascii.Quote);
}
@Override public Object Data() {
if (data_str == null) {
if (data_bry == null)
data_bry = Data_make_bry();
data_str = String_.new_u8(data_bry);
}
return data_str;
}
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Data_make_bry(); return data_bry;}
@Override public boolean Data_eq(byte[] comp) {
if (exact) return Bry_.Eq(comp, doc.Src(), this.Src_bgn(), this.Src_end());
if (data_bry == null) data_bry = Data_make_bry();
return Bry_.Match(data_bry, comp);
}
private byte[] Data_make_bry() {
byte[] src = doc.Src(); int bgn = this.Src_bgn(), end = this.Src_end();
if (exact) return Bry_.Mid(src, bgn, end);
Bry_bfr bfr = doc.Bfr();
byte[] utf8_bry = doc.Tmp_u8_bry();
for (int i = bgn; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Backslash:
b = src[++i];
switch (b) { // NOTE: must properly unescape chars; EX:wd.q:2; DATE:2014-04-23
case Byte_ascii.Ltr_t: bfr.Add_byte(Byte_ascii.Tab); break;
case Byte_ascii.Ltr_n: bfr.Add_byte(Byte_ascii.Nl); break;
case Byte_ascii.Ltr_r: bfr.Add_byte(Byte_ascii.Cr); break;
case Byte_ascii.Ltr_b: bfr.Add_byte(Byte_ascii.Backfeed); break;
case Byte_ascii.Ltr_f: bfr.Add_byte(Byte_ascii.Formfeed); break;
case Byte_ascii.Ltr_u:
int utf8_val = gplx.texts.HexDecUtl.parse_or(src, i + 1, i + 5, -1);
int len = gplx.intl.Utf16_.Encode_int(utf8_val, utf8_bry, 0);
bfr.Add_mid(utf8_bry, 0, len);
i += 4;
break; // \uFFFF 4 hex-dec
case Byte_ascii.Backslash:
case Byte_ascii.Slash:
default:
bfr.Add_byte(b); break; // \? " \ / b f n r t
}
break;
default:
bfr.Add_byte(b);
break;
}
}
return bfr.Xto_bry_and_clear();
}
}

View File

@@ -16,7 +16,7 @@ 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.core.json; import gplx.*; import gplx.core.*;
public class Json_itm_tmp implements Json_itm {
public class Json_itm_tmp implements Json_itm { // TEST:
public Json_itm_tmp(byte tid, String data) {this.tid = tid; this.data = data;}
public byte Tid() {return tid;} private byte tid;
public byte[] Data_bry() {return Bry_.new_u8(Object_.Xto_str_strict_or_empty(data));}
@@ -26,6 +26,6 @@ public class Json_itm_tmp implements Json_itm {
public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_str(data);}
public boolean Data_eq(byte[] comp) {return false;}
public void Clear() {}
public static Json_itm new_str_(String v) {return new Json_itm_tmp(Json_itm_.Tid_string, "\"" + v + "\"");}
public static Json_itm new_int_(int v) {return new Json_itm_tmp(Json_itm_.Tid_int, Int_.Xto_str(v));}
public static Json_itm new_str_(String v) {return new Json_itm_tmp(Json_itm_.Tid__str, "\"" + v + "\"");}
public static Json_itm new_int_(int v) {return new Json_itm_tmp(Json_itm_.Tid__int, Int_.Xto_str(v));}
}

View File

@@ -18,14 +18,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_kv extends Json_itm_base {
public Json_kv(Json_itm key, Json_itm val) {this.key = key; this.val = val;}
@Override public byte Tid() {return Json_itm_.Tid_kv;}
public Json_itm Key() {return key;} Json_itm key;
public Json_itm Val() {return val;} Json_itm val;
public Json_nde Val_as_nde() {return Json_nde.cast_(val);}
public Json_ary Val_as_ary() {return Json_ary.cast(val);}
@Override public byte Tid() {return Json_itm_.Tid__kv;}
public Json_itm Key() {return key;} private final Json_itm key;
public Json_itm Val() {return val;} private final Json_itm val;
public byte[] Key_as_bry() {return key.Data_bry();}
public String Key_as_str() {return (String)key.Data();}
public byte[] Val_as_bry() {return val.Data_bry();}
public Json_nde Val_as_nde() {return Json_nde.cast(val);}
public Json_ary Val_as_ary() {return Json_ary.cast(val);}
public boolean Key_eq(byte[] comp) {return ((Json_itm_str)key).Data_eq(comp);}
@Override public Object Data() {return null;}
@Override public byte[] Data_bry() {return null;}
@@ -35,5 +35,5 @@ public class Json_kv extends Json_itm_base {
val.Print_as_json(bfr, depth);
}
public static final Json_kv[] Ary_empty = new Json_kv[0];
public static Json_kv cast_(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid_kv ? null : (Json_kv)v;}
public static Json_kv cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__kv ? null : (Json_kv)v;}
}

View File

@@ -19,7 +19,7 @@ package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_kv_ary_srl {
public static KeyVal Kv_by_itm(Json_itm itm) {
switch (itm.Tid()) {
case Json_itm_.Tid_kv:
case Json_itm_.Tid__kv:
Json_kv kv = (Json_kv)itm;
return KeyVal_.new_(kv.Key_as_str(), Val_by_itm(kv.Val()));
default:
@@ -28,14 +28,14 @@ public class Json_kv_ary_srl {
}
private static Object Val_by_itm(Json_itm itm) {
switch (itm.Tid()) {
case Json_itm_.Tid_bool: return Bool_.Xto_str_lower(Bool_.cast_(itm.Data()));
case Json_itm_.Tid_int:
case Json_itm_.Tid_null:
case Json_itm_.Tid_string:
case Json_itm_.Tid_decimal: return itm.Data();
case Json_itm_.Tid_array: return Val_by_itm_ary((Json_ary)itm);
case Json_itm_.Tid_nde: return Val_by_itm_nde((Json_nde)itm);
case Json_itm_.Tid_kv: // kv should never be val; EX: "a":"b":c; not possible
case Json_itm_.Tid__bool: return Bool_.To_str_lower(Bool_.cast(itm.Data()));
case Json_itm_.Tid__int:
case Json_itm_.Tid__null:
case Json_itm_.Tid__str:
case Json_itm_.Tid__decimal: return itm.Data();
case Json_itm_.Tid__ary: return Val_by_itm_ary((Json_ary)itm);
case Json_itm_.Tid__nde: return Val_by_itm_nde((Json_nde)itm);
case Json_itm_.Tid__kv: // kv should never be val; EX: "a":"b":c; not possible
default: throw Err_.new_unhandled(itm.Tid());
}
}

View File

@@ -23,7 +23,7 @@ public class Json_kv_ary_srl_tst {
@Test public void Bool_n() {fxt.Test_parse("{'k0':false}" , fxt.ary_(fxt.kv_bool_("k0", false)));}
@Test public void Num() {fxt.Test_parse("{'k0':123}" , fxt.ary_(fxt.kv_int_("k0", 123)));}
@Test public void Str() {fxt.Test_parse("{'k0':'v0'}" , fxt.ary_(fxt.kv_str_("k0", "v0")));}
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.kv_dec_("k0", Decimal_adp_.parse_("1.23"))));}
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.kv_dec_("k0", Decimal_adp_.parse("1.23"))));}
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("1", 1), fxt.kv_int_("2", 2), fxt.kv_int_("3", 3)))));}
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_())));}
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1,'k01':2}}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("k00", 1), fxt.kv_int_("k01", 2)))));}
@@ -38,13 +38,13 @@ class Json_kv_ary_srl_fxt {
public void Test_parse(String raw_str, KeyVal[] expd) {
byte[] raw_bry = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
Json_doc doc = parser.Parse(raw_bry);
KeyVal[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root());
Tfds.Eq_str_lines(KeyVal_.Ary_x_to_str(expd), KeyVal_.Ary_x_to_str(actl));
KeyVal[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root_nde());
Tfds.Eq_str_lines(KeyVal_.Ary_to_str(expd), KeyVal_.Ary_to_str(actl));
}
public KeyVal[] ary_(KeyVal... ary) {return ary;}
public KeyVal kv_obj_(String key, Object val) {return KeyVal_.new_(key, val);}
public KeyVal kv_str_(String key, String val) {return KeyVal_.new_(key, val);}
public KeyVal kv_int_(String key, int val) {return KeyVal_.new_(key, val);}
public KeyVal kv_bool_(String key, boolean val) {return KeyVal_.new_(key, Bool_.Xto_str_lower(val));}
public KeyVal kv_bool_(String key, boolean val) {return KeyVal_.new_(key, Bool_.To_str_lower(val));}
public KeyVal kv_dec_(String key, Decimal_adp val) {return KeyVal_.new_(key, val.To_str());}
}

View File

@@ -19,7 +19,7 @@ package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_nde extends Json_itm_base implements Json_grp {
private Json_itm[] subs = Json_itm_.Ary_empty; private int subs_len = 0, subs_max = 0;
public Json_nde(Json_doc jdoc, int src_bgn) {this.jdoc = jdoc; this.Ctor(src_bgn, -1);}
@Override public byte Tid() {return Json_itm_.Tid_nde;}
@Override public byte Tid() {return Json_itm_.Tid__nde;}
public Json_doc Doc() {return jdoc;} private final Json_doc jdoc;
public void Src_end_(int v) {this.src_end = v;}
@Override public Object Data() {return null;}
@@ -27,21 +27,21 @@ public class Json_nde extends Json_itm_base implements Json_grp {
public int Len() {return subs_len;}
public Json_kv Get_at_as_kv(int i) {
Json_itm rv_itm = Get_at(i);
Json_kv rv = Json_kv.cast_(rv_itm); if (rv == null) throw Err_.new_("json", "sub is not kv", "i", i, "src", Bry_.Mid(jdoc.Src(), this.Src_bgn(), src_end));
Json_kv rv = Json_kv.cast(rv_itm); if (rv == null) throw Err_.new_("json", "sub is not kv", "i", i, "src", Bry_.Mid(jdoc.Src(), this.Src_bgn(), src_end));
return rv;
}
public Json_itm Get_at(int i) {return subs[i];}
public Json_kv Get_kv(byte[] key) {return Json_kv.cast_(Get_itm(key));}
public Json_kv Get_kv(byte[] key) {return Json_kv.cast(Get_itm(key));}
public Json_nde Get(String key) {return Get(Bry_.new_u8(key));}
public Json_nde Get(byte[] key) {
Json_kv kv = Json_kv.cast_(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key);
Json_nde rv = Json_nde.cast_(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key);
Json_kv kv = Json_kv.cast(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key);
Json_nde rv = Json_nde.cast(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key);
return rv;
}
public Json_itm Get_itm(byte[] key) {
for (int i = 0; i < subs_len; i++) {
Json_itm itm = subs[i];
if (itm.Tid() == Json_itm_.Tid_kv) {
if (itm.Tid() == Json_itm_.Tid__kv) {
Json_kv itm_as_kv = (Json_kv)itm;
if (Bry_.Eq(key, itm_as_kv.Key().Data_bry()))
return itm;
@@ -59,7 +59,7 @@ public class Json_nde extends Json_itm_base implements Json_grp {
public byte[] Get_bry(byte[] key, byte[] or) {
Json_itm kv_obj = Get_itm(key);
if (kv_obj == null) return or; // key not found;
if (kv_obj.Tid() != Json_itm_.Tid_kv) return or; // key is not a key_val
if (kv_obj.Tid() != Json_itm_.Tid__kv) return or; // key is not a key_val
Json_kv kv = (Json_kv)kv_obj;
Json_itm val = kv.Val();
return (val == null) ? or : val.Data_bry();
@@ -96,5 +96,5 @@ public class Json_nde extends Json_itm_base implements Json_grp {
Json_grp_.Print_nl(bfr); Json_grp_.Print_indent(bfr, depth);
bfr.Add_byte(Byte_ascii.Curly_end).Add_byte_nl();
}
public static Json_nde cast_(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid_nde ? null : (Json_nde)v;}
public static Json_nde cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__nde ? null : (Json_nde)v;}
}

View File

@@ -17,21 +17,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.core.json; import gplx.*; import gplx.core.*;
public class Json_parser {
public Json_factory Factory() {return factory;} private Json_factory factory = new Json_factory();
private byte[] src; private int src_len, pos; private Number_parser num_parser = new Number_parser();
private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull");
private byte[] src; private int src_len, pos; private final Number_parser num_parser = new Number_parser();
public Json_factory Factory() {return factory;} private final Json_factory factory = new Json_factory();
public Json_doc Parse_by_apos_ary(String... ary) {return Parse_by_apos(String_.Concat_lines_nl(ary));}
public Json_doc Parse_by_apos(String s) {return Parse(Bry_.Replace(Bry_.new_u8(s), Byte_ascii.Apos, Byte_ascii.Quote));}
public Json_doc Parse(String src) {return Parse(Bry_.new_u8(src));}
public Json_doc Parse(byte[] src) {
Json_doc doc = new Json_doc();
this.src = src; this.src_len = src.length; pos = 0;
Skip_ws();
if (src.length == 0) return null;
if (src[pos] != Byte_ascii.Curly_bgn) return null;
Skip_ws();
// if (src[pos + 1] != Byte_ascii.Quote) return null;
// throw Err_.new_wo_type("doc must start with {");
Json_nde root = Make_nde(doc);
doc.Ctor(src, root);
return doc;
synchronized (factory) {
this.src = src; if (src == null) return null;
this.src_len = src.length; if (src_len == 0) return null;
this.pos = 0;
Skip_ws();
boolean root_is_nde = true;
switch (src[pos]) {
case Byte_ascii.Curly_bgn: root_is_nde = Bool_.Y; break;
case Byte_ascii.Brack_bgn: root_is_nde = Bool_.N; break;
default: return null;
}
Skip_ws();
Json_doc doc = new Json_doc();
Json_nde root = Make_nde(doc);
if (root_is_nde) {}
doc.Ctor(src, root);
return doc;
}
}
private Json_nde Make_nde(Json_doc doc) {
++pos; // brack_bgn
@@ -49,7 +58,7 @@ public class Json_parser {
}
throw Err_.new_wo_type("eos inside nde");
}
Json_itm Make_kv(Json_doc doc) {
private Json_itm Make_kv(Json_doc doc) {
Json_itm key = Make_string(doc);
Skip_ws();
Chk(Byte_ascii.Colon);
@@ -57,7 +66,7 @@ public class Json_parser {
Json_itm val = Make_val(doc);
return new Json_kv(key, val);
}
Json_itm Make_val(Json_doc doc) {
private Json_itm Make_val(Json_doc doc) {
while (pos < src_len) {
byte b = src[pos];
switch (b) {
@@ -75,16 +84,16 @@ public class Json_parser {
}
throw Err_.new_wo_type("eos reached in val");
}
Json_itm Make_literal(byte[] remainder, int remainder_len, Json_itm singleton) {
private Json_itm Make_literal(byte[] remainder, int remainder_len, Json_itm singleton) {
++pos; // 1st char
int literal_end = pos + remainder_len;
if (Bry_.Eq(remainder, src, pos, literal_end)) {
pos = literal_end;
return singleton;
}
throw Err_.new_wo_type("invalid literal");
throw Err_.new_("json.parser", "invalid literal", "excerpt", Bry_.Mid_by_len_safe(src, pos - 1, 16));
}
Json_itm Make_string(Json_doc doc) {
private Json_itm Make_string(Json_doc doc) {
int bgn = pos++; // ++: quote_bgn
boolean exact = true;
while (pos < src_len) {
@@ -106,7 +115,7 @@ public class Json_parser {
}
throw Err_.new_wo_type("eos reached inside quote");
}
Json_itm Make_num(Json_doc doc) {
private Json_itm Make_num(Json_doc doc) {
int num_bgn = pos;
boolean loop = true;
while (loop) {
@@ -131,7 +140,7 @@ public class Json_parser {
? factory.Decimal(doc, num_bgn, pos)
: factory.Int(doc, num_bgn, pos);
}
Json_ary Make_ary(Json_doc doc) {
private Json_ary Make_ary(Json_doc doc) {
Json_ary rv = factory.Ary(pos++, pos); // brack_bgn
while (pos < src_len) {
Skip_ws();
@@ -159,9 +168,10 @@ public class Json_parser {
else
throw err_(src, pos, "expected '{0}' but got '{1}'", Char_.To_str(expd), Char_.To_str(src[pos]));
}
Err err_(byte[] src, int bgn, String fmt, Object... args) {return err_(src, bgn, src.length, fmt, args);}
Err err_(byte[] src, int bgn, int src_len, String fmt, Object... args) {
private Err err_(byte[] src, int bgn, String fmt, Object... args) {return err_(src, bgn, src.length, fmt, args);}
private Err err_(byte[] src, int bgn, int src_len, String fmt, Object... args) {
String msg = String_.Format(fmt, args) + " " + Int_.Xto_str(bgn) + " " + String_.new_u8_by_len(src, bgn, 20);
return Err_.new_wo_type(msg);
}
private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull");
}

View File

@@ -58,7 +58,7 @@ class Json_parser_fxt {
public Json_kv itm_kv_(String k, String v) {return factory.Kv(itm_str_(k), itm_str_(v));}
public Json_kv itm_kv_(String k, int v) {return factory.Kv(itm_str_(k), itm_int_(v));}
public Json_kv itm_kv_(String k, boolean v) {return factory.Kv(itm_str_(k), v ? factory.Bool_y() : factory.Bool_n());}
public Json_kv itm_kv_dec_(String k, String v) {return factory.Kv(itm_str_(k), new Json_itm_tmp(Json_itm_.Tid_decimal, v));}
public Json_kv itm_kv_dec_(String k, String v) {return factory.Kv(itm_str_(k), new Json_itm_tmp(Json_itm_.Tid__decimal, v));}
public Json_kv itm_kv_(String k, Json_nde v) {return factory.Kv(itm_str_(k), v);}
public Json_kv itm_kv_ary_int_(String k, int... v) {
Json_ary ary = factory.Ary(-1, -1);
@@ -77,7 +77,7 @@ class Json_parser_fxt {
public void Test_parse(String raw_str, Json_itm... expd_ary) {
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
Json_doc doc = parser.Parse(raw);
doc.Root().Print_as_json(tmp_bfr, 0);
doc.Root_nde().Print_as_json(tmp_bfr, 0);
String actl = tmp_bfr.Xto_str_and_clear();
String expd = Xto_str(raw, doc, expd_ary, 0, expd_ary.length);
Tfds.Eq_str_lines(expd, actl, actl);
@@ -85,7 +85,7 @@ class Json_parser_fxt {
public void Test_parse_val0(String raw_str, Object expd) {
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str));
Json_doc doc = parser.Parse(raw);
Json_kv kv = Json_kv.cast_(doc.Root().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
Json_kv kv = Json_kv.cast(doc.Root_nde().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
Object actl = kv.Val().Data(); // NOTE: Data_bry is escaped val; EX: a\"b has DataBry of a"b
Tfds.Eq(expd, actl);
}

View File

@@ -51,8 +51,8 @@ public class Json_wtr {
}
public Json_wtr Ary_itm_str(String itm) {return Ary_itm_by_type_tid(Type_adp_.Tid__str, itm);}
public Json_wtr Ary_itm_bry(byte[] itm) {return Ary_itm_by_type_tid(Type_adp_.Tid__bry, itm);}
public Json_wtr Ary_itm_obj(Object itm) {return Ary_itm_by_type_tid(Type_adp_.To_tid(itm), itm);}
private Json_wtr Ary_itm_by_type_tid(int itm_type_tid, Object itm) {
public Json_wtr Ary_itm_obj(Object itm) {return Ary_itm_by_type_tid(Type_adp_.To_tid_obj(itm), itm);}
public Json_wtr Ary_itm_by_type_tid(int itm_type_tid, Object itm) {
Add_indent_itm(ary_itm_is_first);
Add_itm_by_tid(itm_type_tid, itm);
Add_nl();
@@ -85,6 +85,14 @@ public class Json_wtr {
nde_itm_is_first = false;
return this;
}
public Json_wtr Kv_obj(byte[] key, Object val, int val_tid) {
Add_indent_itm(nde_itm_is_first);
Add_key(key);
Add_itm_by_tid(val_tid, val);
Add_nl();
nde_itm_is_first = false;
return this;
}
public Json_wtr Kv_bfr(String key, Bry_bfr val) {
Add_indent_itm(nde_itm_is_first);
Add_key(Bry_.new_u8(key));
@@ -115,14 +123,14 @@ public class Json_wtr {
bfr.Add_byte_colon();
return this;
}
public void Add_itm_by_tid(int type_tid, Object obj) {
private void Add_itm_by_tid(int type_tid, Object obj) {
switch (type_tid) {
case Type_adp_.Tid__bool: bfr.Add_bool(Bool_.cast_(obj)); break;
case Type_adp_.Tid__byte: bfr.Add_byte(Byte_.cast_(obj)); break;
case Type_adp_.Tid__int: bfr.Add_int_variable(Int_.cast_(obj)); break;
case Type_adp_.Tid__long: bfr.Add_long_variable(Long_.cast_(obj)); break;
case Type_adp_.Tid__float: bfr.Add_float(Float_.cast_(obj)); break;
case Type_adp_.Tid__double: bfr.Add_double(Double_.cast_(obj)); break;
case Type_adp_.Tid__bool: bfr.Add_bool(Bool_.cast(obj)); break;
case Type_adp_.Tid__byte: bfr.Add_byte(Byte_.cast(obj)); break;
case Type_adp_.Tid__int: bfr.Add_int_variable(Int_.cast(obj)); break;
case Type_adp_.Tid__long: bfr.Add_long_variable(Long_.cast(obj)); break;
case Type_adp_.Tid__float: bfr.Add_float(Float_.cast(obj)); break;
case Type_adp_.Tid__double: bfr.Add_double(Double_.cast(obj)); break;
case Type_adp_.Tid__str: Add_itm_bry(Bry_.new_u8((String)obj)); break;
case Type_adp_.Tid__bry: Add_itm_bry((byte[])obj); break;
case Type_adp_.Tid__char:

View File

@@ -47,6 +47,6 @@ public class Binary_search_ {
else if (pos > pos_last) pos = pos_last;
pos_prv = pos;
}
return Int_.MinValue; // should only occur if (a) ary's 0th slot is not ""; or (b) some unknown error
return Int_.Min_value; // should only occur if (a) ary's 0th slot is not ""; or (b) some unknown error
}
}