Embeddable: Create core dbs in proper subdirectory

pull/620/head
gnosygnu 7 years ago
parent 1336d44f34
commit 66877212bf

@ -0,0 +1,120 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.lang.reflect.Array;
import gplx.core.strings.*; import gplx.core.lists.*;
public class Array_ {
public static Object cast(Object o) {return (Object)o;}
public static void Sort(Object[] obj) {List_adp_sorter.new_().Sort(obj, obj.length);}
public static void Sort(Object[] obj, gplx.core.lists.ComparerAble comparer) {List_adp_sorter.new_().Sort(obj, obj.length, true, comparer);}
public static Object[] Insert(Object[] cur, Object[] add, int add_pos) {
int cur_len = cur.length, add_len = add.length;
Object[] rv = (Object[])Array_.Create(Array_.Component_type(cur), cur_len + add_len);
for (int i = 0; i < add_pos; i++) // copy old up to add_pos
rv[i] = cur[i];
for (int i = 0; i < add_len; i++) // insert add
rv[i + add_pos] = add[i];
for (int i = add_pos; i < cur_len; i++) // copy old after add_pos
rv[i + add_len] = cur[i];
return rv;
}
public static Object[] Replace_insert(Object[] cur, Object[] add, int curReplacePos, int addInsertPos) {
int curLen = cur.length, addLen = add.length; int newLen = addLen - addInsertPos;
Object[] rv = (Object[])Array_.Create(Array_.Component_type(cur), curLen + newLen);
for (int i = 0; i < curReplacePos; i++) // copy old up to curInsertPos; EX: curReplacePos=5, addInsertPos=2; copy up to element 3; 4, 5 are dropped
rv[i] = cur[i];
for (int i = 0; i < addLen; i++) // insert add
rv[i + curReplacePos] = add[i];
for (int i = curReplacePos + addInsertPos; i < curLen; i++) // copy old after curReplacePos
rv[i + newLen] = cur[i];
return rv;
}
public static Object Resize_add_one(Object src, int src_len, Object new_obj) {
Object rv = Resize(src, src_len + 1);
Set_at(rv, src_len, new_obj);
return rv;
}
public static Object Resize(Object src, int trg_len) {
Object trg = Create(Component_type(src), trg_len);
int src_len = Array.getLength(src);
int copy_len = src_len > trg_len ? trg_len : src_len; // trg_len can either expand or shrink
Copy_to(src, 0, trg, 0, copy_len);
return trg;
}
public static List_adp To_list(Object ary) {
int aryLen = Array_.Len(ary);
List_adp rv = List_adp_.New();
for (int i = 0; i < aryLen; i++)
rv.Add(Array_.Get_at(ary, i));
return rv;
}
public static String To_str_nested_obj(Object o) {
Bry_bfr bfr = Bry_bfr_.New();
To_str_nested_ary(bfr, (Object)o, 0);
return bfr.To_str_and_clear();
}
private static void To_str_nested_ary(Bry_bfr bfr, Object ary, int indent) {
int len = Len(ary);
for (int i = 0; i < len; i++) {
Object itm = Get_at(ary, i);
if (itm != null && Type_.Is_array(itm.getClass()))
To_str_nested_ary(bfr, (Object)itm, indent + 1);
else {
if (indent > 0) bfr.Add_byte_repeat(Byte_ascii.Space, indent * 2);
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(itm)).Add_byte_nl();
}
}
}
public static String To_str_obj(Object o) {return To_str((Object)o);}
public static String To_str(Object ary) {
String_bldr sb = String_bldr_.new_();
int ary_len = Len(ary);
for (int i = 0; i < ary_len; i++)
sb.Add_obj(Get_at(ary, i)).Add_char_nl();
return sb.To_str();
}
public static int Len(Object ary) {return Array.getLength(ary);}
public static final int Len_obj(Object[] ary) {return ary == null ? 0 : ary.length;}
public static Object Get_at(Object ary, int i) {return Array.get(ary, i);}
public static void Set_at(Object ary, int i, Object o) {Array.set(ary, i, o);}
public static Object Create(Class<?> t, int count) {return Array.newInstance(t, count);}
public static Object Expand(Object src, Object trg, int src_len) {
try {System.arraycopy(src, 0, trg, 0, src_len);}
catch (Exception e) {throw Err_.new_exc(e, "core", "Array_.Expand failed", "src_len", src_len);}
return trg;
}
public static void Copy(Object src, Object trg) {System.arraycopy(src, 0, trg, 0, Len(src));}
public static void Copy_to(Object src, Object trg, int trgPos) {System.arraycopy(src, 0, trg, trgPos, Len(src));}
public static void Copy_to(Object src, int srcBgn, Object trg, int trgBgn, int srcLen) {System.arraycopy(src, srcBgn, trg, trgBgn, srcLen);}
private static Class<?> Component_type(Object ary) {
if (ary == null) throw Err_.new_null();
return ary.getClass().getComponentType();
}
public static Object Resize_add(Object src, Object add) {
int srcLen = Len(src);
int trgLen = srcLen + Len(add);
Object trg = Create(Component_type(src), trgLen);
Copy(src, trg);
for (int i = srcLen; i < trgLen; i++)
Set_at(trg, i, Get_at(add, i - srcLen));
return trg;
}
public static Object Clone(Object src) {
Object trg = Create(Component_type(src), Len(src));
Copy(src, trg);
return trg;
}
}

@ -0,0 +1,39 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Array__tst {
@Test public void Resize_add() {
tst_Resize_add(ary_(), ary_(1), ary_(1)); // 0 + 1 = 1
tst_Resize_add(ary_(0), ary_(), ary_(0)); // 1 + 0 = 1
tst_Resize_add(ary_(0), ary_(1), ary_(0, 1)); // 1 + 1 = 2
} void tst_Resize_add(int[] source, int[] added, int[] expd) {Tfds.Eq_ary(expd, (int[])Array_.Resize_add(source, added));}
@Test public void Resize() {
tst_Resize(ary_(0), 0, ary_()); // 1 -> 0
tst_Resize(ary_(0, 1), 1, ary_(0)); // 2 -> 1
} void tst_Resize(int[] source, int length, int[] expd) {Tfds.Eq_ary(expd, (int[])Array_.Resize(source, length));}
@Test public void Insert() {
tst_Insert(ary_obj(0, 1, 4, 5), ary_obj(2, 3), 2, ary_obj(0, 1, 2, 3, 4, 5));
} void tst_Insert(Object[] cur, Object[] add, int addPos, Object[] expd) {Tfds.Eq_ary(expd, Array_.Insert(cur, add, addPos));}
@Test public void ReplaceInsert() {
tst_ReplaceInsert(ary_obj(0, 1, 4, 5) , ary_obj(1, 2, 3), 1, 1, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 2, 4, 5) , ary_obj(1, 2, 3), 1, 2, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 2, 3, 4, 5) , ary_obj(1, 2, 3), 1, 3, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 9, 4, 5) , ary_obj(2, 3) , 2, 1, ary_obj(0, 1, 2, 3, 4, 5));
} void tst_ReplaceInsert(Object[] cur, Object[] add, int curReplacePos, int addInsertPos, Object[] expd) {Tfds.Eq_ary(expd, Array_.Replace_insert(cur, add, curReplacePos, addInsertPos));}
Object[] ary_obj(Object... ary) {return ary;}
int[] ary_(int... ary) {return ary;}
}

@ -0,0 +1,65 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Bool_ {//RF:2017-10-08
public static final String Cls_val_name = "bool";
public static final Class<?> Cls_ref_type = Boolean.class;
public static final boolean N = false , Y = true;
public static final byte N_byte = 0 , Y_byte = 1 , __byte = 127;
public static final int N_int = 0 , Y_int = 1 , __int = -1;
public static final byte[] N_bry = new byte[] {Byte_ascii.Ltr_n}, Y_bry = new byte[] {Byte_ascii.Ltr_y};
public static final String True_str = "true", False_str = "false";
public static final byte[] True_bry = Bry_.new_a7(True_str), False_bry = Bry_.new_a7(False_str);
public static boolean By_int(int v) {return v == Y_int;}
public static int To_int(boolean v) {return v ? Y_int : N_int;}
public static byte To_byte(boolean v) {return v ? Y_byte : N_byte;}
public static String To_str_lower(boolean v) {return v ? True_str : False_str;}
public static boolean Cast(Object obj) {try {return (Boolean)obj;} catch (Exception e) {throw Err_.new_type_mismatch_w_exc(e, boolean.class, obj);}}
public static boolean Cast_or(Object obj, boolean or) {try {return (Boolean)obj;} catch (Exception e) {Err_.Noop(e); return or;}}
public static boolean Parse(String raw) {
if ( String_.Eq(raw, True_str)
|| String_.Eq(raw, "True") // needed for Store_Wtr(){boolVal.toString();}
)
return true;
else if ( String_.Eq(raw, False_str)
|| String_.Eq(raw, "False")
)
return false;
throw Err_.new_parse_type(boolean.class, raw);
}
public static boolean Parse_or(String raw, boolean or) {
if ( String_.Eq(raw, True_str)
|| String_.Eq(raw, "True") // needed for Store_Wtr(){boolVal.toString();}
)
return true;
else if ( String_.Eq(raw, False_str)
|| String_.Eq(raw, "False")
)
return false;
return or;
}
public static int Compare(boolean lhs, boolean rhs) {
if ( lhs == rhs) return CompareAble_.Same;
else if (!lhs && rhs) return CompareAble_.Less;
else /*lhs && !rhs*/ return CompareAble_.More;
}
}

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Bool__tst {
private final Bool__fxt fxt = new Bool__fxt();
@Test public void Compare() {
fxt.Test__compare(Bool_.Y, Bool_.Y, CompareAble_.Same);
fxt.Test__compare(Bool_.N, Bool_.N, CompareAble_.Same);
fxt.Test__compare(Bool_.N, Bool_.Y, CompareAble_.Less);
fxt.Test__compare(Bool_.Y, Bool_.N, CompareAble_.More);
}
}
class Bool__fxt {
public void Test__compare(boolean lhs, boolean rhs, int expd) {Tfds.Eq(expd, Bool_.Compare(lhs, rhs));}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,307 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.tests.*;
public class Bry__tst {
private final Bry__fxt fxt = new Bry__fxt();
@Test public void new_ascii_() {
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one
fxt.Test_new_a7("abc" , Bry_.New_by_ints(97, 98, 99)); // many
fxt.Test_new_a7("" , Bry_.Empty); // none
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ?
}
@Test public void new_u8() {
fxt.Test_new_u8("a" , Bry_.New_by_ints(97)); // one
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many
fxt.Test_new_u8("¢" , Bry_.New_by_ints(194, 162)); // bry_len=2; cent
fxt.Test_new_u8("€" , Bry_.New_by_ints(226, 130, 172)); // bry_len=3; euro
fxt.Test_new_u8("𤭢" , Bry_.New_by_ints(240, 164, 173, 162)); // bry_len=4; example from en.w:UTF-8
}
@Test public void Add__bry_plus_byte() {
fxt.Test_add("a" , Byte_ascii.Pipe , "a|"); // basic
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String
}
@Test public void Add__byte_plus_bry() {
fxt.Test_add(Byte_ascii.Pipe , "a" , "|a"); // basic
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String
}
@Test public void Add_w_dlm() {
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
}
@Test public void Add_w_dlm_bry() {
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
}
@Test public void MidByPos() {
tst_MidByPos("abcba", 0, 1, "a");
tst_MidByPos("abcba", 0, 2, "ab");
tst_MidByPos("abcba", 1, 4, "bcb");
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Mid(Bry_.new_u8(src), bgn, end)));}
@Test public void Replace_one() {
tst_ReplaceOne("a" , "b" , "c" , "a");
tst_ReplaceOne("b" , "b" , "c" , "c");
tst_ReplaceOne("bb" , "b" , "c" , "cb");
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Replace_one(Bry_.new_u8(src), Bry_.new_u8(find), Bry_.new_u8(repl))));}
@Test public void XtoStrBytesByInt() {
tst_XtoStrBytesByInt(0, 0);
tst_XtoStrBytesByInt(9, 9);
tst_XtoStrBytesByInt(10, 1, 0);
tst_XtoStrBytesByInt(321, 3, 2, 1);
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
tst_XtoStrBytesByInt(Int_.Max_value, 2,1,4,7,4,8,3,6,4,7);
}
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
byte[] expd = new byte[expdAryAsInt.length];
for (int i = 0; i < expd.length; i++) {
int expdInt = expdAryAsInt[i];
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Byte_ascii.To_a7_str(expdAryAsInt[i]);
}
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
}
@Test public void Has_at_end() {
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
tst_HasAtEnd("abc", "bc", true); // y
tst_HasAtEnd("abc", "bd", false); // n
tst_HasAtEnd("a", "ab", false); // exceeds_len
}
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end));}
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find)));}
@Test public void Has_at_bgn() {
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_bgn(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end), tst);}
@Test public void Match() {
tst_Match("abc", 0, "abc", true);
tst_Match("abc", 2, "c", true);
tst_Match("abc", 0, "cde", false);
tst_Match("abc", 2, "abc", false); // bounds check
tst_Match("abc", 0, "abcd", false);
tst_Match("a" , 0, "", false);
tst_Match("" , 0, "a", false);
tst_Match("" , 0, "", true);
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_u8(src), srcPos, Bry_.new_u8(find)));}
@Test public void ReadCsvStr() {
tst_ReadCsvStr("a|" , "a");
tst_ReadCsvStr("|a|", 1 , "a");
Int_obj_ref bgn = Int_obj_ref.New_zero(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
tst_ReadCsvStr("|", "");
tst_ReadCsvStr_err("a");
tst_ReadCsvStr("'a'|" , "a");
tst_ReadCsvStr("'a''b'|" , "a'b");
tst_ReadCsvStr("'a|b'|" , "a|b");
tst_ReadCsvStr("''|", "");
tst_ReadCsvStr_err("''");
tst_ReadCsvStr_err("'a'b'");
tst_ReadCsvStr_err("'a");
tst_ReadCsvStr_err("'a|");
tst_ReadCsvStr_err("'a'");
}
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
tst_XtoIntBy4Bytes(32, (byte)32); // space
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // &exist;
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
}
@Test public void XtoInt() {
tst_XtoInt("1", 1);
tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
tst_XtoInt("-1", Int_.Min_value, -1);
tst_XtoInt("-123", Int_.Min_value, -123);
tst_XtoInt("123-1", Int_.Min_value, Int_.Min_value);
tst_XtoInt("+123", Int_.Min_value, 123);
tst_XtoInt("", -1);
}
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.To_int_or(Bry_.new_u8(val), or));}
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.To_int_by_a7(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.new_by_int(expd), "XbyInt");}
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New_zero() , expd);}
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New(bgn), expd);}
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
int bgn = bgnRef.Val();
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
Tfds.Eq(expd, actl, "rv");
if (rawHasQuotes) {
int quoteAdj = String_.Count(actl, "'");
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
}
else
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
}
void tst_ReadCsvStr_err(String raw) {
try {Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), Int_obj_ref.New_zero(), (byte)'|');}
catch (Exception e) {Err_.Noop(e); return;}
Tfds.Fail_expdError();
}
@Test public void ReadCsvDte() {
tst_ReadCsvDte("20110801 221435.987");
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
@Test public void ReadCsvInt() {
tst_ReadCsvInt("1234567890");
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.Parse(raw), Bry_.ReadCsvInt(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
@Test public void Trim() {
Trim_tst("a b c", 1, 4, "b");
Trim_tst("a c", 1, 3, "");
Trim_tst(" ", 0, 2, "");
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Trim(Bry_.new_u8(raw), bgn, end)));}
@Test public void Xto_int_lax() {
tst_Xto_int_lax("12a", 12);
tst_Xto_int_lax("1", 1);
tst_Xto_int_lax("123", 123);
tst_Xto_int_lax("a", 0);
tst_Xto_int_lax("-1", -1);
}
private void tst_Xto_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__lax(Bry_.new_u8(val), 0, String_.Len(val), 0));}
@Test public void To_int_or__trim_ws() {
tst_Xto_int_trim("123 " , 123);
tst_Xto_int_trim(" 123" , 123);
tst_Xto_int_trim(" 123 " , 123);
tst_Xto_int_trim(" 1 3 " , -1);
}
private void tst_Xto_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__trim_ws(Bry_.new_u8(val), 0, String_.Len(val), -1));}
@Test public void Compare() {
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_u8(lhs), lhs_bgn, lhs_end, Bry_.new_u8(rhs), rhs_bgn, rhs_end));}
@Test public void Increment_last() {
tst_IncrementLast(ary_(0), ary_(1));
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
}
byte[] ary_(int... ary) {
byte[] rv = new byte[ary.length];
for (int i = 0; i < ary.length; i++)
rv[i] = Byte_.By_int(ary[i]);
return rv;
}
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
@Test public void Replace_between() {
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_a7(Bry_.Replace_between(Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(end), Bry_.new_a7(repl))));}
@Test public void Replace() {
Bry_bfr tmp_bfr = Bry_bfr_.New();
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
}
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
Tfds.Eq(expd, String_.new_a7(Bry_.Replace(tmp_bfr, Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(repl))));
}
@Test public void Split_bry() {
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
Split_bry_tst("a|" , "|" , String_.Ary("a"));
}
void Split_bry_tst(String src, String dlm, String[] expd) {
String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
Tfds.Eq_ary_str(expd, actl);
}
@Test public void Split_lines() {
Tst_split_lines("a\nb" , "a", "b"); // basic
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
Tst_split_lines("a\rb" , "a", "b"); // cr only
}
void Tst_split_lines(String src, String... expd) {
Tfds.Eq_ary(expd, New_ary(Bry_split_.Split_lines(Bry_.new_a7(src))));
}
String[] New_ary(byte[][] lines) {
int len = lines.length;
String[] rv = new String[len];
for (int i = 0; i < len; i++)
rv[i] = String_.new_u8(lines[i]);
return rv;
}
@Test public void Match_bwd_any() {
Tst_match_bwd_any("abc", 2, 0, "c", true);
Tst_match_bwd_any("abc", 2, 0, "b", false);
Tst_match_bwd_any("abc", 2, 0, "bc", true);
Tst_match_bwd_any("abc", 2, 0, "abc", true);
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
Tst_match_bwd_any("abc", 1, 0, "ab", true);
}
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
}
@Test public void Trim_end() {
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.one
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
}
@Test public void Mid_w_trim() {
fxt.Test_Mid_w_trim("abc", "abc"); // no ws
fxt.Test_Mid_w_trim(" a b c ", "a b c"); // ws at bgn and end
fxt.Test_Mid_w_trim("\r\n\t a\r\n\t b \r\n\t ", "a\r\n\t b"); // space at bgn and end
fxt.Test_Mid_w_trim("", ""); // handle 0 bytes
fxt.Test_Mid_w_trim(" ", ""); // handle all ws
}
@Test public void New_u8_nl_apos() {
fxt.Test__new_u8_nl_apos(String_.Ary("a"), "a");
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb");
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b'c", "d"), "a\nb\"c\nd");
}
@Test public void Repeat_bry() {
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
}
@Test public void Xcase__build__all() {
fxt.Test__xcase__build__all(Bool_.N, "abc", "abc");
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
}
}
class Bry__fxt {
private final Bry_bfr tmp = Bry_bfr_.New();
public void Test_trim_end(String raw, byte trim, String expd) {
byte[] raw_bry = Bry_.new_a7(raw);
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_end(raw_bry, trim, raw_bry.length)));
}
public void Test_new_u8(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_u8(raw));}
public void Test_new_a7(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_a7(raw));}
public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));}
public void Test_add(byte b, String s, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(b, Bry_.new_u8(s))));}
public void Test_add_w_dlm(String dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(Bry_.new_u8(dlm), Bry_.Ary(itms))));}
public void Test_add_w_dlm(byte dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(dlm, Bry_.Ary(itms))));}
public void Test_Mid_w_trim(String src, String expd) {byte[] bry = Bry_.new_u8(src); Tfds.Eq(expd, String_.new_u8(Bry_.Mid_w_trim(bry, 0, bry.length)));}
public void Test__new_u8_nl_apos(String[] ary, String expd) {
Tfds.Eq_str_lines(expd, String_.new_u8(Bry_.New_u8_nl_apos(ary)));
}
public void Test__repeat_bry(String s, int count, String expd) {
Gftest.Eq__str(expd, Bry_.Repeat_bry(Bry_.new_u8(s), count));
}
public void Test__xcase__build__all(boolean upper, String src, String expd) {
Gftest.Eq__str(expd, Bry_.Xcase__build__all(tmp, upper, Bry_.new_u8(src)));
}
}

@ -0,0 +1,717 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.encoders.*;
import gplx.langs.htmls.entitys.*;
public class Bry_bfr {
private Bry_bfr_mkr_mgr mkr_mgr; private int reset;
public byte[] Bfr() {return bfr;} private byte[] bfr;
public int Len() {return bfr_len;} private int bfr_len;
public boolean Len_eq_0() {return bfr_len == 0;}
public boolean Len_gt_0() {return bfr_len > 0;}
public void Bfr_init(byte[] bfr, int bfr_len) {
synchronized (this) {
this.bfr = bfr;
this.bfr_len = bfr_len;
this.bfr_max = bfr.length; // NOTE: must sync bfr_max, else will fail later during add; bfr will think bfr has .length of bfr_max, when it actually has .length of bfr_len; DATE:2014-03-09
}
}
public Bry_bfr Mkr_rls() {
if (mkr_mgr != null) {
synchronized (this) {
mkr_mgr.Rls(mkr_idx);
this.mkr_mgr = null;
this.mkr_idx = -1;
}
}
return this;
}
public void Clear_and_rls() {
this.Clear();
this.Mkr_rls();
}
public String To_str_and_rls() {return String_.new_u8(To_bry_and_rls());}
public byte[] To_bry_and_rls() {
byte[] rv = null;
synchronized (bfr) {
rv = To_bry();
this.Clear();
if (reset > 0) Reset_if_gt(reset);
synchronized (this) { // SAME: Mkr_rls()
mkr_mgr.Rls(mkr_idx);
mkr_idx = -1; // TS: DATE:2016-07-06
mkr_mgr = null;
}
}
return rv;
}
public Bry_bfr Reset_(int v) {reset = v; return this;}
public Bry_bfr Reset_if_gt(int limit) {
if (bfr_max > limit) {
this.bfr_max = limit;
this.bfr = new byte[limit];
}
bfr_len = 0;
return this;
}
public Bry_bfr Clear() {
synchronized (this) {
this.bfr_len = 0;
}
return this;
}
public Bry_bfr ClearAndReset() {bfr_len = 0; if (reset > 0) Reset_if_gt(reset); return this;}
public byte Get_at_last_or_nil_if_empty() {return bfr_len == 0 ? Byte_ascii.Null : bfr[bfr_len - 1];}
public Bry_bfr Add_safe(byte[] val) {return val == null ? this : Add(val);}
public Bry_bfr Add(byte[] val) {
int val_len = val.length;
if (bfr_len + val_len > bfr_max) Resize((bfr_max + val_len) * 2);
Bry_.Copy_by_pos(val, 0, val_len, bfr, bfr_len);
// Array_.Copy_to(val, 0, bfr, bfr_len, val_len);
bfr_len += val_len;
return this;
}
public Bry_bfr Add_mid(byte[] val, int bgn, int end) {
int len = end - bgn;
if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
Bry_.Copy_by_pos(val, bgn, end, bfr, bfr_len);
// Array_.Copy_to(val, bgn, bfr, bfr_len, len);
bfr_len += len;
return this;
}
public Bry_bfr Add_reverse_mid(byte[] val, int bgn, int end) {
int len = end - bgn;
if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
Bry_.Copy_by_pos_reversed(val, bgn, end, bfr, bfr_len);
// Array_.Copy_to(val, bgn, bfr, bfr_len, len);
bfr_len += len;
return this;
}
public Bry_bfr Add_mid_w_swap(byte[] val, int bgn, int end, byte swap_src, byte swap_trg) {
int len = end - bgn;
if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
int val_len = end - bgn;
for (int i = 0; i < val_len; ++i) {
byte b = val[i + bgn]; if (b == swap_src) b = swap_trg;
bfr[i + bfr_len] = b;
}
bfr_len += len;
return this;
}
public Bry_bfr Add_bry_ref_obj(Bry_obj_ref v) {v.Bfr_arg__add(this); return this;}
public Bry_bfr Add_bfr_and_preserve(Bry_bfr src) {
int len = src.bfr_len;
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
Bry_.Copy_by_pos(src.bfr, 0, len, bfr, bfr_len);
// Array_.Copy_to(src.bfr, 0, bfr, bfr_len, len);
bfr_len += len;
return this;
}
public Bry_bfr Add_bfr_and_clear(Bry_bfr src) {
Add_bfr_and_preserve(src);
src.ClearAndReset();
return this;
}
public Bry_bfr Add_bfr_or_mid(boolean escaped, Bry_bfr tmp_bfr, byte[] src, int src_bgn, int src_end) {
return escaped
? this.Add_bfr_and_clear(tmp_bfr)
: this.Add_mid(src, src_bgn, src_end);
}
public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end) {return Add_bfr_trim_and_clear(src, trim_bgn, trim_end, Bry_.Trim_ary_ws);}
public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
int src_len = src.bfr_len;
if (bfr_len + src_len > bfr_max) Resize((bfr_max + src_len) * 2);
byte[] src_bry = src.Bfr();
int src_bgn = 0, src_end = src_len;
boolean all_ws = true;
if (trim_bgn) {
for (int i = 0; i < src_len; i++) {
byte b = src_bry[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
src_bgn = i;
i = src_len;
all_ws = false;
}
}
if (all_ws) return this;
}
if (trim_end) {
for (int i = src_len - 1; i > -1; i--) {
byte b = src_bry[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
src_end = i + 1;
i = -1;
all_ws = false;
}
}
if (all_ws) return this;
}
src_len = src_end - src_bgn;
Bry_.Copy_by_pos(src.bfr, src_bgn, src_end, bfr, bfr_len);
// Array_.Copy_to(src.bfr, src_bgn, bfr, bfr_len, src_len);
bfr_len += src_len;
src.Clear();
return this;
}
public Bry_bfr Add_byte_as_a7(byte v) {return Add_byte((byte)(v + Byte_ascii.Num_0));}
public Bry_bfr Add_byte_eq() {return Add_byte(Byte_ascii.Eq);}
public Bry_bfr Add_byte_pipe() {return Add_byte(Byte_ascii.Pipe);}
public Bry_bfr Add_byte_comma() {return Add_byte(Byte_ascii.Comma);}
public Bry_bfr Add_byte_semic() {return Add_byte(Byte_ascii.Semic);}
public Bry_bfr Add_byte_apos() {return Add_byte(Byte_ascii.Apos);}
public Bry_bfr Add_byte_slash() {return Add_byte(Byte_ascii.Slash);}
public Bry_bfr Add_byte_backslash() {return Add_byte(Byte_ascii.Backslash);}
public Bry_bfr Add_byte_quote() {return Add_byte(Byte_ascii.Quote);}
public Bry_bfr Add_byte_space() {return Add_byte(Byte_ascii.Space);}
public Bry_bfr Add_byte_nl() {return Add_byte(Byte_ascii.Nl);}
public Bry_bfr Add_byte_dot() {return Add_byte(Byte_ascii.Dot);}
public Bry_bfr Add_byte_colon() {return Add_byte(Byte_ascii.Colon);}
public Bry_bfr Add_byte(byte val) {
int new_pos = bfr_len + 1;
if (new_pos > bfr_max) Resize(bfr_len * 2);
bfr[bfr_len] = val;
bfr_len = new_pos;
return this;
}
public Bry_bfr Add_byte_repeat(byte b, int len) {
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
for (int i = 0; i < len; i++)
bfr[i + bfr_len] = b;
bfr_len += len;
return this;
}
public Bry_bfr Add_byte_if_not_last(byte b) {
if (bfr_len == 0 || (bfr_len > 0 && bfr[bfr_len - 1] == b)) return this;
this.Add_byte(b);
return this;
}
public Bry_bfr Add_byte_variable(byte v) {return Add_int_variable(v);}
public Bry_bfr Add_short_variable(short v) {return Add_int_variable(v);}
public Bry_bfr Add_u8_int(int val) {
if (bfr_len + 4 > bfr_max) Resize((bfr_max + 4) * 2);
int utf8_len = gplx.core.intls.Utf16_.Encode_int(val, bfr, bfr_len);
bfr_len += utf8_len;
return this;
}
public Bry_bfr Add_bool(boolean v) {return Add(v ? Bool_.True_bry : Bool_.False_bry);}
public Bry_bfr Add_int_bool(boolean v) {return Add_int_fixed(v ? 1 : 0, 1);}
public Bry_bfr Add_int_variable(int val) {
if (val < 0) {
this.Add(Int_.To_bry(val));
return this;
}
int log10 = Int_.Log10(val);
int slots = val > -1 ? log10 + 1 : log10 * -1 + 2;
return Add_int(val, log10, slots);
}
public Bry_bfr Add_int_pad_bgn(byte pad_byte, int str_len, int val) {
int digit_len = Int_.DigitCount(val);
int pad_len = str_len - digit_len;
if (pad_len > 0) // note that this skips pad_len == 0, as well as guarding against negative pad_len; EX: pad(" ", 3, 1234) -> "1234"
Add_byte_repeat(pad_byte, pad_len);
Add_int_fixed(val, digit_len);
return this;
}
public Bry_bfr Add_int_digits(int digits, int val) {return Add_int(val, Int_.Log10(val), digits);}
public Bry_bfr Add_int_fixed(int val, int digits) {return Add_int(val, Int_.Log10(val), digits);}
public Bry_bfr Add_int(int val, int valLog, int arySlots) {
int aryBgn = bfr_len, aryEnd = bfr_len + arySlots;
if (aryEnd > bfr_max) Resize((aryEnd) * 2);
if (val < 0) {
bfr[aryBgn++] = Byte_ascii.Dash;
val *= -1; // make positive
valLog *= -1; // valLog will be negative; make positive
arySlots -= 1; // reduce slot by 1
}
if (valLog >= arySlots) {
val %= Int_.Log10Ary[arySlots];
}
for (int i = 0; i < arySlots; i++) {
int logIdx = arySlots - i - 1;
int div = logIdx < Int_.Log10AryLen ? Int_.Log10Ary[logIdx] : Int_.Max_value;
bfr[aryBgn + i] = (byte)((val / div) + 48);
val %= div;
}
bfr_len = aryEnd;
return this;
}
public Bry_bfr Add_long_variable(long v) {int digitCount = Long_.DigitCount(v); return Add_long(v, digitCount, digitCount);}
public Bry_bfr Add_long_fixed(long val, int digits) {return Add_long(val, Long_.DigitCount(val), digits);}
protected Bry_bfr Add_long(long val, int digitCount, int arySlots) {
int aryBgn = bfr_len, aryEnd = bfr_len + arySlots;
if (aryEnd > bfr_max) Resize((aryEnd) * 2);
if (val < 0) {
bfr[aryBgn++] = Byte_ascii.Dash;
val *= -1; // make positive
arySlots -= 1; // reduce slot by 1
}
if (digitCount >= arySlots) {
val %= Long_.Log10Ary[arySlots];
}
for (int i = 0; i < arySlots; i++) {
int logIdx = arySlots - i - 1;
long div = logIdx < Long_.Log10Ary_len ? Long_.Log10Ary[logIdx] : Long_.Max_value;
bfr[aryBgn + i] = (byte)((val / div) + 48);
val %= div;
}
bfr_len = aryEnd;
return this;
}
public Bry_bfr Add_bry_comma(byte[] v) {return Add_bry(Byte_ascii.Comma, v);}
public Bry_bfr Add_bry(byte dlm, byte[] v) {
if (v == null) return this;
int v_len = v.length;
for (int i = 0; i < v_len; i++) {
if (i != 0) this.Add_byte(dlm);
this.Add_int_variable(v[i]);
}
return this;
}
public Bry_bfr Add_bry_escape(byte quote_byte, byte[] escape, byte[] val, int bgn, int end) { // used for xml_wtr; DATE:2015-04-09
boolean clean = true; // add with chunks of bytes instead of one-by-one
for (int i = bgn; i < end; ++i) {
byte b = val[i];
if (clean) {
if (b == quote_byte) {
clean = false;
this.Add_mid(val, bgn, i);
this.Add(escape);
}
else {}
}
else {
if (b == quote_byte) this.Add(escape);
else this.Add_byte(b);
}
}
if (clean)
Add_mid(val, bgn, end);
return this;
}
public Bry_bfr Add_bry_many(byte[]... ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
byte[] bry = ary[i];
if (bry != null && bry.length > 0)
this.Add(bry);
}
return this;
}
public Bry_bfr Add_bry_escape_html(byte[] val) {
if (val == null) return this;
return Add_bry_escape_html(val, 0, val.length);
}
public Bry_bfr Add_bry_escape_html(byte[] val, int bgn, int end) {
Bry_.Escape_html(this, Bool_.N, val, bgn, end);
return this;
}
public Bry_bfr Add_bry_escape_xml(byte[] val, int bgn, int end) {
Bry_.Escape_html(this, Bool_.Y, val, bgn, end);
return this;
}
public Bry_bfr Add_str_u8_w_nl(String s) {Add_str_u8(s); return Add_byte_nl();}
public Bry_bfr Add_str_u8_null(String s) {return Add_str_u8(s == null ? String_.Null_mark : s);}
public Bry_bfr Add_str_u8(String str) {
try {
int str_len = str.length();
int bry_len = Bry_.new_u8__by_len(str, str_len);
if (bfr_len + bry_len > bfr_max) Resize((bfr_max + bry_len) * 2);
Bry_.new_u8__write(str, str_len, bfr, bfr_len);
bfr_len += bry_len;
return this;
}
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
}
public Bry_bfr Add_str_u8_many(String... ary) {
int len = ary.length;
for (int i = 0; i < len; ++i)
Add_str_u8(ary[i]);
return this;
}
public Bry_bfr Add_str_u8_fmt(String fmt, Object... args) {
Add_str_u8(String_.Format(fmt, args));
return this;
}
public Bry_bfr Add_str_a7_null(String s) {return Add_str_a7(s == null ? String_.Null_mark : s);}
public Bry_bfr Add_str_a7_w_nl(String s) {Add_str_a7(s); return Add_byte_nl();}
public Bry_bfr Add_str_a7(String str) {
try {
int bry_len = str.length();
if (bfr_len + bry_len > bfr_max) Resize((bfr_max + bry_len) * 2);
for (int i = 0; i < bry_len; ++i) {
char c = str.charAt(i);
if (c > 128) c = '?';
bfr[i + bfr_len] = (byte)c;
}
bfr_len += bry_len;
return this;
}
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
}
public Bry_bfr Add_kv_dlm(boolean line, String key, Object val) {
this.Add_str_a7(key).Add_byte_colon().Add_byte_space();
this.Add(Bry_.new_u8(Object_.Xto_str_strict_or_null_mark(val)));
this.Add_byte(line ? Byte_ascii.Nl : Byte_ascii.Tab);
return this;
}
public Bry_bfr Add_float(float f) {Add_str_a7(Float_.To_str(f)); return this;}
public Bry_bfr Add_double(double v) {Add_str_a7(Double_.To_str(v)); return this;}
public Bry_bfr Add_dte(DateAdp val) {return Add_dte_segs(val.Year(), val.Month(),val.Day(), val.Hour(), val.Minute(), val.Second(), val.Frac());}
public Bry_bfr Add_dte_segs(int y, int M, int d, int H, int m, int s, int f) { // yyyyMMdd HHmmss.fff
if (bfr_len + 19 > bfr_max) Resize((bfr_len + 19) * 2);
bfr[bfr_len + 0] = (byte)((y / 1000) + Bry_.Ascii_zero); y %= 1000;
bfr[bfr_len + 1] = (byte)((y / 100) + Bry_.Ascii_zero); y %= 100;
bfr[bfr_len + 2] = (byte)((y / 10) + Bry_.Ascii_zero); y %= 10;
bfr[bfr_len + 3] = (byte)( y + Bry_.Ascii_zero);
bfr[bfr_len + 4] = (byte)((M / 10) + Bry_.Ascii_zero); M %= 10;
bfr[bfr_len + 5] = (byte)( M + Bry_.Ascii_zero);
bfr[bfr_len + 6] = (byte)((d / 10) + Bry_.Ascii_zero); d %= 10;
bfr[bfr_len + 7] = (byte)( d + Bry_.Ascii_zero);
bfr[bfr_len + 8] = Byte_ascii.Space;
bfr[bfr_len + 9] = (byte)((H / 10) + Bry_.Ascii_zero); H %= 10;
bfr[bfr_len + 10] = (byte)( H + Bry_.Ascii_zero);
bfr[bfr_len + 11] = (byte)((m / 10) + Bry_.Ascii_zero); m %= 10;
bfr[bfr_len + 12] = (byte)( m + Bry_.Ascii_zero);
bfr[bfr_len + 13] = (byte)((s / 10) + Bry_.Ascii_zero); s %= 10;
bfr[bfr_len + 14] = (byte)( s + Bry_.Ascii_zero);
bfr[bfr_len + 15] = Byte_ascii.Dot;
bfr[bfr_len + 16] = (byte)((f / 100) + Bry_.Ascii_zero); f %= 100;
bfr[bfr_len + 17] = (byte)((f / 10) + Bry_.Ascii_zero); f %= 10;
bfr[bfr_len + 18] = (byte)( f + Bry_.Ascii_zero);
bfr_len += 19;
return this;
}
public Bry_bfr Add_dte_utc(int y, int M, int d, int H, int m, int s, int f) { // yyyy-MM-ddTHH:mm:ssZ
if (bfr_len + 20 > bfr_max) Resize((bfr_len + 20) * 2);
bfr[bfr_len + 0] = (byte)((y / 1000) + Bry_.Ascii_zero); y %= 1000;
bfr[bfr_len + 1] = (byte)((y / 100) + Bry_.Ascii_zero); y %= 100;
bfr[bfr_len + 2] = (byte)((y / 10) + Bry_.Ascii_zero); y %= 10;
bfr[bfr_len + 3] = (byte)( y + Bry_.Ascii_zero);
bfr[bfr_len + 4] = Byte_ascii.Dash;
bfr[bfr_len + 5] = (byte)((M / 10) + Bry_.Ascii_zero); M %= 10;
bfr[bfr_len + 6] = (byte)( M + Bry_.Ascii_zero);
bfr[bfr_len + 7] = Byte_ascii.Dash;
bfr[bfr_len + 8] = (byte)((d / 10) + Bry_.Ascii_zero); d %= 10;
bfr[bfr_len + 9] = (byte)( d + Bry_.Ascii_zero);
bfr[bfr_len + 10] = Byte_ascii.Ltr_T;
bfr[bfr_len + 11] = (byte)((H / 10) + Bry_.Ascii_zero); H %= 10;
bfr[bfr_len + 12] = (byte)( H + Bry_.Ascii_zero);
bfr[bfr_len + 13] = Byte_ascii.Colon;
bfr[bfr_len + 14] = (byte)((m / 10) + Bry_.Ascii_zero); m %= 10;
bfr[bfr_len + 15] = (byte)( m + Bry_.Ascii_zero);
bfr[bfr_len + 16] = Byte_ascii.Colon;
bfr[bfr_len + 17] = (byte)((s / 10) + Bry_.Ascii_zero); s %= 10;
bfr[bfr_len + 18] = (byte)( s + Bry_.Ascii_zero);
bfr[bfr_len + 19] = Byte_ascii.Ltr_Z;
bfr_len += 20;
return this;
}
public Bry_bfr Add_swap_ws(byte[] src) {return Add_swap_ws(src, 0, src.length);}
public Bry_bfr Add_swap_ws(byte[] src, int bgn, int end) {
int len = end - bgn;
if (bfr_len + (len * 2) > bfr_max) Resize((bfr_max + (len * 2)) * 2);
for (int i = bgn; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Nl: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Ltr_n; bfr_len += 2; break;
case Byte_ascii.Tab: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Ltr_t; bfr_len += 2; break;
case Byte_ascii.Backslash: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Backslash; bfr_len += 2; break;
default: bfr[bfr_len] = b; ++bfr_len; break;
}
}
return this;
}
public Bry_bfr Add_str_pad_space_bgn(String v, int pad_max) {return Add_str_pad_space(v, pad_max, Bool_.N);}
public Bry_bfr Add_str_pad_space_end(String v, int pad_max) {return Add_str_pad_space(v, pad_max, Bool_.Y);}
Bry_bfr Add_str_pad_space(String v, int pad_max, boolean pad_end) {
byte[] v_bry = Bry_.new_u8(v);
if (pad_end) Add(v_bry);
int pad_len = pad_max - v_bry.length;
if (pad_len > 0)
Add_byte_repeat(Byte_ascii.Space, pad_len);
if (!pad_end) Add(v_bry);
return this;
}
public Bry_bfr Add_obj(Object o) {
if (o == null) return this; // treat null as empty String;
Class<?> o_type = o.getClass();
if (o_type == byte[].class) Add((byte[])o);
else if (o_type == Integer.class) Add_int_variable(Int_.Cast(o));
else if (o_type == Byte.class) Add_byte(Byte_.Cast(o));
else if (o_type == Long.class) Add_long_variable(Long_.cast(o));
else if (o_type == String.class) Add_str_u8((String)o);
else if (o_type == Bry_bfr.class) Add_bfr_and_preserve((Bry_bfr)o);
else if (o_type == DateAdp.class) Add_dte((DateAdp)o);
else if (o_type == Io_url.class) Add(((Io_url)o).RawBry());
else if (o_type == Boolean.class) Add_yn(Bool_.Cast(o));
else if (o_type == Double.class) Add_double(Double_.cast(o));
else if (o_type == Float.class) Add_float(Float_.cast(o));
else ((Bfr_arg)o).Bfr_arg__add(this);
return this;
}
public Bry_bfr Add_obj_strict(Object o) {
if (o == null) return this; // treat null as empty String;
Class<?> o_type = o.getClass();
if (o_type == byte[].class) Add((byte[])o);
else if (o_type == Integer.class) Add_int_variable(Int_.Cast(o));
else if (o_type == Byte.class) Add_byte(Byte_.Cast(o));
else if (o_type == Long.class) Add_long_variable(Long_.cast(o));
else if (o_type == String.class) Add_str_u8((String)o);
else if (o_type == Bry_bfr.class) Add_bfr_and_preserve((Bry_bfr)o);
else if (o_type == DateAdp.class) Add_dte((DateAdp)o);
else if (o_type == Io_url.class) Add(((Io_url)o).RawBry());
else if (o_type == Boolean.class) Add_bool(Bool_.Cast(o));
else if (o_type == Double.class) Add_double(Double_.cast(o));
else if (o_type == Float.class) Add_float(Float_.cast(o));
else ((Bfr_arg)o).Bfr_arg__add(this);
return this;
}
public Bry_bfr Add_yn(boolean v) {Add_byte(v ? Byte_ascii.Ltr_y : Byte_ascii.Ltr_n); return this;}
public Bry_bfr Add_base85_len_5(int v) {return Add_base85(v, 5);}
public Bry_bfr Add_base85(int v, int pad) {
int new_len = bfr_len + pad;
if (new_len > bfr_max) Resize((new_len) * 2);
Base85_.Set_bry(v, bfr, bfr_len, pad);
bfr_len = new_len;
return this;
}
public boolean Match_end_byt(byte b) {return bfr_len == 0 ? false : bfr[bfr_len - 1] == b;}
public boolean Match_end_byt_nl_or_bos() {return bfr_len == 0 ? true : bfr[bfr_len - 1] == Byte_ascii.Nl;}
public boolean Match_end_ary(byte[] ary) {return Bry_.Match(bfr, bfr_len - ary.length, bfr_len, ary);}
public Bry_bfr Insert_at(int add_pos, byte[] add_bry) {return Insert_at(add_pos, add_bry, 0, add_bry.length);}
public Bry_bfr Insert_at(int add_pos, byte[] add_bry, int add_bgn, int add_end) {
int add_len = add_end - add_bgn;
int new_max = bfr_max + add_len;
byte[] new_bfr = new byte[new_max];
if (add_pos > 0)
Bry_.Copy_by_pos (bfr , 0, add_pos, new_bfr, 0);
Bry_.Copy_by_pos (add_bry, add_bgn, add_end, new_bfr, add_pos);
Bry_.Copy_by_pos (bfr , add_pos, bfr_len, new_bfr, add_pos + add_len);
bfr = new_bfr;
bfr_len += add_len;
bfr_max = new_max;
return this;
}
public Bry_bfr Delete_rng_to_bgn(int pos) {return Delete_rng(0, pos);}
public Bry_bfr Delete_rng_to_end(int pos) {return Delete_rng(pos, bfr_len);}
public Bry_bfr Delete_rng(int rng_bgn, int rng_end) {
int rng_len = rng_end - rng_bgn;
Bry_.Copy_by_pos(bfr, rng_end, bfr_len, bfr, rng_bgn);
bfr_len -= rng_len;
return this;
}
public Bry_bfr Del_by_1() {
bfr_len -= 1; bfr[bfr_len] = 0; return this;
}
public Bry_bfr Del_by(int count) {
int new_len = bfr_len - count;
if (new_len > -1) bfr_len = new_len;
return this;
}
public Bry_bfr Trim_end(byte trim_byte) {
if (bfr_len == 0) return this;
int count = 0;
for (int i = bfr_len - 1; i > -1; --i) {
byte b = bfr[i];
if (b == trim_byte)
++count;
else
break;
}
if (count > 0)
this.Del_by(count);
return this;
}
public Bry_bfr Trim_end_ws() {
if (bfr_len == 0) return this;
int count = 0;
for (int i = bfr_len - 1; i > -1; --i) {
byte b = bfr[i];
if (Trim_end_ws_ary[b])
++count;
else
break;
}
if (count > 0)
this.Del_by(count);
return this;
}
private static final boolean[] Trim_end_ws_ary = Trim_end_ws_new();
private static boolean[] Trim_end_ws_new() {
boolean[] rv = new boolean[256];
rv[32] = true;
rv[ 9] = true;
rv[10] = true;
rv[13] = true;
rv[11] = true;
return rv;
}
public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
boolean itm_has_bytes = Bry_.Len_gt_0(itm);
if ( i != 0
&& itm_has_bytes
&& bfr_len > 0
)
this.Add(dlm);
if (itm_has_bytes)
this.Add(itm);
}
return this;
}
public boolean Eq(byte b) {return bfr_len == 1 && bfr[0] == b;}
public byte[] To_bry(int bgn, int end) {return bfr_len == 0 ? Bry_.Empty : Bry_.Mid(bfr, bgn, end);}
public byte[] To_bry() {return bfr_len == 0 ? Bry_.Empty : Bry_.Mid(bfr, 0, bfr_len);}
public byte[] To_bry_and_clear_and_trim() {return To_bry_and_clear_and_trim(true, true, Bry_.Trim_ary_ws);}
public byte[] To_bry_and_clear_and_trim(boolean trim_bgn, boolean trim_end, byte[] trim_bry) {
byte[] rv = Bry_.Trim(bfr, 0, bfr_len, trim_bgn, trim_end, trim_bry);
this.Clear();
return rv;
}
public byte[] To_bry_and_clear() {
byte[] rv = To_bry();
this.Clear();
if (reset > 0) Reset_if_gt(reset);
return rv;
}
public byte[] To_bry_and_clear_and_rls() {
byte[] rv = To_bry_and_clear();
this.Mkr_rls();
return rv;
}
public byte[] To_reversed_bry_and_clear() {
int len = this.Len();
byte[] rv = new byte[len];
for (int i = 0; i < len; i++) {
rv[len - i - 1] = bfr[i];
}
this.Clear();
if (reset > 0) Reset_if_gt(reset);
return rv;
}
public String To_str() {return String_.new_u8(To_bry());}
public String To_str_by_pos(int bgn, int end) {return String_.new_u8(To_bry(), bgn, end);}
public String To_str_and_clear() {return String_.new_u8(To_bry_and_clear());}
public String To_str_and_clear_and_trim() {return String_.new_u8(To_bry_and_clear_and_trim());}
public int To_int_and_clear(int or) {int rv = To_int(or); this.Clear(); return rv;}
public int To_int(int or) {
switch (bfr_len) {
case 0: return or;
case 1: {
byte b = bfr[0];
return Byte_ascii.Is_num(b) ? b - Byte_ascii.Num_0 : or;
}
default:
long rv = 0, mult = 1;
for (int i = bfr_len - 1; i > -1; i--) {
byte b = bfr[i];
if (!Byte_ascii.Is_num(b)) return or;
long dif = (b - Byte_ascii.Num_0 ) * mult;
long new_val = rv + dif;
if (new_val > Int_.Max_value) return or; // if number is > 2^32 consider error (int overflow); return or; DATE:2014-06-10
rv = new_val;
mult *= 10;
}
return (int)rv;
}
}
public void Rls() {
bfr = null;
this.Mkr_rls();
}
public byte[][] To_bry_ary_and_clear() {
if (bfr_len == 0) return Bry_.Ary_empty;
Int_list line_ends = Find_all(Byte_ascii.Nl);
// create lines
int lines_len = line_ends.Len();
byte[][] rv = new byte[lines_len][];
int line_bgn = 0;
for (int i = 0; i < lines_len; ++i) {
int line_end = line_ends.Get_at(i);
rv[i] = Bry_.Mid(bfr, line_bgn, line_end);
line_bgn = line_end + 1;
}
this.ClearAndReset();
return rv;
}
public String[] To_str_ary_and_clear() {
if (bfr_len == 0) return String_.Ary_empty;
Int_list line_ends = Find_all(Byte_ascii.Nl);
// create lines
int lines_len = line_ends.Len();
String[] rv = new String[lines_len];
int line_bgn = 0;
for (int i = 0; i < lines_len; ++i) {
int line_end = line_ends.Get_at(i);
rv[i] = String_.new_u8(bfr, line_bgn, line_end);
line_bgn = line_end + 1;
}
this.ClearAndReset();
return rv;
}
private Int_list Find_all(byte find) {
Int_list rv = new Int_list();
// scan bfr for nl
int line_bgn = 0, line_end = 0;
while (line_bgn < bfr_len) {
line_end = Bry_find_.Find_fwd(bfr, find, line_bgn, bfr_len);
if (line_end == Bry_find_.Not_found) { // no more \n; add bfr_end
rv.Add(bfr_len);
break;
}
else { // \n found; add it
rv.Add(line_end);
line_bgn = line_end + 1;
}
}
return rv;
}
@Override public int hashCode() {return Bry_obj_ref.CalcHashCode(bfr, 0, bfr_len);}
@Override public boolean equals(Object obj) {
if (obj == null) return false; // NOTE: strange, but null check needed; throws null error; EX.WP: File:Eug<75>ne Delacroix - La libert<72> guidant le peuple.jpg
Bry_obj_ref comp = (Bry_obj_ref)obj;
return Bry_.Match(bfr, 0, bfr_len, comp.Val(), comp.Val_bgn(), comp.Val_end());
}
public void Resize(int v) {
bfr_max = v;
bfr = Bry_.Resize(bfr, 0, v);
}
public int Mkr_idx() {return mkr_idx;} private int mkr_idx = -1;
public boolean Mkr_idx_is_null() {return mkr_idx == -1;}
public int Bfr_max() {return bfr_max;} private int bfr_max;
public Bry_bfr Mkr_init(Bry_bfr_mkr_mgr mkr_mgr, int itm) {
synchronized (this) {
this.mkr_mgr = mkr_mgr; this.mkr_idx = itm;
}
return this;
}
protected Bry_bfr() {}
public Bry_bfr(int bfr_max) {
Init(bfr_max);
}
protected void Init(int bfr_max) {
this.bfr_max = bfr_max;
this.bfr = new byte[bfr_max];
}
}

@ -0,0 +1,43 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.brys.*;
public class Bry_bfr_ {
public static Bry_bfr New() {return new Bry_bfr(16);}
public static Bry_bfr New_w_size(int v) {return new Bry_bfr(v);}
public static Bry_bfr Reset(int v) {return new Bry_bfr(16).Reset_(v);} // PERF: set initial size to 16, not reset val; allows for faster "startup"; DATE:2014-06-14
public static final Bry_bfr[] Ary_empty = new Bry_bfr[0];
private static Bry_bfr_mkr_mgr dflt;
public static Bry_bfr Get() {if (dflt == null) dflt = new Bry_bfr_mkr_mgr(Bry_bfr_mkr.Tid_b128, 128); return dflt.Get();} // NOTE: lazy else "Object synchronization" error; DATE:2015-11-18
public static void Assert_at_end(Bry_bfr bfr, byte assert_byte) {
int len = bfr.Len(); if (len == 0) return;
int assert_count = 0;
byte[] bfr_bry = bfr.Bfr();
for (int i = len - 1; i > -1; --i) {
byte b = bfr_bry[i];
if (b == assert_byte)
++assert_count;
else
break;
}
switch (assert_count) {
case 0: bfr.Add_byte(assert_byte); break;
case 1: break;
default: bfr.Del_by(assert_count - 1); break;
}
}
}

@ -0,0 +1,247 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*;
public class Bry_bfr_tst {
private Bry_bfr bb = Bry_bfr_.New();
@Before public void setup() {bb.Clear();} private ByteAryBfr_fxt fxt = new ByteAryBfr_fxt();
@Test public void AddByte() {
bb = Bry_bfr_.New_w_size(2); // NOTE: make sure auto-expands
tst_AddByte("a", "a", 2);
tst_AddByte("b", "ab", 2);
tst_AddByte("c", "abc", 4);
}
@Test public void AddAry() { // NOTE: make sure auto-expands
bb = Bry_bfr_.New_w_size(2);
tst_AddByte("abcd", "abcd", 12);
}
@Test public void Add_byte_repeat() { // NOTE: make sure auto-expands
bb = Bry_bfr_.New_w_size(2);
tst_Add_byte_repeat(Byte_ascii.Space, 12, String_.Repeat(" ", 12));
} void tst_Add_byte_repeat(byte b, int len, String expd) {Tfds.Eq(expd, bb.Add_byte_repeat(b, len).To_str_and_clear());}
void tst_AddByte(String s, String expdStr, int expdLen) {
if (String_.Len(s) == 1)
bb.Add_byte((byte)String_.CharAt(s, 0));
else
bb.Add(Bry_.new_u8(s));
Tfds.Eq(expdStr, String_.new_u8(bb.To_bry()));
Tfds.Eq(expdLen, bb.Bfr_max());
}
@Test public void Add_dte() {
tst_AddDte("20110801 221435.987");
}
void tst_AddDte(String raw) {
bb.Add_dte(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte));
Tfds.Eq(raw, String_.new_u8(bb.To_bry()));
}
@Test public void Add_int_variable() {
Add_int_variable(-1);
Add_int_variable(-12);
Add_int_variable(-1234);
Add_int_variable(2);
Add_int_variable(12);
Add_int_variable(1234);
Add_int_variable(123456789);
}
@Test public void Add_float() {
tst_Add_float(1 / 3);
tst_Add_float(-1 / 3);
}
void tst_Add_float(float v) {
bb.Add_float(v);
Tfds.Eq(v, Float_.parse(String_.new_u8(bb.To_bry())));
}
void Add_int_variable(int val) {
bb.Clear();
bb.Add_int_variable(val);
Tfds.Eq(val, Int_.Parse(String_.new_u8(bb.To_bry())));
}
@Test public void Add_int_fixed_len3() {tst_Add_int_fixed(123, 3, "123");}
@Test public void Add_int_fixed_pad_1() {tst_Add_int_fixed(2, 1, "2");}
@Test public void Add_int_fixed_pad_2() {tst_Add_int_fixed(2, 2, "02");}
@Test public void Add_int_fixed_pad_16() {tst_Add_int_fixed(2, 16, "0000000000000002");} // test overflows int
@Test public void Add_int_fixed_neg() {tst_Add_int_fixed(-2, 2, "-2");}
@Test public void Add_int_fixed_neg_pad1() {tst_Add_int_fixed(-2, 1, "-");}
@Test public void Add_int_fixed_chop_1() {tst_Add_int_fixed(123, 1, "3");}
@Test public void Add_int_fixed_chop_neg() {tst_Add_int_fixed(-21, 2, "-1");}
void tst_Add_int_fixed(int val, int digits, String expd) {Tfds.Eq(expd, String_.new_u8(bb.Add_int_fixed(val, digits).To_bry()));}
@Test public void Add_long_fixed_len3() {tst_Add_long_fixed(123, 3, "123");}
@Test public void Add_long_fixed_pad_1() {tst_Add_long_fixed(2, 1, "2");}
@Test public void Add_long_fixed_pad_2() {tst_Add_long_fixed(2, 2, "02");}
@Test public void Add_long_fixed_pad_16() {tst_Add_long_fixed(2, 16, "0000000000000002");} // test overflows long
@Test public void Add_long_fixed_neg() {tst_Add_long_fixed(-2, 2, "-2");}
@Test public void Add_long_fixed_neg_pad1() {tst_Add_long_fixed(-2, 1, "-");}
@Test public void Add_long_fixed_chop_1() {tst_Add_long_fixed(123, 1, "3");}
@Test public void Add_long_fixed_chop_neg() {tst_Add_long_fixed(-21, 2, "-1");}
@Test public void Add_long_fixed_large() {tst_Add_long_fixed(123456789012345L, 15, "123456789012345");}
void tst_Add_long_fixed(long val, int digits, String expd) {Tfds.Eq(expd, String_.new_u8(bb.Add_long_fixed(val, digits).To_bry()));}
@Test public void AddDte_short() {
tst_AddDte_short("2010-08-26T22:38:36Z");
}
void tst_AddDte_short(String raw) {
// byte[] ary = String_.XtoByteAryAscii(raw);
// Bry_fmtr_IntBldr ib = new Bry_fmtr_IntBldr();
// int y = 0, m = 0, d = 0, h = 0, n = 0, s = 0, aryLen = ary.length;
// for (int i = 0; i < aryLen; i++) {
// byte b = ary[i];
// switch (i) {
// case 4: y = ib.To_int_and_clear(); break;
// case 7: m = ib.To_int_and_clear(); break;
// case 10: d = ib.To_int_and_clear(); break;
// case 13: h = ib.To_int_and_clear(); break;
// case 16: n = ib.To_int_and_clear(); break;
// case 19: s = ib.To_int_and_clear(); break;
// default: ib.Add(b); break;
// }
// }
// long l = Pow38_to(y, m, d, h, n, s);
//// Base85_.Set_bry(l, bb.
// bb.Add_int(l);
}
// @Test public void InsertAt_str() {
// tst_InsertAt_str("", 0, "c", "c");
// tst_InsertAt_str("ab", 0, "c", "cab");
// tst_InsertAt_str("ab", 0, "cdefghij", "cdefghijab");
// }
// void tst_InsertAt_str(String orig, int insertAt, String insertStr, String expd) {
// bb = Bry_bfr_.New(16);
// bb.Add_str(orig);
// bb.InsertAt_str(insertAt, insertStr);
// String actl = bb.To_str_and_clear();
// Tfds.Eq(expd, actl);
// }
@Test public void To_bry_and_clear_and_trim() {
tst_XtoAryAndClearAndTrim("a" , "a");
tst_XtoAryAndClearAndTrim(" a " , "a");
tst_XtoAryAndClearAndTrim(" a b " , "a b");
tst_XtoAryAndClearAndTrim(" " , "");
}
void tst_XtoAryAndClearAndTrim(String raw, String expd) {
bb.Add_str_u8(raw);
Tfds.Eq(expd, String_.new_u8(bb.To_bry_and_clear_and_trim()));
}
@Test public void XtoInt() {
tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.Min_value);
tst_XtoInt("9999999999", Int_.Min_value);
}
void tst_XtoInt(String raw, int expd) {
bb.Add_str_u8(raw);
Tfds.Eq(expd, bb.To_int_and_clear(Int_.Min_value));
}
static long Pow38_to(int year, int month, int day, int hour, int minute, int second, int frac) {
return ((long)year) << 26
| ((long)month & 0x0f) << 22 // 16
| ((long)day & 0x1f) << 17 // 32
| ((long)hour & 0x1f) << 12 // 32
| ((long)minute & 0x3f) << 6 // 64
| ((long)second & 0x3f) // 64
;
}
static DateAdp Pow38_by(long v) {
int year = (int) (v >> 26);
int month = (int)((v >> 22) & 0x0f);
int day = (int)((v >> 17) & 0x1f);
int hour = (int)((v >> 12) & 0x1f);
int minute = (int)((v >> 6) & 0x3f);
int second = (int)((v ) & 0x3f);
return DateAdp_.new_(year, month, day, hour, minute, second, 0);
}
@Test public void Add_bfr_trimEnd_and_clear() {
tst_Add_bfr_trimEnd_and_clear("a ", "a");
}
void tst_Add_bfr_trimEnd_and_clear(String raw, String expd) {
Bry_bfr tmp = Bry_bfr_.New().Add_str_u8(raw);
Tfds.Eq(expd, bb.Add_bfr_trim_and_clear(tmp, false, true).To_str_and_clear());
}
@Test public void Add_bfr_trimAll_and_clear() {
tst_Add_bfr_trimAll_and_clear(" a ", "a");
tst_Add_bfr_trimAll_and_clear(" a b ", "a b");
tst_Add_bfr_trimAll_and_clear("a", "a");
tst_Add_bfr_trimAll_and_clear("", "");
}
void tst_Add_bfr_trimAll_and_clear(String raw, String expd) {
Bry_bfr tmp = Bry_bfr_.New().Add_str_u8(raw);
Tfds.Eq(expd, bb.Add_bfr_trim_and_clear(tmp, true, true).To_str_and_clear());
}
@Test public void Add_int_pad_bgn() {
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 0, "000");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 1, "001");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 10, "010");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 100, "100");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 1000, "1000");
}
@Test public void Add_bry_escape() {
fxt.Test__add_bry_escape("abc" , "abc"); // nothing to escape
fxt.Test__add_bry_escape("a'bc" , "a''bc"); // single escape (code handles first quote differently)
fxt.Test__add_bry_escape("a'b'c" , "a''b''c"); // double escape (code handles subsequent quotes different than first)
fxt.Test__add_bry_escape("abc", 1, 2 , "b"); // nothing to escape
}
@Test public void Add_bry_escape_html() {
fxt.Test__add_bry_escape_html("abc" , "abc"); // escape=none
fxt.Test__add_bry_escape_html("a&\"'<>b" , "a&amp;&quot;&#39;&lt;&gt;b"); // escape=all; code handles first escape differently
fxt.Test__add_bry_escape_html("a&b&c" , "a&amp;b&amp;c"); // staggered; code handles subsequent escapes differently
fxt.Test__add_bry_escape_html("abc", 1, 2 , "b"); // by index; fixes bug in initial implementation
}
@Test public void Insert_at() {
fxt.Test_Insert_at("abcd", 0, "xyz" , "xyzabcd"); // bgn
fxt.Test_Insert_at("abcd", 4, "xyz" , "abcdxyz"); // end
fxt.Test_Insert_at("abcd", 2, "xyz" , "abxyzcd"); // mid
fxt.Test_Insert_at("abcd", 2, "xyz", 1, 2 , "abycd"); // mid
}
@Test public void Delete_rng() {
fxt.Test_Delete_rng("abcd", 0, 2 , "cd"); // bgn
fxt.Test_Delete_rng("abcd", 2, 4 , "ab"); // end
fxt.Test_Delete_rng("abcd", 1, 3 , "ad"); // mid
}
@Test public void Delete_rng_to_bgn() {
fxt.Test_Delete_rng_to_bgn("abcd", 2 , "cd");
}
@Test public void Delete_rng_to_end() {
fxt.Test_Delete_rng_to_end("abcd", 2 , "ab");
}
@Test public void To_bry_ary_and_clear() {
fxt.Test__to_bry_ary_and_clear("" ); // empty
fxt.Test__to_bry_ary_and_clear("a" , "a"); // lines=1
fxt.Test__to_bry_ary_and_clear("a\nb\nc" , "a", "b", "c"); // lines=n
fxt.Test__to_bry_ary_and_clear("a\n" , "a"); // nl at end
}
}
class ByteAryBfr_fxt {
private final Bry_bfr bfr = Bry_bfr_.Reset(16);
public Bry_bfr Bfr() {return bfr;}
public void Clear() {
bfr.ClearAndReset();
}
public void Test_Add_int_pad_bgn(byte pad_byte, int str_len, int val, String expd) {Tfds.Eq(expd, bfr.Add_int_pad_bgn(pad_byte, str_len, val).To_str_and_clear());}
public void Test__add_bry_escape(String src, String expd) {Test__add_bry_escape(src, 0, String_.Len(src), expd);}
public void Test__add_bry_escape(String src, int src_bgn, int src_end, String expd) {
byte[] val_bry = Bry_.new_u8(src);
Tfds.Eq(expd, bfr.Add_bry_escape(Byte_ascii.Apos, Byte_.Ary(Byte_ascii.Apos, Byte_ascii.Apos), val_bry, src_bgn, src_end).To_str_and_clear());
}
public void Test_Insert_at(String init, int pos, String val, String expd) {Tfds.Eq(expd, bfr.Add_str_u8(init).Insert_at(pos, Bry_.new_u8(val)).To_str_and_clear());}
public void Test_Insert_at(String init, int pos, String val, int val_bgn, int val_end, String expd) {Tfds.Eq(expd, bfr.Add_str_u8(init).Insert_at(pos, Bry_.new_u8(val), val_bgn, val_end).To_str_and_clear());}
public void Test_Delete_rng(String init, int bgn, int end, String expd) {Tfds.Eq(expd, bfr.Add_str_u8(init).Delete_rng(bgn, end).To_str_and_clear());}
public void Test_Delete_rng_to_bgn(String init, int pos, String expd) {Tfds.Eq(expd, bfr.Add_str_u8(init).Delete_rng_to_bgn(pos).To_str_and_clear());}
public void Test_Delete_rng_to_end(String init, int pos, String expd) {Tfds.Eq(expd, bfr.Add_str_u8(init).Delete_rng_to_end(pos).To_str_and_clear());}
public void Test__to_bry_ary_and_clear(String bfr_str, String... expd) {
Tfds.Eq_ary(expd, String_.Ary(bfr.Add_str_u8(bfr_str).To_bry_ary_and_clear()));
}
public void Test__add_bry_escape_html(String src, String expd) {Test__add_bry_escape_html(src, 0, String_.Len(src), expd);}
public void Test__add_bry_escape_html(String src, int src_bgn, int src_end, String expd) {
Gftest.Eq__bry(Bry_.new_u8(expd), bfr.Add_bry_escape_html(Bry_.new_u8(src), src_bgn, src_end).To_bry_and_clear());
}
}

@ -0,0 +1,402 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Bry_find_ {
public static final int Not_found = -1;
public static int Find_fwd(byte[] src, byte lkp) {return Find_fwd(src, lkp, 0, src.length);}
public static int Find_fwd(byte[] src, byte lkp, int cur) {return Find_fwd(src, lkp, cur, src.length);}
public static int Find_fwd(byte[] src, byte lkp, int cur, int end) {
for (int i = cur; i < end; i++)
if (src[i] == lkp) return i;
return Bry_find_.Not_found;
}
public static int Find_fwd_or(byte[] src, byte lkp, int cur, int end, int or) {
int rv = Find_fwd(src, lkp, cur, end);
return rv == Bry_find_.Not_found ? or : rv;
}
public static int Find_fwd_or(byte[] src, byte[] lkp, int cur, int end, int or) {
int rv = Find_fwd(src, lkp, cur, end);
return rv == Bry_find_.Not_found ? or : rv;
}
public static int Find_bwd(byte[] src, byte lkp) {return Find_bwd(src, lkp, src.length, 0);}
public static int Find_bwd(byte[] src, byte lkp, int cur) {return Find_bwd(src, lkp, cur , 0);}
public static int Find_bwd(byte[] src, byte lkp, int cur, int end) {
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
--end;
for (int i = cur; i > end; i--)
if (src[i] == lkp) return i;
return Bry_find_.Not_found;
}
public static int Move_fwd(byte[] src, byte lkp, int cur, int end) {
int rv = Find_fwd(src, lkp, cur, src.length);
return rv == Bry_find_.Not_found ? rv : rv + 1;
}
public static int Move_fwd(byte[] src, byte[] lkp, int cur) {return Move_fwd(src, lkp, cur, src.length);}
public static int Move_fwd(byte[] src, byte[] lkp, int cur, int end) {
int rv = Find_fwd(src, lkp, cur, src.length);
return rv == Bry_find_.Not_found ? rv : rv + lkp.length;
}
public static int Find_fwd(byte[] src, byte[] lkp) {return Find(src, lkp, 0 , src.length, true);}
public static int Find_fwd(byte[] src, byte[] lkp, int cur) {return Find(src, lkp, cur , src.length, true);}
public static int Find_fwd(byte[] src, byte[] lkp, int cur, int end) {return Find(src, lkp, cur , end, true);}
private static final int OffsetCompare = 1;// handle srcPos >= 1 -> srcPosChk > 0
public static int Find(byte[] src, byte[] lkp, int src_bgn, int src_end, boolean fwd) {
if (src_bgn < 0 || src.length == 0) return Bry_find_.Not_found;
int dif, lkp_len = lkp.length, lkp_bgn, lkp_end, src_end_chk;
if (fwd) {
if (src_bgn > src_end) return Bry_find_.Not_found;
dif = 1; lkp_bgn = 0; lkp_end = lkp_len; src_end_chk = src_end - OffsetCompare;
}
else {
if (src_bgn < src_end) return Bry_find_.Not_found;
dif = -1; lkp_bgn = lkp_len - 1; lkp_end = -1; src_end_chk = src.length - OffsetCompare; // src_end_chk needed when going bwd, b/c lkp_len may be > 1
}
while (src_bgn != src_end) { // while src is not done;
int lkp_cur = lkp_bgn;
while (lkp_cur != lkp_end) { // while lkp is not done
int pos = src_bgn + lkp_cur;
if ( pos > src_end_chk // outside bounds; occurs when lkp_len > 1
|| src[pos] != lkp[lkp_cur]) // srcByte doesn't match lkpByte
break;
else
lkp_cur += dif;
}
if (lkp_cur == lkp_end) return src_bgn; // lkp matches src; exit
src_bgn += dif;
}
return Bry_find_.Not_found;
}
public static int Find_bwd(byte[] src, byte[] lkp, int cur) {return Find_bwd(src, lkp, cur , 0);}
public static int Find_bwd(byte[] src, byte[] lkp, int cur, int end) {
if (cur < 1) return Bry_find_.Not_found;
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
--end;
int src_len = src.length;
int lkp_len = lkp.length;
for (int i = cur; i > end; i--) {
if (i + lkp_len > src_len) continue; // lkp too small for pos; EX: src=abcde; lkp=bcd; pos=4
boolean match = true;
for (int j = 0; j < lkp_len; j++) {
if (lkp[j] != src[i + j]) {
match = false;
break;
}
}
if (match) return i;
}
return Bry_find_.Not_found;
}
public static int Find_bwd_last_ws(byte[] src, int cur) {
if (cur < 1) return Bry_find_.Not_found;
--cur;
int rv = Bry_find_.Not_found;
for (int i = cur; i > -1; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
rv = i;
break;
default:
i = -1;
break;
}
}
return rv;
}
public static int Find_bwd_ws(byte[] src, int cur, int end) {
for (int i = cur; i > -1; --i) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
return i;
}
}
return Bry_find_.Not_found;
}
public static int Find_fwd_last_ws(byte[] src, int cur) {
int end = src.length;
if (cur >= end) return Bry_find_.Not_found;
int rv = Bry_find_.Not_found;
for (int i = cur; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
rv = i;
break;
default:
i = -1;
break;
}
}
return rv;
}
public static int Find_bwd_non_ws_or_not_found(byte[] src, int cur, int end) { // get pos of 1st char that is not ws;
if (cur >= src.length) return Bry_find_.Not_found;
for (int i = cur; i >= end; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
break;
default:
return i;
}
}
return Bry_find_.Not_found;
}
public static int Find_bwd__while_space_or_tab(byte[] src, int cur, int end) { // get pos of 1st char that is not \t or \s
if (cur < 0 || cur > src.length) return Bry_find_.Not_found;
for (int i = cur - 1; i >= end; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab:
break;
default:
return i + 1;
}
}
return Bry_find_.Not_found;
}
public static int Find_bwd_non_ws_or_end(byte[] src, int cur, int end) {
if (cur >= src.length) return Bry_find_.Not_found;
for (int i = cur; i >= end; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
break;
default:
return i;
}
}
return end;
}
public static int Find_bwd__skip_ws(byte[] src, int end, int bgn) {
int src_len = src.length;
if (end == src_len) return end;
if (end > src_len || end < 0) return Bry_find_.Not_found;
int pos = end - 1; // start from end - 1; handles situations where len is passed in
for (int i = pos; i >= bgn; --i) {
switch (src[i]) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
break;
default:
return i + 1;
}
}
return bgn;
}
public static int Find_bwd__skip(byte[] src, int end, int bgn, byte skip) {
int src_len = src.length; // if (end == src_len) return end;
if (end > src_len || end < 0) return Bry_find_.Not_found;
int pos = end - 1; // start from end - 1; handles situations where len is passed in
for (int i = pos; i >= bgn; --i) {
if (src[i] != skip)
return i + 1;
}
return bgn;
}
public static int Find_bwd__skip(byte[] src, int end, int bgn, byte[] skip) {
int src_len = src.length;
if (end > src_len || end < 0) return Bry_find_.Not_found;
int skip_len = skip.length;
int pos = end - skip_len; // start from end - 1; handles situations where len is passed in
for (int i = pos; i >= bgn; --i) {
if (!Bry_.Eq(src, i, i + skip_len, skip))
return i + skip_len;
}
return bgn;
}
public static int Find_bwd_while(byte[] src, int cur, int end, byte while_byte) {
--cur;
while (true) {
if ( cur < end
|| src[cur] != while_byte) return cur;
--cur;
}
}
public static int Find_bwd_while_v2(byte[] src, int cur, int end, byte while_byte) {
--cur;
while (true) {
if ( cur < end
|| src[cur] != while_byte) return cur + 1;
--cur;
}
}
public static int Find_fwd_while(byte[] src, int cur, int end, byte while_byte) {
while (true) {
if ( cur == end
|| src[cur] != while_byte) return cur;
cur++;
}
}
public static int Find_fwd_while(byte[] src, int cur, int end, byte[] while_bry) {
int while_len = while_bry.length;
while (true) {
if (cur == end) return cur;
for (int i = 0; i < while_len; i++) {
if (while_bry[i] != src[i + cur]) return cur;
}
cur += while_len;
}
}
public static int Find_fwd_while_in(byte[] src, int cur, int end, boolean[] while_ary) {
while (cur < end) {
if (cur == end || !while_ary[src[cur]]) return cur;
cur++;
}
return end;
}
public static int Find_fwd_until(byte[] src, int cur, int end, byte until_byte) {
while (true) {
if ( cur == end
|| src[cur] == until_byte) return cur;
cur++;
}
}
public static int Find_fwd_until_space_or_tab(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return Bry_find_.Not_found;
switch (src[cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab:
return cur;
default:
++cur;
break;
}
}
}
public static int Find_fwd_until_ws(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return Bry_find_.Not_found;
switch (src[cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
return cur;
default:
++cur;
break;
}
}
}
public static int Find_fwd_while_space_or_tab(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab: ++cur; break;
default: return cur;
}
}
}
public static int Trim_fwd_space_tab(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab: ++cur; break;
default: return cur;
}
}
}
public static int Trim_bwd_space_tab(byte[] src, int cur, int bgn) {
while (true) {
int prv_cur = cur - 1; // check byte before cur; EX: "a b " will have len of 4, and pass cur=4;
if (prv_cur < bgn) return cur; // checking byte before prv; exit;
switch (src[prv_cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab: --cur; break;
default: return cur;
}
}
}
public static int Find_fwd_while_ws(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
try {
switch (src[cur]) {
case Byte_ascii.Nl: case Byte_ascii.Cr:
case Byte_ascii.Space: case Byte_ascii.Tab: ++cur; break;
default: return cur;
}
} catch (Exception e) {throw Err_.new_exc(e, "core", "idx is invalid", "cur", cur, "src", src);}
}
}
public static int Find_fwd_while_letter(byte[] src, int cur, int end) {
while (cur < end) {
switch (src[cur]) {
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e:
case Byte_ascii.Ltr_f: case Byte_ascii.Ltr_g: case Byte_ascii.Ltr_h: case Byte_ascii.Ltr_i: case Byte_ascii.Ltr_j:
case Byte_ascii.Ltr_k: case Byte_ascii.Ltr_l: case Byte_ascii.Ltr_m: case Byte_ascii.Ltr_n: case Byte_ascii.Ltr_o:
case Byte_ascii.Ltr_p: case Byte_ascii.Ltr_q: case Byte_ascii.Ltr_r: case Byte_ascii.Ltr_s: case Byte_ascii.Ltr_t:
case Byte_ascii.Ltr_u: case Byte_ascii.Ltr_v: case Byte_ascii.Ltr_w: case Byte_ascii.Ltr_x: case Byte_ascii.Ltr_y: case Byte_ascii.Ltr_z:
break;
default:
return cur;
}
++cur;
}
return cur;
}
public static int Find_fwd_while_num(byte[] src) {return Find_fwd_while_num(src, 0, src.length);}
public static int Find_fwd_while_num(byte[] src, int cur, int end) {
while (cur < end) {
if (!Byte_ascii.Is_num(src[cur]))
return cur;
++cur;
}
return cur;
}
public static int Find_fwd_while_not_ws(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.Space:
case Byte_ascii.Nl:
case Byte_ascii.Tab:
case Byte_ascii.Cr:
++cur;
break;
default:
return cur;
}
}
}
public static int Find_bwd_while_alphanum(byte[] src, int cur) {return Find_bwd_while_alphanum(src, cur, -1);}
public static int Find_bwd_while_alphanum(byte[] src, int cur, int end) {
--cur;
while (cur > end) {
switch (src[cur]) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e:
case Byte_ascii.Ltr_f: case Byte_ascii.Ltr_g: case Byte_ascii.Ltr_h: case Byte_ascii.Ltr_i: case Byte_ascii.Ltr_j:
case Byte_ascii.Ltr_k: case Byte_ascii.Ltr_l: case Byte_ascii.Ltr_m: case Byte_ascii.Ltr_n: case Byte_ascii.Ltr_o:
case Byte_ascii.Ltr_p: case Byte_ascii.Ltr_q: case Byte_ascii.Ltr_r: case Byte_ascii.Ltr_s: case Byte_ascii.Ltr_t:
case Byte_ascii.Ltr_u: case Byte_ascii.Ltr_v: case Byte_ascii.Ltr_w: case Byte_ascii.Ltr_x: case Byte_ascii.Ltr_y: case Byte_ascii.Ltr_z:
--cur;
break;
default:
return cur;
}
}
return 0; // always return a valid index
}
}

@ -0,0 +1,90 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*;
public class Bry_find__tst {
private Bry_find__fxt fxt = new Bry_find__fxt();
@Test public void Find_fwd() {
fxt.Test_Find_fwd("abcba", "b", 0, 1);
fxt.Test_Find_fwd("abcba", "z", 0, -1);
fxt.Test_Find_fwd("abcba", "b", 1, 1);
fxt.Test_Find_fwd("abcba", "b", 2, 3);
fxt.Test_Find_fwd("abcba", "b", 4, -1);
fxt.Test_Find_fwd("abcba", "zb", 4, -1);
fxt.Test_Find_fwd("abcba", "a", 6, -1);
}
@Test public void Find_bwd() {
fxt.Test_Find_bwd("abcba", "b", 4, 3);
fxt.Test_Find_bwd("abcba", "z", 4, -1);
fxt.Test_Find_bwd("abcba", "b", 3, 1);
fxt.Test_Find_bwd("abcba", "b", 2, 1);
fxt.Test_Find_bwd("abcba", "b", 0, -1);
fxt.Test_Find_bwd("abcba", "zb", 4, -1);
fxt.Test_Find_fwd("abcba", "a", -1, -1);
fxt.Test_Find_bwd("abcba", "ab", 4, 0);
}
@Test public void Find_bwd_last_ws() {
fxt.Test_Find_bwd_1st_ws_tst("a b" , 2, 1); // basic
fxt.Test_Find_bwd_1st_ws_tst("a b" , 3, 1); // multiple
fxt.Test_Find_bwd_1st_ws_tst("ab" , 1, Bry_find_.Not_found); // none
}
@Test public void Trim_fwd_space_tab() {
fxt.Test_Trim_fwd_space_tab(" a b" , 1);
fxt.Test_Trim_fwd_space_tab("\ta b" , 1);
fxt.Test_Trim_fwd_space_tab(" \ta b" , 2);
fxt.Test_Trim_fwd_space_tab("a bc" , 0);
fxt.Test_Trim_fwd_space_tab("" , 0);
fxt.Test_Trim_fwd_space_tab(" \t" , 2);
}
@Test public void Trim_bwd_space_tab() {
fxt.Test_Trim_bwd_space_tab("a b " , 3);
fxt.Test_Trim_bwd_space_tab("a b\t" , 3);
fxt.Test_Trim_bwd_space_tab("a b\t " , 3);
fxt.Test_Trim_bwd_space_tab("a bc" , 4);
fxt.Test_Trim_bwd_space_tab("" , 0);
fxt.Test_Trim_bwd_space_tab(" \t" , 0);
}
@Test public void Find_fwd_while_in() {
boolean[] while_ary = fxt.Init__find_fwd_while_in(Byte_ascii.Space, Byte_ascii.Tab, Byte_ascii.Nl);
fxt.Test__find_fwd_while_in(" \t\na", while_ary, 3);
}
}
class Bry_find__fxt {
public void Test_Find_fwd(String src, String lkp, int bgn, int expd) {Tfds.Eq(expd, Bry_find_.Find_fwd(Bry_.new_u8(src), Bry_.new_u8(lkp), bgn));}
public void Test_Find_bwd(String src, String lkp, int bgn, int expd) {Tfds.Eq(expd, Bry_find_.Find_bwd(Bry_.new_u8(src), Bry_.new_u8(lkp), bgn));}
public void Test_Find_bwd_1st_ws_tst(String src, int pos, int expd) {Tfds.Eq(expd, Bry_find_.Find_bwd_last_ws(Bry_.new_a7(src), pos));}
public void Test_Trim_bwd_space_tab(String raw_str, int expd) {
byte[] raw_bry = Bry_.new_u8(raw_str);
int actl = Bry_find_.Trim_bwd_space_tab(raw_bry, raw_bry.length, 0);
Tfds.Eq(expd, actl, raw_str);
}
public void Test_Trim_fwd_space_tab(String raw_str, int expd) {
byte[] raw_bry = Bry_.new_u8(raw_str);
int actl = Bry_find_.Trim_fwd_space_tab(raw_bry, 0, raw_bry.length);
Tfds.Eq(expd, actl, raw_str);
}
public boolean[] Init__find_fwd_while_in(byte... ary) {
boolean[] rv = new boolean[256];
int len = ary.length;
for (int i = 0; i < len; i++)
rv[ary[i]] = true;
return rv;
}
public void Test__find_fwd_while_in(String src, boolean[] ary, int expd) {
byte[] src_bry = Bry_.new_u8(src);
Gftest.Eq__int(expd, Bry_find_.Find_fwd_while_in(src_bry, 0, src_bry.length, ary));
}
}

@ -0,0 +1,87 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.brys.*; import gplx.core.brys.fmts.*;
public class Bry_fmt {
private final Object thread_lock = new Object();
private byte[] src;
private Bry_fmt_itm[] itms; private int itms_len;
private Bfr_fmt_arg[] args = Bfr_fmt_arg.Ary_empty;
private byte[][] keys = Bry_.Ary_empty;
private Object[] vals = null;
private boolean dirty;
public Bry_fmt(byte[] src, byte[][] keys, Bfr_fmt_arg[] args) {
dirty = true;
this.src = src; this.keys = keys; this.args = args;
}
public byte[] Fmt() {return src;}
public Bry_fmt Fmt_(String v) {return Fmt_(Bry_.new_u8(v));}
public Bry_fmt Fmt_(byte[] v) {dirty = true; src = v; return this;}
public Bry_fmt Args_(Bfr_fmt_arg... v) {dirty = true; args = v; return this;}
public Bry_fmt Keys_(String... v) {return Keys_(Bry_.Ary(v));}
public Bry_fmt Keys_(byte[]... v) {dirty = true; keys = v; return this;}
public Bry_fmt Vals_(Object... v) {vals = v; return this;}
public String Bld_many_to_str_auto_bfr(Object... vals_ary) {
Bry_bfr bfr = Bry_bfr_.Get();
try {return Bld_many_to_str(bfr, vals_ary);}
finally {bfr.Mkr_rls();}
}
public String Bld_many_to_str(Bry_bfr bfr, Object... vals_ary) {
Bld_many(bfr, vals_ary);
return bfr.To_str_and_clear();
}
public byte[] Bld_many_to_bry(Bry_bfr bfr, Object... vals_ary) {
Bld_many(bfr, vals_ary);
return bfr.To_bry_and_clear();
}
public void Bld_many(Bry_bfr bfr, Object... vals_ary) {
if (dirty) Compile();
int vals_len = vals_ary.length;
for (int i = 0; i < itms_len; ++i) {
Bry_fmt_itm itm = itms[i];
switch (itm.Tid) {
case Bry_fmt_itm.Tid__txt: bfr.Add_mid(src, itm.Src_bgn, itm.Src_end); break;
case Bry_fmt_itm.Tid__arg: itm.Arg.Bfr_arg__add(bfr);break;
case Bry_fmt_itm.Tid__key:
int idx = itm.Key_idx;
if (idx > -1 && idx < vals_len)
bfr.Add_obj(vals_ary[idx]);
else
bfr.Add_mid(src, itm.Src_bgn, itm.Src_end);
break;
default: throw Err_.new_unhandled(itm.Tid);
}
}
}
public String To_str() {return Bld_many_to_str_auto_bfr(vals);}
private void Compile() {
synchronized (thread_lock) {
dirty = false;
this.itms = Bry_fmt_parser_.Parse(Byte_ascii.Tilde, Byte_ascii.Curly_bgn, Byte_ascii.Curly_end, args, keys, src);
this.itms_len = itms.length;
}
}
public static Bry_fmt New(String fmt, String... keys) {return new Bry_fmt(Bry_.new_u8(fmt), Bry_.Ary(keys), Bfr_fmt_arg.Ary_empty);}
public static Bry_fmt New(byte[] fmt, String... keys) {return new Bry_fmt(fmt , Bry_.Ary(keys), Bfr_fmt_arg.Ary_empty);}
public static String Make_str(String fmt_str, Object... vals) {return Auto(fmt_str).Vals_(vals).To_str();}
public static Bry_fmt Auto_nl_apos(String... lines) {return Auto(Bry_.New_u8_nl_apos(lines));}
public static Bry_fmt Auto_nl_skip_last(String... lines) {return Auto(Bry_.new_u8(String_.Concat_lines_nl_skip_last(lines)));}
public static Bry_fmt Auto(String fmt_str) {return Auto(Bry_.new_u8(fmt_str));}
public static Bry_fmt Auto(byte[] fmt_bry) {
byte[][] keys_bry = Bry_fmt_parser_.Parse_keys(fmt_bry);
return new Bry_fmt(fmt_bry, keys_bry, Bfr_fmt_arg.Ary_empty);
}
}

@ -0,0 +1,155 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.brys.*;
public class Bry_split_ {
private static final Object thread_lock = new Object();
public static byte[][] Split(byte[] src, byte dlm) {return Split(src, dlm, false);}
public static byte[][] Split(byte[] src, byte dlm, boolean trim) {return src == null ? Bry_.Ary_empty : Split(src, 0, src.length, dlm, trim);}
public static byte[][] Split(byte[] src, int bgn, int end, byte dlm, boolean trim) {
synchronized (thread_lock) {
Bry_split_wkr__to_ary wkr = Bry_split_wkr__to_ary.Instance;
Split(src, bgn, end, dlm, trim, wkr);
return wkr.To_ary();
}
}
public static int Split(byte[] src, int src_bgn, int src_end, byte dlm, boolean trim, Bry_split_wkr wkr) {
if (src == null || src_end - src_bgn < 1) return 0;
int pos = src_bgn;
int itm_bgn = -1, itm_end = -1;
int count = 0;
while (true) {
boolean pos_is_last = pos == src_end;
byte b = pos_is_last ? dlm : src[pos];
int nxt_pos = pos + 1;
boolean process = true;
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: // ignore ws; assumes that flags have no ws (they are single char) and vnts have no ws (EX: zh-hans)
if (trim && b != dlm) process = false; // b != dlm handles cases where ws is dlm, but trim is enabled; EX: " a \n b" -> "a", "b"
break;
}
if (process) {
if (b == dlm) {
boolean reset = true;
if (itm_bgn == -1) {
if (pos_is_last) {} // skip dlm at bgn / end; EX: "a,"
else {wkr.Split(src, pos, pos );} // else, process "empty" dlm; EX: ",a"
}
else {
int rv = wkr.Split(src, itm_bgn, itm_end);
switch (rv) {
case Rv__ok: ++count; break;
case Rv__extend: reset = false; break;
case Rv__cancel: return count;
default: throw Err_.new_unhandled(rv);
}
}
if (reset) itm_bgn = itm_end = -1;
}
else {
if (itm_bgn == -1) itm_bgn = pos;
itm_end = nxt_pos;
}
}
if (pos_is_last) break;
pos = nxt_pos;
}
return count;
}
public static byte[][] Split(byte[] src, byte[] dlm) {return Split(src, 0, src.length, dlm);}
public static byte[][] Split(byte[] src, int src_bgn, int src_end, byte[] dlm) {
if (src == null) return Bry_.Ary_empty;
int src_len = src.length;
if (src_len == 0) return Bry_.Ary_empty;
int cur_pos = src_bgn, dlm_len = dlm.length;
List_adp rv = List_adp_.New();
while (true) {
int find_pos = Bry_find_.Find_fwd(src, dlm, cur_pos);
if (find_pos == Bry_find_.Not_found) {
if (cur_pos >= src_end) break; // dlm is last sequence in src; do not create empty itm
find_pos = src_end;
}
rv.Add(Bry_.Mid(src, cur_pos, find_pos));
cur_pos = find_pos + dlm_len;
if (cur_pos >= src_end) break;
}
return (byte[][])rv.To_ary(byte[].class);
}
public static byte[][] Split_lines(byte[] src) {
if (Bry_.Len_eq_0(src)) return Bry_.Ary_empty;
int src_len = src.length, src_pos = 0, fld_bgn = 0;
List_adp rv = List_adp_.New();
while (true) {
boolean last = src_pos == src_len;
byte b = last ? Byte_ascii.Nl : src[src_pos];
int nxt_bgn = src_pos + 1;
switch (b) {
case Byte_ascii.Cr:
case Byte_ascii.Nl:
if ( b == Byte_ascii.Cr // check for crlf
&& nxt_bgn < src_len && src[nxt_bgn] == Byte_ascii.Nl) {
++nxt_bgn;
}
if (last && (src_pos - fld_bgn == 0)) {} // ignore trailing itms
else
rv.Add(Bry_.Mid(src, fld_bgn, src_pos));
fld_bgn = nxt_bgn;
break;
}
if (last) break;
src_pos = nxt_bgn;
}
return (byte[][])rv.To_ary(byte[].class);
}
public static byte[][] Split_w_max(byte[] src, byte dlm, int max) {
byte[][] rv = new byte[max][];
int src_len = src.length;
int rv_idx = 0;
int itm_bgn = 0;
int src_pos = 0;
while (true) {
boolean is_last = src_pos == src_len;
byte b = is_last ? dlm : src[src_pos];
if (b == dlm) {
rv[rv_idx++] = Bry_.Mid(src, itm_bgn, src_pos);
itm_bgn = src_pos + 1;
}
if (is_last || rv_idx == max)
break;
else
src_pos++;
}
return rv;
}
public static final int Rv__ok = 0, Rv__extend = 1, Rv__cancel = 2;
}
class Bry_split_wkr__to_ary implements gplx.core.brys.Bry_split_wkr {
private final List_adp list = List_adp_.New();
public int Split(byte[] src, int itm_bgn, int itm_end) {
synchronized (list) {
byte[] bry = itm_end == itm_bgn ? Bry_.Empty : Bry_.Mid(src, itm_bgn, itm_end);
list.Add(bry);
return Bry_split_.Rv__ok;
}
}
public byte[][] To_ary() {
synchronized (list) {
return (byte[][])list.To_ary_and_clear(byte[].class);
}
}
public static final Bry_split_wkr__to_ary Instance = new Bry_split_wkr__to_ary(); Bry_split_wkr__to_ary() {}
}

@ -0,0 +1,80 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*;
public class Bry_split__tst {
private final Bry_split__fxt fxt = new Bry_split__fxt();
@Test public void Split() {
fxt.Test_split("a" , Byte_ascii.Pipe, Bool_.N, "a"); // no trim
fxt.Test_split("a|" , Byte_ascii.Pipe, Bool_.N, "a");
fxt.Test_split("|a" , Byte_ascii.Pipe, Bool_.N, "", "a");
fxt.Test_split("|" , Byte_ascii.Pipe, Bool_.N, "");
fxt.Test_split("" , Byte_ascii.Pipe, Bool_.N);
fxt.Test_split("a|b|c" , Byte_ascii.Pipe, Bool_.N, "a", "b", "c");
fxt.Test_split(" a " , Byte_ascii.Pipe, Bool_.Y, "a"); // trim
fxt.Test_split(" a |" , Byte_ascii.Pipe, Bool_.Y, "a");
fxt.Test_split("| a " , Byte_ascii.Pipe, Bool_.Y, "", "a");
fxt.Test_split(" | " , Byte_ascii.Pipe, Bool_.Y, "");
fxt.Test_split(" " , Byte_ascii.Pipe, Bool_.Y);
fxt.Test_split(" a | b | c " , Byte_ascii.Pipe, Bool_.Y, "a", "b", "c");
fxt.Test_split(" a b | c d " , Byte_ascii.Pipe, Bool_.Y, "a b", "c d");
fxt.Test_split(" a \n b " , Byte_ascii.Nl , Bool_.N, " a ", " b "); // ws as dlm
fxt.Test_split(" a \n b " , Byte_ascii.Nl , Bool_.Y, "a", "b"); // ws as dlm; trim
fxt.Test_split("a|extend|b" , Byte_ascii.Pipe, Bool_.Y, "a", "extend|b"); // extend
fxt.Test_split("extend|a" , Byte_ascii.Pipe, Bool_.Y, "extend|a"); // extend
fxt.Test_split("a|cancel|b" , Byte_ascii.Pipe, Bool_.Y, "a"); // cancel
}
@Test public void Split__bry() {
fxt.Test_split("a|b|c|d" , 2, 6, "|", "b", "c");
fxt.Test_split("a|b|c|d" , 2, 4, "|", "b");
}
@Test public void Empty() {
fxt.Test_split("a\n\nb" , Byte_ascii.Nl, Bool_.N, "a", "", "b");
}
@Test public void Split_w_max() {
fxt.Test__split_w_max("a|b|c|d" , Byte_ascii.Pipe, 2, "a", "b"); // max is less
fxt.Test__split_w_max("a" , Byte_ascii.Pipe, 2, "a", null); // max is more
fxt.Test__split_w_max("|" , Byte_ascii.Pipe, 2, "", ""); // empty itms
}
}
class Bry_split__fxt {
private final Bry_split_wkr__example wkr = new Bry_split_wkr__example();
public void Test_split(String raw_str, byte dlm, boolean trim, String... expd) {
byte[] src = Bry_.new_a7(raw_str);
Bry_split_.Split(src, 0, src.length, dlm, trim, wkr);
byte[][] actl_ary = wkr.To_ary();
Tfds.Eq_ary_str(expd, String_.Ary(actl_ary));
}
public void Test_split(String src, int src_bgn, int src_end, String dlm, String... expd) {
Tfds.Eq_ary_str(Bry_.Ary(expd), Bry_split_.Split(Bry_.new_u8(src), src_bgn, src_end, Bry_.new_u8(dlm)));
}
public void Test__split_w_max(String src, byte dlm, int max, String... expd) {
Gftest.Eq__ary(expd, String_.Ary(Bry_split_.Split_w_max(Bry_.new_u8(src), dlm, max)));
}
}
class Bry_split_wkr__example implements gplx.core.brys.Bry_split_wkr {
private final List_adp list = List_adp_.New();
public int Split(byte[] src, int itm_bgn, int itm_end) {
byte[] bry = itm_end == itm_bgn ? Bry_.Empty : Bry_.Mid(src, itm_bgn, itm_end);
if (Bry_.Eq(bry, Bry_.new_a7("extend"))) return Bry_split_.Rv__extend;
else if (Bry_.Eq(bry, Bry_.new_a7("cancel"))) return Bry_split_.Rv__cancel;
list.Add(bry);
return Bry_split_.Rv__ok;
}
public byte[][] To_ary() {
return (byte[][])list.To_ary_and_clear(byte[].class);
}
}

@ -0,0 +1,68 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Byte_ {//RF:2017-10-08
public static final String Cls_val_name = "byte";
public static final Class<?> Cls_ref_type = Byte.class;
public static final byte
Zero = 0
, Min_value = Byte.MIN_VALUE
, Max_value_127 = 127
, Val_128 = -128
, Val_255 = -1
;
public static byte By_int(int v) {return v > 127 ? (byte)(v - 256) : (byte)v;} // PERF?: (byte)(v & 0xff)
public static int To_int(byte v) {return v < 0 ? (int)v + 256 : v;}
public static String To_str(byte v) {return new Byte(v).toString();}
public static byte[] To_bry(byte v) {return new byte[] {v};}
public static byte Cast(Object o) {try {return (Byte)o;} catch (Exception e) {throw Err_.new_type_mismatch_w_exc(e, byte.class, o);}}
public static byte Parse(String raw) {return Byte.parseByte(raw);}
public static byte Parse_or(String raw, byte or) {
if (raw == null) return or;
try {return Parse(raw);}
catch (Exception e) {Err_.Noop(e); return or;}
}
public static boolean Match_any(byte v, byte... ary) {
for (byte itm : ary)
if (v == itm) return true;
return false;
}
public static boolean Match_all(byte v, byte... ary) {
for (byte itm : ary)
if (v != itm) return false;
return true;
}
public static int Compare(byte lhs, byte rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
public static byte[] Ary(byte... ary) {return ary;}
public static byte[] Ary_by_ints(int... ary) {
int ary_len = ary.length;
byte[] rv = new byte[ary_len];
for (int i = 0; i < ary_len; i++) {
rv[i] = By_int(ary[i]);
}
return rv;
}
}

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Byte__tst {
@Test public void int_() {
tst_int_( 0, 0);
tst_int_( 127, 127);
tst_int_( 128, 128); // NOTE: JAVA defines byte as -128 -> 127
tst_int_( 255, 255);
tst_int_( 256, 0); // NOTE: 256 will cast to 1; (byte)256 works same in both JAVA/.NET
} void tst_int_(int v, int expd) {Tfds.Eq((byte)expd, Byte_.By_int(v));} // WORKAROUND/JAVA: expd is of type int b/c java promotes numbers to ints
@Test public void To_int() {
tst_XtoInt( 0, 0);
tst_XtoInt( 127, 127);
tst_XtoInt( 128, 128);
tst_XtoInt( 255, 255);
tst_XtoInt( 256, 0);
} void tst_XtoInt(int v, int expd) {Tfds.Eq(expd, Byte_.To_int((byte)v));} // WORKAROUND/JAVA: v is of type int b/c java promotes numbers to ints
}

@ -0,0 +1,129 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Byte_ascii {
public static final byte
Null = 0 , Backfeed = 8, Tab = 9
, Nl = 10, Formfeed = 12, Cr = 13
, Escape = 27
, Space = 32, Bang = 33, Quote = 34
, Hash = 35, Dollar = 36, Percent = 37, Amp = 38, Apos = 39
, Paren_bgn = 40, Paren_end = 41, Star = 42, Plus = 43, Comma = 44
, Dash = 45, Dot = 46, Slash = 47, Num_0 = 48, Num_1 = 49
, Num_2 = 50, Num_3 = 51, Num_4 = 52, Num_5 = 53, Num_6 = 54
, Num_7 = 55, Num_8 = 56, Num_9 = 57, Colon = 58, Semic = 59
, Lt = 60, Eq = 61, Gt = 62, Question = 63, At = 64
, Ltr_A = 65, Ltr_B = 66, Ltr_C = 67, Ltr_D = 68, Ltr_E = 69
, Ltr_F = 70, Ltr_G = 71, Ltr_H = 72, Ltr_I = 73, Ltr_J = 74
, Ltr_K = 75, Ltr_L = 76, Ltr_M = 77, Ltr_N = 78, Ltr_O = 79
, Ltr_P = 80, Ltr_Q = 81, Ltr_R = 82, Ltr_S = 83, Ltr_T = 84
, Ltr_U = 85, Ltr_V = 86, Ltr_W = 87, Ltr_X = 88, Ltr_Y = 89
, Ltr_Z = 90, Brack_bgn = 91, Backslash = 92, Brack_end = 93, Pow = 94 // Circumflex
, Underline = 95, Tick = 96, Ltr_a = 97, Ltr_b = 98, Ltr_c = 99
, Ltr_d = 100, Ltr_e = 101, Ltr_f = 102, Ltr_g = 103, Ltr_h = 104
, Ltr_i = 105, Ltr_j = 106, Ltr_k = 107, Ltr_l = 108, Ltr_m = 109
, Ltr_n = 110, Ltr_o = 111, Ltr_p = 112, Ltr_q = 113, Ltr_r = 114
, Ltr_s = 115, Ltr_t = 116, Ltr_u = 117, Ltr_v = 118, Ltr_w = 119
, Ltr_x = 120, Ltr_y = 121, Ltr_z = 122, Curly_bgn = 123, Pipe = 124
, Curly_end = 125, Tilde = 126, Delete = 127
;
public static final byte
Angle_bgn = Lt, Angle_end = Gt
;
public static final int Len_1 = 1;
public static final byte Max_7_bit = (byte)127, Ascii_min = 0, Ascii_max = 127;
public static boolean Is_sym(byte b) {
switch (b) {
case Byte_ascii.Bang: case Byte_ascii.Quote:
case Byte_ascii.Hash: case Byte_ascii.Dollar: case Byte_ascii.Percent: case Byte_ascii.Amp: case Byte_ascii.Apos:
case Byte_ascii.Paren_bgn: case Byte_ascii.Paren_end: case Byte_ascii.Star: case Byte_ascii.Plus: case Byte_ascii.Comma:
case Byte_ascii.Dash: case Byte_ascii.Dot: case Byte_ascii.Slash:
case Byte_ascii.Colon: case Byte_ascii.Semic:
case Byte_ascii.Lt: case Byte_ascii.Eq: case Byte_ascii.Gt: case Byte_ascii.Question: case Byte_ascii.At:
case Byte_ascii.Brack_bgn: case Byte_ascii.Backslash: case Byte_ascii.Brack_end: case Byte_ascii.Pow:
case Byte_ascii.Underline: case Byte_ascii.Tick:
case Byte_ascii.Curly_bgn: case Byte_ascii.Pipe:
case Byte_ascii.Curly_end: case Byte_ascii.Tilde:
return true;
default:
return false;
}
}
public static boolean Is_ltr(byte b) {
return ( b >= Byte_ascii.Ltr_a && b <= Byte_ascii.Ltr_z
|| b >= Byte_ascii.Ltr_A && b <= Byte_ascii.Ltr_Z);
}
public static boolean Is_ws(byte b) {
switch (b) {
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: case Byte_ascii.Space: return true;
default: return false;
}
}
public static boolean Is_num(byte b) {
return b > Byte_ascii.Slash && b < Byte_ascii.Colon;
}
public static byte To_a7_int(byte b) {return (byte)(b - Byte_ascii.Num_0);}
public static byte To_a7_str(int digit) {
switch (digit) {
case 0: return Byte_ascii.Num_0; case 1: return Byte_ascii.Num_1; case 2: return Byte_ascii.Num_2; case 3: return Byte_ascii.Num_3; case 4: return Byte_ascii.Num_4;
case 5: return Byte_ascii.Num_5; case 6: return Byte_ascii.Num_6; case 7: return Byte_ascii.Num_7; case 8: return Byte_ascii.Num_8; case 9: return Byte_ascii.Num_9;
default: throw Err_.new_("Byte_ascii", "unknown digit", "digit", digit);
}
}
public static String To_str(byte b) {return Char_.To_str((char)b);}
public static byte Case_upper(byte b) {
return b > 96 && b < 123
? (byte)(b - 32)
: b;
}
public static byte Case_lower(byte b) {
return b > 64 && b < 91
? (byte)(b + 32)
: b;
}
public static final byte[] Space_len2 = new byte[] {Space, Space}, Space_len4 = new byte[] {Space, Space, Space, Space};
public static final byte[]
Tab_bry = new byte[] {Byte_ascii.Tab}
, Nl_bry = new byte[] {Byte_ascii.Nl}
, Space_bry = new byte[] {Byte_ascii.Space}
, Bang_bry = new byte[] {Byte_ascii.Bang}
, Quote_bry = new byte[] {Byte_ascii.Quote}
, Hash_bry = new byte[] {Byte_ascii.Hash}
, Dot_bry = new byte[] {Byte_ascii.Dot}
, Angle_bgn_bry = new byte[] {Byte_ascii.Angle_bgn}
, Angle_end_bry = new byte[] {Byte_ascii.Angle_end}
, Comma_bry = new byte[] {Byte_ascii.Comma}
, Colon_bry = new byte[] {Byte_ascii.Colon}
, Semic_bry = new byte[] {Byte_ascii.Semic}
, Eq_bry = new byte[] {Byte_ascii.Eq}
, Amp_bry = new byte[] {Byte_ascii.Amp}
, Lt_bry = new byte[] {Byte_ascii.Lt}
, Gt_bry = new byte[] {Byte_ascii.Gt}
, Question_bry = new byte[] {Byte_ascii.Question}
, Brack_bgn_bry = new byte[] {Byte_ascii.Brack_bgn}
, Brack_end_bry = new byte[] {Byte_ascii.Brack_end}
, Apos_bry = new byte[] {Byte_ascii.Apos}
, Pipe_bry = new byte[] {Byte_ascii.Pipe}
, Underline_bry = new byte[] {Byte_ascii.Underline}
, Slash_bry = new byte[] {Byte_ascii.Slash}
, Star_bry = new byte[] {Byte_ascii.Star}
, Dash_bry = new byte[] {Byte_ascii.Dash}
, Cr_lf_bry = new byte[] {Byte_ascii.Cr, Byte_ascii.Nl}
, Num_0_bry = new byte[] {Byte_ascii.Num_0}
, Num_1_bry = new byte[] {Byte_ascii.Num_1}
;
}

@ -0,0 +1,20 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Cancelable {
boolean Canceled();
void Cancel();
}

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Cancelable_ {
public static final Cancelable Never = new Cancelable_never();
public static Cancelable New_proxy() {return new Cancelable_proxy();}
}
class Cancelable_never implements Cancelable {
public boolean Canceled() {return false;}
public void Cancel() {}
}
class Cancelable_proxy implements Cancelable {
private boolean canceled = false;
public boolean Canceled() {return canceled;}
public void Cancel() {canceled = true;}
}

@ -0,0 +1,72 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Char_ {
public static final String Cls_val_name = "char";
public static final Class<?> Cls_ref_type = Character.class;
public static final char Null = '\0', NewLine = '\n';
public static boolean IsCaseLower(char c) {return Character.isLowerCase(c);}
public static boolean IsLetterOrDigit(char c) {return Character.isLetterOrDigit(c);}
public static boolean IsLetterEnglish(char c) {
switch (c) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': return true;
default: return false;
}
}
public static boolean IsLetterLowerEnglish(char c) {
switch (c) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': return true;
default: return false;
}
}
public static boolean IsNumber(char c) {
switch (c) {
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return true;
default: return false;
}
}
public static boolean IsWhitespace(char c) {
switch (c) {
case ' ': case '\t': case '\n': case '\r': return true;
default: return false;
}
}
public static boolean In(char match, char... ary) {
for (char itm : ary)
if (itm == match) return true;
return false;
}
public static int To_int_or(char c, int or) {
switch (c) {
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
default: return or;
}
}
public static String To_str(char[] ary, int pos, int length) {return new String(ary, pos, length);}
public static String To_str(int b) {return To_str((char)b);}
public static String To_str(char c) {return String.valueOf(c);}
public static char By_int(int i) {return (char)i;}
public static char cast(Object o) {try {return (Character)o;} catch(Exception e) {throw Err_.new_type_mismatch_w_exc(e, char.class, o);}}
public static char parse(String raw) {try {return raw.charAt(0);} catch(Exception exc) {throw Err_.new_parse_exc(exc, char.class, raw);}}
}

@ -0,0 +1,18 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface CompareAble extends Comparable {} // URL:/doc/gplx/CompareAble_.txt
// public int compareTo(Object obj) {Type comp = (Type)obj; return prop.compareTo(comp.prop);}

@ -0,0 +1,43 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class CompareAble_ {
public static Comparable as_(Object obj) {return obj instanceof Comparable ? (Comparable)obj : null;}
public static int Compare_obj(Object lhs, Object rhs) {return Compare_comp(as_(lhs), as_(rhs));}
public static int Compare_comp(Comparable lhs, Comparable rhs) {
if (lhs == null && rhs == null) return CompareAble_.Same;
else if (lhs == null) return CompareAble_.More;
else if (rhs == null) return CompareAble_.Less;
else return Compare(lhs, rhs);
}
public static int Compare(Comparable lhs, Comparable rhs) {return lhs.compareTo(rhs);}
public static boolean Is(int expd, Comparable lhs, Comparable rhs) {
int actl = Compare_comp(lhs, rhs);
if (actl == Same && expd % 2 == Same) // actl=Same and expd=(Same||MoreOrSame||LessOrSame)
return true;
else
return (actl * expd) > 0; // actl=More||Less; expd will match if on same side of 0 (ex: expd=Less; actl=Less; -1 * -1 = 1)
}
public static final int
More = 1
, Less = -1
, Same = 0
, More_or_same = 2
, Less_or_same = -2
;
}

@ -0,0 +1,151 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
public class DateAdp implements CompareAble, Gfo_invk {
public int compareTo(Object obj) {DateAdp comp = (DateAdp)obj; return under.compareTo(comp.under);}
@Override public String toString() {return XtoStr_gplx_long();}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_XtoStr_fmt)) return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");
else if (ctx.Match(k, Invk_AddDays)) {
int days = m.ReadInt("days");
if (ctx.Deny()) return this;
return this.Add_day(days);
}
else return Gfo_invk_.Rv_unhandled;
} public static final String Invk_XtoStr_fmt = "XtoStr_fmt", Invk_AddDays = "Add_day";
public int Segment(int segmentIdx) {
switch (segmentIdx) {
case DateAdp_.SegIdx_year: return this.Year();
case DateAdp_.SegIdx_month: return this.Month();
case DateAdp_.SegIdx_day: return this.Day();
case DateAdp_.SegIdx_hour: return this.Hour();
case DateAdp_.SegIdx_minute: return this.Minute();
case DateAdp_.SegIdx_second: return this.Second();
case DateAdp_.SegIdx_frac: return this.Frac();
case DateAdp_.SegIdx_dayOfWeek: return this.DayOfWeek();
case DateAdp_.SegIdx_weekOfYear: return this.WeekOfYear();
case DateAdp_.SegIdx_dayOfYear: return this.DayOfYear();
default: throw Err_.new_unhandled(segmentIdx);
}
}
public int[] XtoSegAry() {
int[] rv = new int[7];
rv[DateAdp_.SegIdx_year] = this.Year();
rv[DateAdp_.SegIdx_month] = this.Month();
rv[DateAdp_.SegIdx_day] = this.Day();
rv[DateAdp_.SegIdx_hour] = this.Hour();
rv[DateAdp_.SegIdx_minute] = this.Minute();
rv[DateAdp_.SegIdx_second] = this.Second();
rv[DateAdp_.SegIdx_frac] = this.Frac();
return rv;
}
public String XtoStr_gplx() {return XtoStr_fmt("yyyyMMdd_HHmmss.fff");}
public String XtoStr_gplx_long() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss.fff");}
public String XtoStr_fmt_HHmmss() {return XtoStr_fmt("HH:mm:ss");}
public String XtoStr_fmt_HHmm() {return XtoStr_fmt("HH:mm");}
public String XtoStr_fmt_yyyy_MM_dd() {return XtoStr_fmt("yyyy-MM-dd");}
public String XtoStr_fmt_yyyyMMdd_HHmmss() {return XtoStr_fmt("yyyyMMdd_HHmmss");}
public String XtoStr_fmt_yyyyMMdd_HHmmss_fff() {return XtoStr_fmt("yyyyMMdd_HHmmss.fff");}
public String XtoStr_fmt_yyyyMMdd_HHmm() {return XtoStr_fmt("yyyyMMdd_HHmm");}
public String XtoStr_fmt_yyyy_MM_dd_HH_mm() {return XtoStr_fmt("yyyy-MM-dd HH:mm");}
public String XtoStr_fmt_yyyy_MM_dd_HH_mm_ss() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");}
public String XtoStr_fmt_iso_8561() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");}
public String XtoStr_fmt_iso_8561_w_tz() {return XtoStr_fmt("yyyy-MM-dd'T'HH:mm:ss'Z'");}
public static int Timezone_offset_test = Int_.Min_value;
public Calendar UnderDateTime() {return under;} Calendar under;
public int Year() {return under.get(Calendar.YEAR);}
public int Month() {return under.get(Calendar.MONTH) + Month_base0adj;}
public int Day() {return under.get(Calendar.DAY_OF_MONTH);}
public int Hour() {return under.get(Calendar.HOUR_OF_DAY);}
public int Minute() {return under.get(Calendar.MINUTE);}
public int Second() {return under.get(Calendar.SECOND);}
public int DayOfWeek() {return under.get(Calendar.DAY_OF_WEEK) - 1;} // -1 : Base0; NOTE: dotnet/php is also Sunday=0
public int DayOfYear() {return under.get(Calendar.DAY_OF_YEAR);}
public int Timezone_offset() {
return Timezone_offset_test == Int_.Min_value // Timezone_offset_test not over-ridden
? 0
// ? under.getTimeZone().getOffset(this.Timestamp_unix()) / 1000 // divide by 1000 to convert from ms to seconds
: Timezone_offset_test
;
}
public DateAdp XtoUtc() {
java.util.Date date = under.getTime();
java.util.TimeZone tz = under.getTimeZone();
long msFromEpochGmt = date.getTime();
int offsetFromUTC = tz.getOffset(msFromEpochGmt);
Calendar gmtCal = Calendar.getInstance();
gmtCal.setTimeInMillis(msFromEpochGmt + -offsetFromUTC);
return new DateAdp(gmtCal);
}
public DateAdp XtoLocal() {
java.util.Date date = under.getTime();
java.util.TimeZone tz = under.getTimeZone();
long msFromEpochGmt = date.getTime();
int offsetFromUTC = tz.getOffset(msFromEpochGmt);
Calendar gmtCal = Calendar.getInstance();
gmtCal.setTimeInMillis(msFromEpochGmt + offsetFromUTC);
return new DateAdp(gmtCal);
}
public long Timestamp_unix() {
long offsetFromUTC = (under.getTimeZone().getOffset(0));
boolean dst = TimeZone.getDefault().inDaylightTime(under.getTime());
long dst_adj = dst ? 3600000 : 0;
return (under.getTimeInMillis() + offsetFromUTC + dst_adj) / 1000;
}
public int WeekOfYear() {return under.get(Calendar.WEEK_OF_YEAR);}
public int Frac() {return under.get(Calendar.MILLISECOND);}
public DateAdp Add_frac(int val) {return CloneAndAdd(Calendar.MILLISECOND, val);}
public DateAdp Add_second(int val) {return CloneAndAdd(Calendar.SECOND, val);}
public DateAdp Add_minute(int val) {return CloneAndAdd(Calendar.MINUTE, val);}
public DateAdp Add_hour(int val) {return CloneAndAdd(Calendar.HOUR, val);}
public DateAdp Add_day(int val) {return CloneAndAdd(Calendar.DAY_OF_MONTH, val);}
public DateAdp Add_month(int val) {return CloneAndAdd(Calendar.MONTH, val);}
public DateAdp Add_year(int val) {return CloneAndAdd(Calendar.YEAR, val);}
DateAdp CloneAndAdd(int field, int val) {
Calendar clone = (Calendar)under.clone();
clone.add(field, val);
return new DateAdp(clone);
}
public String XtoStr_fmt(String fmt) {
fmt = fmt.replace("f", "S");
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
return sdf.format(under.getTime());
}
public String XtoStr_tz() {
SimpleDateFormat sdf = new SimpleDateFormat("Z");
String time_zone = sdf.format(under.getTime());
return String_.Mid(time_zone, 0, 3) + ":" + String_.Mid(time_zone, 3, String_.Len(time_zone));
}
public boolean Eq(DateAdp v) {DateAdp comp = v; return Object_.Eq(under.getTimeInMillis(), comp.under.getTimeInMillis());}
public int Diff_days(DateAdp prev) {
long diff = this.under.getTimeInMillis() - prev.under.getTimeInMillis();
return (int)(diff / (1000 * 60 * 60 * 24));
}
public Time_span Diff(DateAdp earlier) {
long diff = this.under.getTimeInMillis() - earlier.under.getTimeInMillis();
return Time_span_.fracs_(diff);
}
protected DateAdp(Calendar under) {this.under = under;}
protected DateAdp(int year, int month, int day, int hour, int minute, int second, int frac) {
this.under = new GregorianCalendar(year, month - Month_base0adj, day, hour, minute, second);
under.set(Calendar.MILLISECOND, frac);
}
public static final int Month_base0adj = 1;
}

@ -0,0 +1,124 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import gplx.core.times.*;
public class DateAdp_ implements Gfo_invk {
public static final String Cls_ref_name = "Date";
public static final Class<?> Cls_ref_type = DateAdp.class;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_Now)) return Datetime_now.Get();
else return Gfo_invk_.Rv_unhandled;
} public static final String Invk_Now = "Now";
public static final DateAdp MinValue = new DateAdp( 1, 1, 1, 0, 0, 0, 0);
public static final DateAdp MaxValue = new DateAdp(9999, 12, 31, 23, 59, 59, 999);
// public static DateAdp Now() {return Tfds.Now_enabled() ? Tfds.Now() : new DateAdp(new GregorianCalendar());}
public static DateAdp new_(int year, int month, int day, int hour, int minute, int second, int frac) {return new DateAdp(year, month, day, hour, minute, second, frac);}
public static DateAdp seg_(int[] ary) {
int ary_len = ary.length;
int y = ary_len > 0 ? ary[0] : 1;
int M = ary_len > 1 ? ary[1] : 1;
int d = ary_len > 2 ? ary[2] : 1;
int h = ary_len > 3 ? ary[3] : 0;
int m = ary_len > 4 ? ary[4] : 0;
int s = ary_len > 5 ? ary[5] : 0;
int f = ary_len > 6 ? ary[6] : 0;
return new DateAdp(y, M, d, h, m, s, f);
}
public static DateAdp cast(Object arg) {try {return (DateAdp)arg;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, DateAdp.class, arg);}}
public static DateAdp parse_iso8561_or(String raw, DateAdp or) {
try {return parse_iso8561(raw);}
catch (Exception e) {Err_.Noop(e); return or;}
}
public static DateAdp parse_iso8561(String raw) { // NOTE: for now, same as parse_gplx
int[] ary = date_parser.Parse_iso8651_like(raw);
if (ary[1] < 1 || ary[1] > 12) return DateAdp_.MinValue; // guard against invalid month
if (ary[2] < 1 || ary[2] > 31) return DateAdp_.MinValue;
return new DateAdp(ary[0], ary[1], ary[2], ary[3], ary[4], ary[5], ary[6]);
}
public static DateAdp parse_gplx(String raw) {
int[] ary = date_parser.Parse_iso8651_like(raw);
if (ary[1] < 1 || ary[1] > 12) return DateAdp_.MinValue; // guard against invalid month
if (ary[2] < 1 || ary[2] > 31) return DateAdp_.MinValue;
return new DateAdp(ary[0], ary[1], ary[2], ary[3], ary[4], ary[5], ary[6]);
} static DateAdp_parser date_parser = DateAdp_parser.new_();
public static DateAdp dateTime_(GregorianCalendar v) {return new DateAdp(v);}
public static DateAdp dateTime_obj_(Object v) {return new DateAdp((GregorianCalendar)v);}
public static final DateAdp_ Gfs = new DateAdp_();
public static int DaysInMonth(DateAdp date) {
int rv = DaysInMonth_ary[date.Month() - Int_.Base1];
if (rv == 28 && IsLeapYear(date.Year())) rv = 29;
return rv;
} static int [] DaysInMonth_ary = {31,28,31,30,31,30,31,31,30,31,30,31};
public static boolean IsLeapYear(int year) {
if (year % 4 != 0) return false;
else if (year % 400 == 0) return true;
else if (year % 100 == 0) return false;
else return true;
}
public static DateAdp unixtime_utc_seconds_(long v) {return unixtime_utc_ms_(v * 1000);}
public static DateAdp parse_fmt_or(String raw, String fmt, DateAdp or) {
try {return parse_fmt(raw, fmt);}
catch (Exception e) {Err_.Noop(e); return or;}
}
public static DateAdp db_(Object v) {
Timestamp ts = (Timestamp)v;
Calendar gc = Calendar.getInstance();
gc.setTimeInMillis(ts.getTime());
return new DateAdp(gc);
}
public static DateAdp parse_(String raw) {
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = null;
try {d = sdf.parse(raw);}
catch (ParseException e) {throw Err_.new_("parse", "failed to parse to DateAdp", "raw", raw);}
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
cal.setTime(d);
return dateTime_(cal);
}
public static DateAdp parse_fmt(String raw, String fmt) {
fmt = fmt.replace('t', 'a'); // AM/PM
fmt = fmt.replace('f', 'S'); // milliseconds
SimpleDateFormat sdf = new SimpleDateFormat(fmt, Locale.US);
Date d = null;
try {d = sdf.parse(raw);}
catch (ParseException e) {throw Err_.new_("parse", "failed to parse to DateAdp", "raw", raw, "fmt", fmt);}
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
cal.setTime(d);
return dateTime_(cal);
}
public static DateAdp unixtime_utc_ms_(long v) {return unixtime_lcl_ms_(v).XtoUtc();}
public static DateAdp unixtime_lcl_ms_(long v) {
GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(v);
return new DateAdp(c);
}
public static final int SegIdx_year = 0, SegIdx_month = 1, SegIdx_day = 2, SegIdx_hour = 3, SegIdx_minute = 4, SegIdx_second = 5, SegIdx_frac = 6, SegIdx_dayOfWeek = 7, SegIdx_weekOfYear = 8, SegIdx_dayOfYear = 9, SegIdx__max = 10;
public static String Xto_str_fmt_or(DateAdp v, String fmt, String or) {
return v == null ? or : v.XtoStr_fmt(fmt);
}
public static final String
Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss"
, Fmt__yyyyMMdd = "yyyyMMdd";
}

@ -0,0 +1,86 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*;
public class DateAdp__tst {
private final DateAdp__fxt fxt = new DateAdp__fxt();
@Test public void Parse_gplx() {
fxt.Test__parse_gplx("99991231_235959.999" , "99991231_235959.999");
fxt.Test__parse_gplx("20090430_213200.123" , "20090430_213200.123");
fxt.Test__parse_gplx("20090430_213200" , "20090430_213200.000");
fxt.Test__parse_gplx("20090430" , "20090430_000000.000");
}
@Test public void Parse_separators() {
fxt.Test__parse_gplx("2009-04-30 21:32:00.123" , "20090430_213200.123");
fxt.Test__parse_gplx("2009-04-30 21:32:00" , "20090430_213200.000");
fxt.Test__parse_gplx("2009-04-30" , "20090430_000000.000");
}
@Test public void Parse_utc() {
fxt.Test__parse_gplx("2015-12-26T10:03:53Z" , "20151226_100353.000");
}
@Test public void DayOfWeek() {
fxt.Test__day_of_week("2012-01-18", 3); //3=Wed
}
@Test public void WeekOfYear() {
fxt.Test__week_of_year("2006-02-01", 5); // 1-1:Sun;2-1:Wed
fxt.Test__week_of_year("2007-02-01", 5); // 1-1:Mon;2-1:Thu
fxt.Test__week_of_year("2008-02-01", 5); // 1-1:Tue;2-1:Fri
fxt.Test__week_of_year("2009-02-01", 6); // 1-1:Thu;2-1:Sun
fxt.Test__week_of_year("2010-02-01", 6); // 1-1:Fri;2-1:Mon
fxt.Test__week_of_year("2011-02-01", 6); // 1-1:Sat;2-1:Tue
}
@Test public void DayOfYear() {
fxt.Test__day_of_year("2012-01-01", 1);
fxt.Test__day_of_year("2012-02-29", 60);
fxt.Test__day_of_year("2012-12-31", 366);
}
@Test public void Timestamp_unix() {
fxt.Test__timestamp_unix("1970-01-01 00:00:00", 0);
fxt.Test__timestamp_unix("2012-01-01 00:00:00", 1325376000);
}
@Test public void DaysInMonth() {
fxt.Test__days_in_month("2012-01-01", 31);
fxt.Test__days_in_month("2012-02-01", 29);
fxt.Test__days_in_month("2012-04-01", 30);
fxt.Test__days_in_month("2011-02-01", 28);
}
@Test public void XtoUtc() {
fxt.Test__to_utc("2012-01-01 00:00", "2012-01-01 05:00"); //4=Wed
}
}
class DateAdp__fxt {
public void Test__parse_gplx(String raw, String expd) {
Gftest.Eq__str(expd, DateAdp_.parse_gplx(raw).XtoStr_gplx());
}
public void Test__day_of_week(String raw, int expd) {
Gftest.Eq__int(expd, DateAdp_.parse_gplx(raw).DayOfWeek());
}
public void Test__week_of_year(String raw, int expd) {
Gftest.Eq__int(expd, DateAdp_.parse_gplx(raw).WeekOfYear());
}
public void Test__day_of_year(String raw, int expd) {
Gftest.Eq__int(expd, DateAdp_.parse_gplx(raw).DayOfYear());
}
public void Test__days_in_month(String raw, int expd) {
Gftest.Eq__int(expd, DateAdp_.DaysInMonth(DateAdp_.parse_gplx(raw)));
}
public void Test__timestamp_unix(String raw, long expd) {
Gftest.Eq__long(expd, DateAdp_.parse_gplx(raw).Timestamp_unix());
}
public void Test__to_utc(String raw, String expd) {
Tfds.Eq(expd, DateAdp_.parse_gplx(raw).XtoUtc().XtoStr_fmt_yyyy_MM_dd_HH_mm());
}
}

@ -0,0 +1,67 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.util.GregorianCalendar;
public class Datetime_now {
private static final DateAdp dflt = DateAdp_.parse_gplx("2001-01-01 00:00:00.000");
private static DateAdp manual;
private static boolean autoincrement = true;
public static void Manual_y_() {
manual = dflt;
}
public static void Manual_n_() {
manual = null;
autoincrement = true;
}
public static void Manual_and_freeze_(DateAdp v) {
manual = v;
autoincrement = false;
}
public static void Manual_(DateAdp v) {
manual = v;
}
public static void Autoincrement_n_() {
autoincrement = false;
}
public static DateAdp Dflt_add_min_(int v) {
return dflt.Add_minute(v);
}
public static DateAdp Get() {
if (manual == null) return new DateAdp(new GregorianCalendar());
DateAdp rv = manual;
if (autoincrement) manual = rv.Add_minute(1); // simulate passage of manual by increasing manual by 1 minute with each call
return rv;
}
public static DateAdp Get_force() { // ignore manual and force get of real time
return new DateAdp(new GregorianCalendar());
}
// private static final DateAdp manual_time_dflt = DateAdp_.parse_gplx("2001-01-01 00:00:00.000");
// private static DateAdp manual_time;
// static boolean Now_enabled() {return now_enabled;} private static boolean now_enabled;
// static void Now_enabled_y_() {now_enabled = Bool_.Y; manual_time = manual_time_dflt;}
// static void Now_enabled_n_() {now_enabled = Bool_.N; now_freeze = false;}
// public static void Now_set(DateAdp date) {now_enabled = true; manual_time = date;}
// public static void Now_freeze_y_() {now_freeze = true;}
// private static boolean now_freeze;
// public static DateAdp Now_time0_add_min(int minutes) {return manual_time_dflt.Add_minute(minutes);}
// @gplx.Internal protected static DateAdp Now() {
// DateAdp rv = manual_time;
// if (!now_freeze) manual_time = rv.Add_minute(1);
// return rv;
// }
}

@ -0,0 +1,90 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
public class Decimal_adp implements CompareAble {
public int compareTo(Object obj) {Decimal_adp comp = (Decimal_adp)obj; return under.compareTo(comp.under);}
protected Decimal_adp(BigDecimal v) {this.under = v;} private final BigDecimal under;
protected Decimal_adp(int v) {this.under = new BigDecimal(v);}
public Object Under() {return under;}
public BigDecimal Under_as_native() {return under;}
public int Precision() {return under.precision();}
public int Frac_1000() {return (int)(under.movePointRight(3).floatValue() % 1000);}
public boolean Eq(Decimal_adp v) {return v.under.doubleValue() == under.doubleValue();}
public boolean Eq(int v) {return under.doubleValue() == v;}
public String To_str() {
BigDecimal tmp = under;
int tmp_scale = tmp.scale();
if (tmp_scale <= -14) return tmp.toString(); // NOTE: if large number, call .toString which will return exponential notaion (1E##) instead of literal (1000....); 14 matches MW code; DATE:2015-04-10
if (tmp_scale > 14)
tmp = tmp.setScale(14, RoundingMode.DOWN); // NOTE: if small number, round down to remove excessive zeroes; 14 matches PHP/C# values more closely; RoundingMode.Down for same reason; see E, Pi tests
return tmp .stripTrailingZeros() // NOTE: stripTrailingZeros for exp tests; EX: 120.0 -> 120; 0.01200000000000 -> .012
.toPlainString(); // NOTE: toPlainString b/c stripTrailingZeros now converts 120 to 1.2E+2 (and any other value that is a multiple of 10)
}
public String To_str(String fmt) {
return new DecimalFormat(fmt).format(under);
}
@Override public String toString() {return under.toString();}
public int To_int() {return (int)under.doubleValue();}
public long To_long() {return (long)under.doubleValue();}
public long To_long_mult_1000() {return under.movePointRight(3).longValue();}
public double To_double() {return under.doubleValue();}
public Decimal_adp Add(Decimal_adp v) {return new Decimal_adp(under.add(v.under, Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Subtract(Decimal_adp v) {return new Decimal_adp(under.subtract(v.under, Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Multiply(Decimal_adp v) {return new Decimal_adp(under.multiply(v.under));}
public Decimal_adp Multiply(double v) {return new Decimal_adp(under.multiply(new BigDecimal(v, Decimal_adp_.Gplx_rounding_context)));}
public Decimal_adp Multiply(long v) {return new Decimal_adp(under.multiply(new BigDecimal(v)));}
public Decimal_adp Divide(Decimal_adp v) {return new Decimal_adp(under.divide(v.under, Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Mod(Decimal_adp v) {return new Decimal_adp(under.remainder(v.under, Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Abs() {return new Decimal_adp(under.abs(Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Pow(int v) {return new Decimal_adp(under.pow(v, Decimal_adp_.Gplx_rounding_context));}
public Decimal_adp Sqrt() {return new Decimal_adp(new BigDecimal(Math_.Sqrt(under.doubleValue())));}
public Decimal_adp Truncate() {return new Decimal_adp(under.intValue());}
public Decimal_adp Round_old(int v) {return new Decimal_adp(under.setScale(v, RoundingMode.HALF_UP));}
public Decimal_adp Round(int v) {
BigDecimal new_val = null;
if (v > 0) {
new_val = under.setScale(v, RoundingMode.HALF_UP);
}
else {
int actl_places = under.precision() - under.scale();
int reqd_places = -v;
if (reqd_places < actl_places)
new_val = under.round(new java.math.MathContext(actl_places - reqd_places, RoundingMode.HALF_UP));
else if (reqd_places == actl_places) {
int base_10 = (int)Math_.Pow(10, reqd_places - 1);
if (under.intValue() / base_10 < 5)
new_val = BigDecimal.ZERO;
else
new_val = new BigDecimal(Math_.Pow(10, reqd_places));
}
else
new_val = BigDecimal.ZERO;
}
return new Decimal_adp(new_val);
}
public boolean Comp_gte(Decimal_adp v) {return under.doubleValue() >= v.under.doubleValue();}
public boolean Comp_gte(int v) {return under.doubleValue() >= v;}
public boolean Comp_lte(Decimal_adp v) {return under.doubleValue() <= v.under.doubleValue();}
public boolean Comp_lte(int v) {return under.doubleValue() <= v;}
public boolean Comp_gt(Decimal_adp v) {return under.doubleValue() > v.under.doubleValue();}
public boolean Comp_gt(int v) {return under.doubleValue() > v;}
public boolean Comp_lt(Decimal_adp v) {return under.doubleValue() < v.under.doubleValue();}
public boolean Comp_lt(int v) {return under.doubleValue() < v;}
}

@ -0,0 +1,69 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class Decimal_adp_ {
public static final String Cls_val_name = "decimal";
public static final Class<?> Cls_ref_type = Decimal_adp.class;
public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
public static final Decimal_adp Zero = new Decimal_adp(0);
public static final Decimal_adp One = new Decimal_adp(1);
public static final Decimal_adp Neg1 = new Decimal_adp(-1);
public static final Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
public static final Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
public static Decimal_adp parts_(long num, int frc) {
// int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
// int pow10 = (int)Math_.Pow(10, log10);
int pow10 = XtoPow10(frc);
return divide_((num * (pow10)) + frc, pow10);
}
public static Decimal_adp cast(Object obj) {return (Decimal_adp)obj;}
static int XtoPow10(int v) {
if (v > -1 && v < 10) return 10;
else if (v > 9 && v < 100) return 100;
else if (v > 99 && v < 1000) return 1000;
else if (v > 999 && v < 10000) return 10000;
else if (v > 9999 && v < 100000) return 100000;
else if (v > 99999 && v < 1000000) return 1000000;
else if (v > 999999 && v < 10000000) return 10000000;
else if (v > 9999999 && v < 100000000) return 100000000;
else if (v > 99999999 && v < 1000000000) return 1000000000;
else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
}
public static String CalcPctStr(long dividend, long divisor, String fmt) {
if (divisor == 0) return "%ERR";
return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
}
public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
public static Decimal_adp divide_(long lhs, long rhs) { return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context)); } public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));} public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));} public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);} public static Decimal_adp parse(String raw) {
try {
DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US); // always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
nf.setParseBigDecimal(true);
BigDecimal bd = (BigDecimal)nf.parse(raw);
return new Decimal_adp(bd);
} catch (ParseException e) {
throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw);
}
} public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN); public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31 }

@ -0,0 +1,86 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Decimal_adp__tst {
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt();
@Test public void divide_() {
fxt.Test_divide(1, 1000, "0.001");
fxt.Test_divide(1, 3, "0.33333333333333");
fxt.Test_divide(1, 7, "0.14285714285714");
}
@Test public void base1000_() {
fxt.Test_base_1000(1000, "1");
fxt.Test_base_1000(1234, "1.234");
fxt.Test_base_1000(123, "0.123");
}
@Test public void parts_() {
fxt.Test_parts(1, 0, "1");
fxt.Test_parts(1, 2, "1.2");
fxt.Test_parts(1, 23, "1.23");
fxt.Test_parts(123, 4567, "123.4567");
}
@Test public void parse() {
fxt.Test_parse("1", "1");
fxt.Test_parse("1.2", "1.2");
fxt.Test_parse("0.1", "0.1");
}
@Test public void Truncate_decimal() {
fxt.Test_truncate_decimal("1", "1");
fxt.Test_truncate_decimal("1.1", "1");
fxt.Test_truncate_decimal("1.9", "1");
}
@Test public void Fraction1000() {
fxt.Test_frac_1000(1, 1000, 1); // 0.001
fxt.Test_frac_1000(1, 3, 333); // 0.33333333
fxt.Test_frac_1000(1234, 1000, 234); // 1.234
fxt.Test_frac_1000(12345, 10000, 234); // 1.2345
}
@Test public void Lt() {
fxt.Test_comp_lt(1,123, 2, true);
fxt.Test_comp_lt(1,99999999, 2, true);
}
@Test public void To_str_fmt() {
fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
fxt.Test_to_str_fmt(1, 2, "00.00", "00.50");
}
@Test public void Round() {
fxt.Test_round("123.456", 3, "123.456");
fxt.Test_round("123.456", 2, "123.46");
fxt.Test_round("123.456", 1, "123.5");
fxt.Test_round("123.456", 0, "123");
fxt.Test_round("123.456", -1, "120");
fxt.Test_round("123.456", -2, "100");
fxt.Test_round("123.456", -3, "0");
fxt.Test_round("6", -1, "10");
fxt.Test_round("5", -1, "10");
fxt.Test_round("6", -2, "0");
}
}
class Decimal_adp__fxt {
public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse(raw).To_str());}
public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse(expd).To_str(), Decimal_adp_.parse(raw).Truncate().To_str());}
public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse(raw).Round(places).To_str(), "round");}
}

@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Double_ {
public static final String Cls_val_name = "double";
public static final Class<?> Cls_ref_type = Double.class;
public static final double
MinValue = Double.MIN_VALUE
, NaN = Double.NaN
, Inf_pos = Double.POSITIVE_INFINITY
;
public static final byte[]
NaN_bry = Bry_.new_a7("NaN")
, Inf_pos_bry = Bry_.new_a7("INF")
;
public static boolean IsNaN(double v) {return Double.isNaN(v);}
public static double cast(Object o) {try {return (Double)o;} catch(Exception e) {throw Err_.new_type_mismatch_w_exc(e, double.class, o);}}
public static double parse(String raw) {try {return Double.parseDouble(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, double.class, raw);}}
public static double parse_or(String raw, double v) {try {return Double.parseDouble(raw);} catch(Exception e) {Err_.Noop(e); return v;}}
public static double coerce_(Object v) {
try {String s = String_.as_(v); return s == null ? Double_.cast(v) : Double_.parse(s);}
catch (Exception e) {throw Err_.new_cast(e, double.class, v);}
}
public static String To_str(double v) {
int v_int = (int)v;
return v - v_int == 0 ? Int_.To_str(v_int) : Double.toString(v);
}
public static String To_str_loose(double v) {
int v_as_int = (int)v;
return v == v_as_int
? Int_.To_str(v_as_int) // convert to int, and call print String to eliminate any trailing decimal places
: Float_.To_str((float)v); // calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d; DATE:2014-07-29
}
public static int Compare(double lhs, double rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
}

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Double__tst {
private Double__fxt fxt = new Double__fxt();
@Test public void Xto_str_loose() {
fxt.Test_Xto_str_loose(2449.6000000d , "2449.6");
fxt.Test_Xto_str_loose(623.700d , "623.7");
}
}
class Double__fxt {
public void Test_Xto_str_loose(double v, String expd) {Tfds.Eq(expd, Double_.To_str_loose(v));}
}

@ -0,0 +1,20 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Enm_ {
public static int To_int(Object enm) {return Ordinal_lang(enm);}
private static int Ordinal_lang(Object v) {return ((Enum)v).ordinal();}
}

@ -0,0 +1,89 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.errs.*;
public class Err extends RuntimeException {
private final boolean is_gplx;
private final String trace;
private Err_msg[] msgs_ary = new Err_msg[8]; private int msgs_len = 8, msgs_idx = 0;
public Err(boolean is_gplx, String trace, String type, String msg, Object... args) {
this.is_gplx = is_gplx;
// NOTE: Err_ factory methods pass in null stack trace for gplx excs; call Stack_trace here, note that trace will not show constructor
this.trace = is_gplx ? Err_.Trace_lang(this) : trace;
Msgs_add(type, msg, args);
}
// marks messages logged so they can be ignored; used by Gfh_utl
public boolean Logged() {return logged;} public Err Logged_y_() {logged = true; return this;} private boolean logged;
// ignores current frame for reporting messages
public int Trace_ignore() {return trace_ignore;} public Err Trace_ignore_add_1_() {++trace_ignore; return this;} private int trace_ignore = 0;
public Err Args_add(Object... args) {msgs_ary[msgs_idx - 1].Args_add(args); return this;} // i - 1 to get current
public String To_str__full() {return To_str(Bool_.N, Bool_.Y);}
public String To_str__log() {return To_str(Bool_.Y, Bool_.Y);}
public String To_str__msg_only(){
return msgs_idx == 0 ? "<<MISSING ERROR MESSAGE>>" : msgs_ary[0].To_str_wo_type(); // take 1st message only
}
public String To_str__top_wo_args() {
return msgs_idx == 0 ? "<<MISSING ERROR MESSAGE>>" : msgs_ary[0].To_str_wo_args();
}
private String To_str(boolean called_by_log, boolean include_trace) {
String nl_str = called_by_log ? "\t" : "\n";
String rv = "";
for (int i = 0; i < msgs_idx; ++i) {
rv += "[err " + Int_.To_str(i) + "] " + String_.Replace(msgs_ary[i].To_str(), "\n", nl_str) + nl_str;
}
if (include_trace)
rv += "[trace]:" + Trace_to_str(is_gplx, called_by_log, trace_ignore, trace == null ? Err_.Trace_lang(this) : trace);
return rv;
}
@Override public String getMessage() {return To_str__msg_only();}
public static String Trace_to_str(boolean is_gplx, boolean called_by_log, int ignore_lines, String trace) {
if (trace == null) return ""; // WORKAROUND:.NET: StackTrace is only available when error is thrown; can't do "Console.Write(new Exception().StackTrace);
String[] lines = String_.Split_lang(trace, '\n'); int lines_len = lines.length;
int line_bgn = 0;
if (is_gplx) { // remove Err_.new_wo_type lines from trace for gplx exceptions
for (int i = 0; i < lines_len; ++i) {
String line = lines[i];
if (String_.Has_at_bgn(line, "gplx.Err_.new")) continue; // ignore trace frames with "gplx.Err_.new"; EX: throw Err_.new_unimplemented
line_bgn = i + ignore_lines;
break;
}
}
// concat lines
String rv = "";
String line_bgn_dlm = called_by_log ? "\t " : "\n "; // "\n " indents
for (int i = line_bgn; i < lines_len; ++i)
rv += line_bgn_dlm + lines[i];
return rv;
}
@gplx.Internal protected void Msgs_add(String type, String msg, Object[] args) {
if (msgs_idx == msgs_len) {
int new_len = msgs_len * 2;
Err_msg[] new_ary = new Err_msg[new_len];
Array_.Copy_to(msgs_ary, new_ary, 0);
this.msgs_ary = new_ary;
this.msgs_len = new_len;
}
msgs_ary[msgs_idx] = new Err_msg(type, msg, args);
++msgs_idx;
}
}

@ -0,0 +1,77 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Err_ {
private static String Type__gplx = "gplx", Trace_null = null;
public static void Noop(Exception e) {}
public static Err New(String msg, Object... args) {return new Err(Bool_.Y, Trace_null, "", String_.Format(msg, args));}
public static Err new_(String type, String msg, Object... args) {return new Err(Bool_.Y, Trace_null, type, msg, args);}
public static Err new_wo_type(String msg, Object... args) {return new Err(Bool_.Y, Trace_null, Type__gplx, msg, args);}
public static Err new_exc(Exception e, String type, String msg, Object... args) {
Err rv = Cast_or_make(e);
rv.Msgs_add(type, msg, args);
return rv;
}
public static Err new_unhandled(Object val) {return new Err(Bool_.Y, Trace_null, Type__gplx, "val is not in switch/if", "val", val);}
public static Err new_unhandled_default(Object val) {return new Err(Bool_.Y, Trace_null, Type__gplx, "val is not in switch", "val", val);}
public static Err new_unsupported() {return new Err(Bool_.Y, Trace_null, Type__gplx, "method not supported");}
public static Err new_unimplemented() {return new Err(Bool_.Y, Trace_null, Type__gplx, "method not implemented");}
public static Err new_unimplemented_w_msg(String msg, Object... args) {return new Err(Bool_.Y, Trace_null, Type__gplx, msg, args);}
public static Err new_deprecated(String s) {return new Err(Bool_.Y, Trace_null, Type__gplx, "deprecated", "method", s);}
public static Err new_parse_type(Class<?> c, String raw) {return new_parse(Type_.Canonical_name(c), raw);}
public static Err new_parse_exc(Exception e, Class<?> c, String raw) {return new_parse(Type_.Canonical_name(c), raw).Args_add("e", Err_.Message_lang(e));}
public static Err new_parse(String type, String raw) {return new Err(Bool_.Y, Trace_null, Type__gplx, "parse failed", "type", type, "raw", raw);}
public static Err new_null() {return new Err(Bool_.Y, Trace_null, Type__gplx, "null obj");}
public static Err new_null(String arg) {return new Err(Bool_.Y, Trace_null, Type__gplx, "null obj", "arg", arg);}
public static Err new_missing_idx(int idx, int len) {return new Err(Bool_.Y, Trace_null, Type__gplx, "index is out of bounds", "idx", idx, "len", len);}
public static Err new_missing_key(String key) {return new Err(Bool_.Y, Trace_null, Type__gplx, "key not found", "key", key);}
public static Err new_invalid_op(String msg) {return new Err(Bool_.Y, Trace_null, Type__gplx, msg);}
public static Err new_invalid_arg(String msg, Object... args) {return new Err(Bool_.Y, Trace_null, Type__gplx, msg, args);}
public static Err new_op_canceled() {return new Err(Bool_.Y, Trace_null, Type__op_canceled, "canceled by usr");}
public static Err new_type_mismatch_w_exc(Exception ignore, Class<?> t, Object o) {return new_type_mismatch(t, o);}
public static Err new_type_mismatch(Class<?> t, Object o) {return new Err(Bool_.Y, Trace_null, Type__gplx, "type mismatch", "expdType", Type_.Canonical_name(t), "actlType", Type_.Name_by_obj(o), "actlObj", Object_.Xto_str_strict_or_null_mark(o));}
public static Err new_cast(Exception ignore, Class<?> t, Object o) {
String o_str = "";
try {o_str = Object_.Xto_str_strict_or_null_mark(o);}
catch (Exception e) {o_str = "<ERROR>"; Err_.Noop(e);}
return new Err(Bool_.Y, Trace_null, Type__gplx, "cast failed", "type", Type_.Name(t), "obj", o_str);
}
public static String Message_gplx_full(Exception e) {return Cast_or_make(e).To_str__full();}
public static String Message_gplx_log(Exception e) {return Cast_or_make(e).To_str__log();}
public static String Message_lang(Throwable e) {
return Error.class.isAssignableFrom(e.getClass())
? e.toString() // error has null for "getMessage()" return "toString()" instead
: e.getMessage();
}
public static String Trace_lang(Throwable e) {return Trace_lang_exec(e.getStackTrace());}
private static String Trace_lang_exec(StackTraceElement[] ary) {
String rv = "";
int len = ary.length;
for (int i = 0; i < len; i++) {
if (i != 0) rv += "\n";
rv += ary[i].toString();
}
return rv;
}
public static Err Cast_or_null(Exception e) {return Type_.Eq_by_obj(e, Err.class) ? (Err)e : null;}
public static Err Cast_or_make(Throwable e) {return Type_.Eq_by_obj(e, Err.class) ? (Err)e : new Err(Bool_.N, Err_.Trace_lang(e), Type_.Name_by_obj(e), Err_.Message_lang(e));}
public static final String Type__op_canceled = "gplx.op_canceled";
}

@ -0,0 +1,45 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Err_tst {
private final Err_fxt fxt = new Err_fxt();
@Test public void Trace_to_str__gplx() {
fxt.Test_Trace_to_str(Bool_.Y, Bool_.N, 0, String_.Concat_lines_nl_skip_last
( "gplx.Err_.new_wo_type(Err_.java:1)" // ignore this line
, "gplx.String_.Len(String_.java:2)"
), String_.Concat_lines_nl_skip_last
( ""
, " gplx.String_.Len(String_.java:2)"
));
}
@Test public void Trace_to_str__gplx_ignore() {
fxt.Test_Trace_to_str(Bool_.Y, Bool_.N, 1, String_.Concat_lines_nl_skip_last
( "gplx.Err_.new_wo_type(Err_.java:1)" // ignore this line
, "gplx.String_.Fail(String_.java:2)" // ignore this line also
, "gplx.String_.Len(String_.java:3)"
), String_.Concat_lines_nl_skip_last
( ""
, " gplx.String_.Len(String_.java:3)"
));
}
}
class Err_fxt {
public void Test_Trace_to_str(boolean is_gplx, boolean called_by_log, int ignore_lines, String trace, String expd) {
String actl = Err.Trace_to_str(is_gplx, called_by_log, ignore_lines, trace);
Tfds.Eq_str_lines(expd, actl);
}
}

@ -0,0 +1,39 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Float_ {
public static final String Cls_val_name = "float";
public static final Class<?> Cls_ref_type = Float.class;
public static final float NaN = Float.NaN;;
public static boolean IsNaN(float v) {return Float.isNaN(v);}
public static float cast(Object obj) {try {return (Float)obj;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, float.class, obj);}}
public static float parse(String raw) {try {return Float.parseFloat(raw);} catch(Exception exc) {throw Err_.new_parse_exc(exc, float.class, raw);}}
public static int Compare(float lhs, float rhs) {
if ( lhs == rhs) return CompareAble_.Same;
else if ( lhs < rhs) return CompareAble_.Less;
else /*lhs > rhs*/ return CompareAble_.More;
}
public static String To_str(float v) {
int v_int = (int)v;
return v - v_int == 0 ? Int_.To_str(v_int) : Float.toString(v);
}
public static float Div(int val, int divisor) {return (float)val / (float)divisor;}
public static float Div(long val, long divisor) {return (float)val / (float)divisor;}
public static int RoundUp(float val) {
int rv = (int)val;
return (rv == val) ? rv : rv + 1;
}
}

@ -0,0 +1,70 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.interfaces.*;
public interface GfoMsg {
String Key();
GfoMsg CloneNew();
String To_str();
GfoMsg Clear();
GfoMsg Parse_(boolean v);
int Args_count();
Keyval Args_getAt(int i);
GfoMsg Args_ovr(String k, Object v);
void Args_reset();
GfoMsg Add(String k, Object v);
int Subs_count();
GfoMsg Subs_getAt(int i);
GfoMsg Subs_add(GfoMsg m);
GfoMsg Subs_(GfoMsg... ary);
boolean ReadBool(String k);
boolean ReadBoolOr(String k, boolean or);
boolean ReadBoolOrFalse(String k);
boolean ReadBoolOrTrue(String k);
int ReadInt(String k);
int ReadIntOr(String k, int or);
long ReadLong(String k);
long ReadLongOr(String k, long or);
float ReadFloat(String k);
float ReadFloatOr(String k, float or);
double ReadDouble(String k);
double ReadDoubleOr(String k, double or);
DateAdp ReadDate(String k);
DateAdp ReadDateOr(String k, DateAdp or);
Decimal_adp ReadDecimal(String k);
Decimal_adp ReadDecimalOr(String k, Decimal_adp or);
String ReadStr(String k);
String ReadStrOr(String k, String or);
Io_url ReadIoUrl(String k);
Io_url ReadIoUrlOr(String k, Io_url url);
boolean ReadYn(String k);
boolean ReadYn_toggle(String k, boolean cur);
boolean ReadYnOrY(String k);
byte ReadByte(String k);
byte[] ReadBry(String k);
byte[] ReadBryOr(String k, byte[] or);
Object ReadObj(String k);
Object ReadObj(String k, ParseAble parseAble);
Object ReadObjOr(String k, ParseAble parseAble, Object or);
String[]ReadStrAry(String k, String spr);
String[]ReadStrAryIgnore(String k, String spr, String ignore);
byte[][]ReadBryAry(String k, byte spr);
Object ReadValAt(int i);
Object CastObj(String k);
Object CastObjOr(String k, Object or);
}

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class GfoMsgUtl {
public static int SetInt(GfsCtx ctx, GfoMsg m, int cur) {return ctx.Deny() ? cur : m.ReadIntOr("v", cur);}
public static boolean SetBool(GfsCtx ctx, GfoMsg m, boolean cur) {return ctx.Deny() ? cur : m.ReadBoolOr("v", cur);}
public static String SetStr(GfsCtx ctx, GfoMsg m, String cur) {return ctx.Deny() ? cur : m.ReadStrOr("v", cur);}
public static Io_url SetIoUrl(GfsCtx ctx, GfoMsg m, Io_url cur) {return ctx.Deny() ? cur : m.ReadIoUrlOr("v", cur);}
public static Decimal_adp SetDecimal(GfsCtx ctx, GfoMsg m, Decimal_adp cur) {return ctx.Deny() ? cur : m.ReadDecimalOr("v", cur);}
}

@ -0,0 +1,268 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*; import gplx.core.strings.*; import gplx.core.brys.*; import gplx.core.interfaces.*;
public class GfoMsg_ {
public static GfoMsg as_(Object obj) {return obj instanceof GfoMsg ? (GfoMsg)obj : null;}
public static final GfoMsg Null = new GfoMsg_base().ctor_("<<NULL MSG>>", false);
public static GfoMsg new_parse_(String key) {return new GfoMsg_base().ctor_(key, true);}
public static GfoMsg new_cast_(String key) {return new GfoMsg_base().ctor_(key, false);}
public static GfoMsg srl_(GfoMsg owner, String key) {
GfoMsg rv = new_parse_(key);
owner.Subs_add(rv);
return rv;
}
public static GfoMsg root_(String... ary) {return root_leafArgs_(ary);}
public static GfoMsg root_leafArgs_(String[] ary, Keyval... kvAry) {
int len = Array_.Len(ary); if (len == 0) throw Err_.new_invalid_arg("== 0", "@len", len);
GfoMsg root = new GfoMsg_base().ctor_(ary[0], false);
GfoMsg owner = root;
for (int i = 1; i < len; i++) {
String key = ary[i];
GfoMsg cur = new GfoMsg_base().ctor_(key, false);
owner.Subs_add(cur);
owner = cur;
}
for (int i = 0; i < kvAry.length; i++) {
Keyval kv = kvAry[i];
owner.Add(kv.Key(), kv.Val());
}
return root;
}
public static GfoMsg chain_(GfoMsg owner, String key) {
GfoMsg sub = owner;
List_adp list = List_adp_.New();
list.Add(sub.Key());
while (sub != null) {
if (sub.Subs_count() == 0) break;
sub = (GfoMsg)sub.Subs_getAt(0);
list.Add(sub.Key());
}
list.Add(key);
GfoMsg root = GfoMsg_.new_parse_((String)list.Get_at(0));
GfoMsg cur = root;
for (int i = 1; i < list.Count(); i++) {
String k = (String)list.Get_at(i);
GfoMsg mm = GfoMsg_.new_parse_(k);
cur.Subs_add(mm);
cur = mm;
}
return root;
}
public static GfoMsg wtr_() {return new GfoMsg_wtr().ctor_("", false);}
public static GfoMsg rdr_(String cmd) {return new GfoMsg_rdr().ctor_(cmd, false);}
public static GfoMsg basic_(String cmd, Object... vals) {
GfoMsg rv = new_cast_(cmd);
int len = vals.length;
for (int i = 0; i < len; i++)
rv.Add("", vals[i]);
return rv;
}
}
class GfoMsg_wtr extends GfoMsg_base {
@Override protected Object ReadOr(String k, Object defaultOr) {
if (args == null) args = List_adp_.New();
args.Add(Keyval_.new_(k, null));
return defaultOr;
}
}
class GfoMsg_rdr extends GfoMsg_base {
@Override protected Object ReadOr(String k, Object defaultOr) {
if (args == null) args = List_adp_.New();
args.Add(Keyval_.new_(k, defaultOr));
return defaultOr;
}
}
class GfoMsg_base implements GfoMsg {
public String Key() {return key;} private String key;
public int Subs_count() {return subs == null ? 0 : subs.Count();}
public GfoMsg Subs_getAt(int i) {return subs == null ? null : (GfoMsg)subs.Get_at(i);}
public GfoMsg Subs_add(GfoMsg m) {if (subs == null) subs = List_adp_.New(); subs.Add(m); return this;}
public GfoMsg Subs_(GfoMsg... ary) {for (GfoMsg m : ary) Subs_add(m); return this;}
public int Args_count() {return args == null ? 0 : args.Count();}
public void Args_reset() {
counter = 0;
Args_reset(this);
}
public GfoMsg Clear() {
this.Args_reset();
if (subs != null) subs.Clear();
if (args != null) args.Clear();
return this;
}
static void Args_reset(GfoMsg owner) {
int len = owner.Subs_count();
for (int i = 0; i < len; i++) {
GfoMsg sub = owner.Subs_getAt(i);
sub.Args_reset();
}
}
public Keyval Args_getAt(int i) {return args == null ? null : (Keyval)args.Get_at(i);}
public GfoMsg Args_ovr(String k, Object v) {
if (args == null) args = List_adp_.New();
for (int i = 0; i < args.Count(); i++) {
Keyval kv = (Keyval)args.Get_at(i);
if (String_.Eq(k, kv.Key())) {
kv.Val_(v);
return this;
}
}
args.Add(Keyval_.new_(k, v));
return this;
}
public GfoMsg Parse_(boolean v) {parse = v; return this;}
public GfoMsg Add(String k, Object v) {
if (args == null) args = List_adp_.New();
args.Add(Keyval_.new_(k, v));
return this;
}
public boolean ReadBool(String k) {Object rv = ReadOr(k,false); if (rv == Nil) ThrowNotFound(k); return parse ? Yn.parse_or((String)rv, false) : Bool_.Cast(rv);}
public int ReadInt(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Int_.Parse((String)rv) : Int_.Cast(rv);}
public byte ReadByte(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Byte_.Parse((String)rv) : Byte_.Cast(rv);}
public long ReadLong(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Long_.parse((String)rv) : Long_.cast(rv);}
public float ReadFloat(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Float_.parse((String)rv) : Float_.cast(rv);}
public double ReadDouble(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Double_.parse((String)rv) : Double_.cast(rv);}
public Decimal_adp ReadDecimal(String k) {Object rv = ReadOr(k, 0) ; if (rv == Nil) ThrowNotFound(k); return parse ? Decimal_adp_.parse((String)rv) : Decimal_adp_.cast(rv);}
public String ReadStr(String k) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return (String)rv;}
public DateAdp ReadDate(String k) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return parse ? DateAdp_.parse_gplx((String)rv) : DateAdp_.cast(rv);}
public Io_url ReadIoUrl(String k) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return parse ? Io_url_.new_any_((String)rv) : Io_url_.cast(rv);}
public Object CastObj(String k) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return rv;}
public boolean ReadBoolOr(String k, boolean or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Yn.parse_or((String)rv, or) : Bool_.Cast(rv);}
public int ReadIntOr(String k, int or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Int_.Parse((String)rv) : Int_.Cast(rv);}
public long ReadLongOr(String k, long or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Long_.parse((String)rv) : Long_.cast(rv);}
public float ReadFloatOr(String k, float or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Float_.parse((String)rv) : Float_.cast(rv);}
public double ReadDoubleOr(String k,double or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Double_.parse((String)rv) : Double_.cast(rv);}
public Decimal_adp ReadDecimalOr(String k,Decimal_adp or) {Object rv = ReadOr(k, or); if (rv == Nil) return or ; return parse ? Decimal_adp_.parse((String)rv) : Decimal_adp_.cast(rv);}
public String ReadStrOr(String k, String or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return (String)rv;}
public DateAdp ReadDateOr(String k, DateAdp or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? DateAdp_.parse_gplx((String)rv) : DateAdp_.cast(rv);}
public Io_url ReadIoUrlOr(String k, Io_url or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? Io_url_.new_any_((String)rv) : Io_url_.cast(rv);}
public boolean ReadBoolOrFalse(String k) {Object rv = ReadOr(k,false); if (rv == Nil) return false ; return parse ? Yn.parse_or((String)rv, false) : Bool_.Cast(rv);}
public boolean ReadBoolOrTrue(String k) {Object rv = ReadOr(k, true); if (rv == Nil) return true ; return parse ? Yn.parse_or((String)rv, true) : Bool_.Cast(rv);}
public boolean ReadYnOrY(String k) {Object rv = ReadOr(k, true); if (rv == Nil) return true ; return parse ? Yn.parse_or((String)rv, true) : Bool_.Cast(rv);}
public boolean ReadYn(String k) {Object rv = ReadOr(k,false); if (rv == Nil) ThrowNotFound(k); return parse ? Yn.parse_or((String)rv, false) : Yn.coerce_(rv);}
public boolean ReadYn_toggle(String k, boolean cur) {
Object rv = ReadOr(k, "!");
if (rv == Nil) ThrowNotFound(k);
if (!parse) throw Err_.new_wo_type("only parse supported");
String rv_str = (String)rv;
return (String_.Eq(rv_str, "!")) ? !cur : Yn.parse(rv_str);
}
public byte[] ReadBry(String k) {Object rv = ReadOr(k,false); if (rv == Nil) ThrowNotFound(k); return parse ? Bry_.new_u8((String)rv) : (byte[])rv;}
public byte[] ReadBryOr(String k, byte[] or) {Object rv = ReadOr(k, or); if (rv == Nil) return or; return parse ? Bry_.new_u8((String)rv) : (byte[])rv;}
public Object CastObjOr(String k, Object or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return rv;}
public Object ReadObj(String k) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return rv;}
public Object ReadObj(String k, ParseAble parseAble) {Object rv = ReadOr(k, null); if (rv == Nil) ThrowNotFound(k); return parse ? parseAble.ParseAsObj((String)rv) : rv;}
public Object ReadObjOr(String k, ParseAble parseAble, Object or) {Object rv = ReadOr(k, or) ; if (rv == Nil) return or ; return parse ? parseAble.ParseAsObj((String)rv) : rv;}
public String[] ReadStrAry(String k, String spr) {return String_.Split(ReadStr(k), spr);}
public byte[][] ReadBryAry(String k, byte spr) {return Bry_split_.Split(ReadBry(k), spr);}
public String[] ReadStrAryIgnore(String k, String spr, String ignore) {return String_.Split(String_.Replace(ReadStr(k), ignore, ""), spr);}
public Object ReadValAt(int i) {return Args_getAt(i).Val();}
@gplx.Virtual protected Object ReadOr(String k, Object defaultOr) {
if (args == null) return Nil; // WORKAROUND.gfui: args null for DataBndr_whenEvt_execCmd
if (!String_.Eq(k, "")) {
for (int i = 0; i < args.Count(); i++) {
Keyval kv = (Keyval)args.Get_at(i);
if (String_.Eq(k, kv.Key())) return kv.Val();
}
}
if (counter >= args.Count()) return Nil;
for (int i = 0; i < args.Count(); i++) {
Keyval kv = (Keyval)args.Get_at(i);
if (String_.Eq(kv.Key(), "") && i >= counter) {
counter++;
return kv.Val();
}
}
return Nil;
} int counter = 0;
void ThrowNotFound(String k) {throw Err_.new_wo_type("arg not found in msg", "k", k, "counter", counter, "args", args);}
String ArgsXtoStr() {
if (this.Args_count() == 0) return "<<EMPTY>>";
String_bldr sb = String_bldr_.new_();
for (int i = 0; i < this.Args_count(); i++) {
Keyval rv = (Keyval)this.Args_getAt(i);
sb.Add_fmt("{0};", rv.Key());
}
return sb.To_str();
}
public GfoMsg CloneNew() {
GfoMsg_base rv = new GfoMsg_base().ctor_(key, parse);
if (args != null) {
rv.args = List_adp_.New();
for (int i = 0; i < args.Count(); i++)
rv.args.Add(args.Get_at(i));
}
if (subs != null) {
rv.subs = List_adp_.New();
for (int i = 0; i < args.Count(); i++) {
GfoMsg sub = (GfoMsg)args.Get_at(i);
rv.subs.Add(sub.CloneNew()); // NOTE: recursion
}
}
return rv;
}
protected List_adp args;
List_adp subs;
public String To_str() {
String_bldr sb = String_bldr_.new_();
To_str(sb, new XtoStrWkr_gplx(), this);
return sb.To_str_and_clear();
}
void To_str(String_bldr sb, XtoStrWkr wkr, GfoMsg m) {
sb.Add(m.Key());
if (m.Subs_count() == 0) {
sb.Add(":");
boolean first = true;
for (int i = 0; i < m.Args_count(); i++) {
Keyval kv = m.Args_getAt(i);
if (kv.Val() == null) continue;
if (!first) sb.Add(" ");
sb.Add(kv.Key());
sb.Add("='");
sb.Add(wkr.To_str(kv.Val()));
sb.Add("'");
first = false;
}
sb.Add(";");
}
else {
sb.Add(".");
To_str(sb, wkr, m.Subs_getAt(0));
}
}
public GfoMsg_base ctor_(String key, boolean parse) {this.key = key; this.parse = parse; return this;} private boolean parse;
@gplx.Internal protected GfoMsg_base(){}
static final String_obj_val Nil = String_obj_val.new_("<<NOT FOUND>>");
}
interface XtoStrWkr {
String To_str(Object o);
}
class XtoStrWkr_gplx implements XtoStrWkr {
public String To_str(Object o) {
if (o == null) return "<<NULL>>";
Class<?> type = Type_.Type_by_obj(o);
String rv = null;
if (Type_.Eq(type, String_.Cls_ref_type)) rv = String_.cast(o);
else if (Type_.Eq(type, Int_.Cls_ref_type)) return Int_.To_str(Int_.Cast(o));
else if (Type_.Eq(type, Bool_.Cls_ref_type)) return Yn.To_str(Bool_.Cast(o));
else if (Type_.Eq(type, DateAdp_.Cls_ref_type)) return DateAdp_.cast(o).XtoStr_gplx();
else rv = Object_.Xto_str_strict_or_empty(o);
return String_.Replace(rv, "'", "''");
}
}

@ -0,0 +1,49 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.langs.gfs.*;
public class GfoMsg_tst {
@Before public void setup() {
GfsCore.Instance.AddObj(new Mok(), "Mok");
}
@Test public void Write1() {
GfoMsg m = GfoMsg_.root_leafArgs_(String_.Ary("a", "b"), Keyval_.new_("int0", 1));
tst_Msg(m, "a.b:int0='1';");
}
@Test public void Write() {
Mok mok = new Mok();
tst_Msg(Gfo_invk_to_str.WriteMsg(mok, Mok.Invk_Cmd0, true, 1, "a"), "Mok.Cmd0:bool0='y' int0='1' str0='a';");
mok.Int0 = 2;
mok.Bool0 = true;
mok.Str0 = "b";
tst_Msg(Gfo_invk_to_str.ReadMsg(mok, Mok.Invk_Cmd0), "Mok.Cmd0:bool0='y' int0='2' str0='b';");
}
void tst_Msg(GfoMsg m, String expd) {Tfds.Eq(expd, m.To_str());}
class Mok implements Gfo_invk {
public boolean Bool0;
public int Int0;
public String Str0;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_Cmd0)) {
Bool0 = m.ReadBoolOr("bool0", Bool0);
Int0 = m.ReadIntOr("int0", Int0);
Str0 = m.ReadStrOr("str0", Str0);
if (ctx.Deny()) return this;
}
return this;
} public static final String Invk_Cmd0 = "Cmd0";
}
}

@ -0,0 +1,19 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface GfoTemplate {
Object NewCopy(GfoTemplate template);
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class GfoTemplateFactory implements Gfo_invk {
public void Reg(String key, GfoTemplate template) {hash.Add(key, template);}
public Object Make(String key) {
GfoTemplate template = (GfoTemplate)hash.Get_by(key);
return template.NewCopy(template);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
ctx.Match(k, k);
Object o = hash.Get_by(k);
return o == null ? Gfo_invk_.Rv_unhandled : o;
}
public static final GfoTemplateFactory Instance = new GfoTemplateFactory(); GfoTemplateFactory() {}
Hash_adp hash = Hash_adp_.New();
}

@ -0,0 +1,17 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_evt_itm extends Gfo_invk, Gfo_evt_mgr_owner {}

@ -0,0 +1,124 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.lists.*;
public class Gfo_evt_mgr {
private final Gfo_evt_mgr_owner sender; private Ordered_hash subsRegy, pubsRegy;
public Gfo_evt_mgr(Gfo_evt_mgr_owner sender) {this.sender = sender;}
@gplx.Internal protected void AddSub(Gfo_evt_mgr_owner pub, String pubEvt, Gfo_evt_itm sub, String subPrc) {
GfoEvLnk lnk = new GfoEvLnk(pub, pubEvt, sub, subPrc);
if (subsRegy == null) subsRegy = Ordered_hash_.New();
AddInList(subsRegy, pubEvt, lnk);
sub.Evt_mgr().AddPub(pubEvt, lnk);
}
@gplx.Internal protected void Lnk(Gfo_evt_mgr_owner pub) {
if (pub.Evt_mgr().lnks == null) pub.Evt_mgr().lnks = List_adp_.New();
pub.Evt_mgr().lnks.Add(this);
} List_adp lnks;
void AddInList(Ordered_hash regy, String key, GfoEvLnk lnk) {
GfoEvLnkList list = (GfoEvLnkList)regy.Get_by(key);
if (list == null) {
list = new GfoEvLnkList(key);
regy.Add(key, list);
}
list.Add(lnk);
}
@gplx.Internal protected void AddPub(String pubEvt, GfoEvLnk lnk) {
if (pubsRegy == null) pubsRegy = Ordered_hash_.New();
AddInList(pubsRegy, pubEvt, lnk);
}
@gplx.Internal protected void Pub(GfsCtx ctx, String evt, GfoMsg m) {
ctx.MsgSrc_(sender);
GfoEvLnkList subs = subsRegy == null ? null : (GfoEvLnkList)subsRegy.Get_by(evt);
if (subs != null) {
for (int i = 0; i < subs.Count(); i++) {
GfoEvLnk lnk = (GfoEvLnk)subs.Get_at(i);
lnk.Sub().Invk(ctx, 0, lnk.SubPrc(), m); // NOTE: itm.Key() needed for Subscribe_diff()
}
}
if (lnks != null) {
for (int i = 0; i < lnks.Count(); i++) {
Gfo_evt_mgr lnk = (Gfo_evt_mgr)lnks.Get_at(i);
lnk.Pub(ctx, evt, m);
}
}
}
@gplx.Internal protected void RlsSub(Gfo_evt_mgr_owner eobj) {
RlsRegyObj(pubsRegy, eobj, true);
RlsRegyObj(subsRegy, eobj, false);
}
@gplx.Internal protected void RlsPub(Gfo_evt_mgr_owner eobj) {
RlsRegyObj(pubsRegy, eobj, true);
RlsRegyObj(subsRegy, eobj, false);
}
@gplx.Internal protected void RlsRegyObj(Ordered_hash regy, Gfo_evt_mgr_owner eobj, boolean pub) {
if (regy == null) return;
List_adp delList = List_adp_.New();
for (int i = 0; i < regy.Count(); i++) {
GfoEvLnkList pubsList = (GfoEvLnkList)regy.Get_at(i);
delList.Clear();
for (int j = 0; j < pubsList.Count(); j++) {
GfoEvLnk lnk = (GfoEvLnk)pubsList.Get_at(j);
if (lnk.End(!pub) == eobj) delList.Add(lnk);
}
for (int j = 0; j < delList.Count(); j++) {
GfoEvLnk del = (GfoEvLnk)delList.Get_at(j);
del.End(pub).Evt_mgr().RlsLnk(!pub, pubsList.Key(), del.End(!pub));
pubsList.Del(del);
}
}
}
@gplx.Internal protected void RlsLnk(boolean pubEnd, String key, Gfo_evt_mgr_owner endObj) {
Ordered_hash regy = pubEnd ? pubsRegy : subsRegy;
GfoEvLnkList list = (GfoEvLnkList)regy.Get_by(key);
List_adp delList = List_adp_.New();
for (int i = 0; i < list.Count(); i++) {
GfoEvLnk lnk = (GfoEvLnk)list.Get_at(i);
if (lnk.End(pubEnd) == endObj) delList.Add(lnk);
}
for (int i = 0; i < delList.Count(); i++) {
GfoEvLnk lnk = (GfoEvLnk)delList.Get_at(i);
list.Del(lnk);
}
delList.Clear();
}
}
class GfoEvLnkList {
public String Key() {return key;} private String key;
public int Count() {return list.Count();}
public void Add(GfoEvLnk lnk) {list.Add(lnk);}
public void Del(GfoEvLnk lnk) {list.Del(lnk);}
public GfoEvLnk Get_at(int i) {return (GfoEvLnk)list.Get_at(i);}
public GfoEvLnkList(String key) {this.key = key;}
List_adp list = List_adp_.New();
}
class GfoEvLnk {
public Gfo_evt_mgr_owner Pub() {return pub;} Gfo_evt_mgr_owner pub;
public String PubEvt() {return pubEvt;} private String pubEvt;
public Gfo_evt_itm Sub() {return sub;} Gfo_evt_itm sub;
public String SubPrc() {return subPrc;} private String subPrc;
public Gfo_evt_mgr_owner End(boolean pubEnd) {return pubEnd ? pub : sub;}
public GfoEvLnk(Gfo_evt_mgr_owner pub, String pubEvt, Gfo_evt_itm sub, String subPrc) {this.pub = pub; this.pubEvt = pubEvt; this.sub = sub; this.subPrc = subPrc;}
}
class GfoEvItm {
public String Key() {return key;} private String key;
public Gfo_invk InvkAble() {return invkAble;} Gfo_invk invkAble;
public static GfoEvItm new_(Gfo_invk invkAble, String key) {
GfoEvItm rv = new GfoEvItm();
rv.invkAble = invkAble; rv.key = key;
return rv;
}
}

@ -0,0 +1,43 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Gfo_evt_mgr_ {
public static void Sub(Gfo_evt_mgr_owner pub, String pubEvt, Gfo_evt_itm sub, String subEvt) {pub.Evt_mgr().AddSub(pub, pubEvt, sub, subEvt);}
public static void Sub_same(Gfo_evt_mgr_owner pub, String evt, Gfo_evt_itm sub) {pub.Evt_mgr().AddSub(pub, evt, sub, evt);}
public static void Sub_same_many(Gfo_evt_mgr_owner pub, Gfo_evt_itm sub, String... evts) {
int len = evts.length;
for (int i = 0; i < len; i++) {
String evt = evts[i];
pub.Evt_mgr().AddSub(pub, evt, sub, evt);
}
}
public static void Pub(Gfo_evt_mgr_owner pub, String pubEvt) {pub.Evt_mgr().Pub(GfsCtx.new_(), pubEvt, GfoMsg_.new_cast_(pubEvt));}
public static void Pub_obj(Gfo_evt_mgr_owner pub, String pubEvt, String key, Object v) {pub.Evt_mgr().Pub(GfsCtx.new_(), pubEvt, msg_(pubEvt, Keyval_.new_(key, v)));}
public static void Pub_val(Gfo_evt_mgr_owner pub, String pubEvt, Object v) {pub.Evt_mgr().Pub(GfsCtx.new_(), pubEvt, msg_(pubEvt, Keyval_.new_("v", v)));}
public static void Pub_vals(Gfo_evt_mgr_owner pub, String pubEvt, Keyval... ary) {pub.Evt_mgr().Pub(GfsCtx.new_(), pubEvt, msg_(pubEvt, ary));}
public static void Pub_msg(Gfo_evt_mgr_owner pub, GfsCtx ctx, String pubEvt, GfoMsg m) {pub.Evt_mgr().Pub(ctx, pubEvt, m);}
public static void Lnk(Gfo_evt_mgr_owner pub, Gfo_evt_mgr_owner sub) {sub.Evt_mgr().Lnk(pub);}
public static void Rls_pub(Gfo_evt_mgr_owner pub) {pub.Evt_mgr().RlsPub(pub);}
public static void Rls_sub(Gfo_evt_mgr_owner sub) {sub.Evt_mgr().RlsSub(sub);}
static GfoMsg msg_(String evt, Keyval... kvAry) {
GfoMsg m = GfoMsg_.new_cast_(evt);
for (int i = 0; i < kvAry.length; i++) {
Keyval kv = kvAry[i];
m.Add(kv.Key(), kv.Val());
}
return m;
}
}

@ -0,0 +1,19 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_evt_mgr_owner {
Gfo_evt_mgr Evt_mgr();
}

@ -0,0 +1,67 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Gfo_evt_mgr_tst {
@Before public void setup() {
pub = make_(); sub = make_();
} MockEvObj pub, sub;
@Test public void Basic() {
Gfo_evt_mgr_.Sub_same(pub, "ev1", sub);
Gfo_evt_mgr_.Pub_val(pub, "ev1", "val1");
sub.tst_Handled("val1");
}
@Test public void None() {// make sure no subscribers does not cause exception
Gfo_evt_mgr_.Sub_same(pub, "ev1", sub);
Gfo_evt_mgr_.Pub_val(pub, "ev2", "val1"); //ev2 does not exist
sub.tst_Handled();
}
@Test public void Lnk() {
MockEvObj mid = make_();
mid.Evt_mgr().Lnk(pub);
Gfo_evt_mgr_.Sub_same(mid, "ev1", sub);
Gfo_evt_mgr_.Pub_val(pub, "ev1", "val1");
sub.tst_Handled("val1");
}
@Test public void RlsSub() {
this.Basic();
Gfo_evt_mgr_.Rls_sub(sub);
Gfo_evt_mgr_.Pub_val(pub, "ev1", "val1");
sub.tst_Handled();
}
@Test public void RlsPub() {
this.Basic();
Gfo_evt_mgr_.Rls_sub(pub);
Gfo_evt_mgr_.Pub_val(pub, "ev1", "val1");
sub.tst_Handled();
}
MockEvObj make_() {return new MockEvObj();}
}
class MockEvObj implements Gfo_evt_itm {
public Gfo_evt_mgr Evt_mgr() {return eventMgr;} Gfo_evt_mgr eventMgr;
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
handled.Add(m.ReadStr("v"));
return this;
}
List_adp handled = List_adp_.New();
public void tst_Handled(String... expd) {
Tfds.Eq_ary_str(expd, handled.To_str_ary());
handled.Clear();
}
public MockEvObj(){eventMgr = new Gfo_evt_mgr(this);}
}

@ -0,0 +1,26 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_invk {
Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m);
}
/*
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk__set)) {}
else return Gfo_invk_.Rv_unhandled;
return this;
} private static final String Invk__set = "set";
*/

@ -0,0 +1,41 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*;
public class Gfo_invk_ {
public static final String Mutator_suffix = "_";
public static final Gfo_invk Noop = new Gfo_invk__noop();
public static final String_obj_val
Rv_unhandled = String_obj_val.new_("Unhandled")
, Rv_handled = String_obj_val.new_("Handled")
, Rv_host = String_obj_val.new_("Host")
, Rv_cancel = String_obj_val.new_("Cancel")
, Rv_error = String_obj_val.new_("Error");
public static Gfo_invk as_(Object obj) {return obj instanceof Gfo_invk ? (Gfo_invk)obj : null;}
public static Object Invk_no_key(Gfo_invk invk) {return Invk_by_msg(invk, "", GfoMsg_.Null);}
public static Object Invk_by_key(Gfo_invk invk, String k) {return Invk_by_msg(invk, k , GfoMsg_.Null);}
public static Object Invk_by_val(Gfo_invk invk, String k, Object v) {return Invk_by_msg(invk, k , GfoMsg_.new_cast_(k).Add("v", v));}
public static Object Invk_by_msg(Gfo_invk invk, String k, GfoMsg m) {
Object rv = invk.Invk(GfsCtx.Instance, 0, k, m);
if (rv == Gfo_invk_.Rv_unhandled) throw Err_.new_wo_type("invkable did not handle message", "key", k);
return rv;
}
}
class Gfo_invk__noop implements Gfo_invk {
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return this;}
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Gfo_invk_cmd {
private final Gfo_invk itm; private final String cmd; private final GfoMsg msg;
public Gfo_invk_cmd(Gfo_invk itm, String cmd, GfoMsg msg) {
this.itm = itm; this.cmd = cmd; this.msg = msg;
}
public Object Exec() {return itm.Invk(GfsCtx.Instance, 0, cmd, msg);}
public Object Exec_by_ctx(GfsCtx ctx, GfoMsg msg) {return itm.Invk(ctx, 0, cmd, msg);}
public static final Gfo_invk_cmd Noop = new Gfo_invk_cmd(Gfo_invk_.Noop, "", GfoMsg_.Null);
public static Gfo_invk_cmd New_by_key(Gfo_invk itm, String cmd) {return New_by_val(itm, cmd, null);}
public static Gfo_invk_cmd New_by_val(Gfo_invk itm, String cmd, Object val) {
return new Gfo_invk_cmd(itm, cmd, (val == null) ? GfoMsg_.Null : GfoMsg_.new_parse_(cmd).Add("v", val));
}
}

@ -0,0 +1,66 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*;
public class Gfo_invk_cmd_mgr {
public Gfo_invk_cmd_mgr Add_cmd_many(Gfo_invk invk, String... keys) {
for (String key : keys)
list.Add(GfoInvkCmdItm.new_(key, invk));
return this;
}
public Gfo_invk_cmd_mgr Add_cmd(String key, Gfo_invk invk) {
list.Add(GfoInvkCmdItm.new_(key, invk));
return this;
}
public Gfo_invk_cmd_mgr Add_mgr(String key, Gfo_invk invk) {
list.Add(GfoInvkCmdItm.new_(key, invk).Type_isMgr_(true));
return this;
}
public Gfo_invk_cmd_mgr Add_xtn(Gfo_invk xtn) {
list.Add(GfoInvkCmdItm.new_("xtn", xtn).Type_isXtn_(true));
return this;
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m, Object host) {
for (int i = 0; i < list.Count(); i++) {
GfoInvkCmdItm itm = (GfoInvkCmdItm)list.Get_at(i);
if (itm.Type_isXtn()) {
Object invkVal = itm.Invk().Invk(ctx, ikey, k, m);
if (invkVal != Gfo_invk_.Rv_unhandled) return invkVal;
}
if (!ctx.Match(k, itm.Key())) continue;
if (itm.Type_isMgr()) return itm.Invk();
Object rv = null;
m.Add("host", host);
rv = itm.Invk().Invk(ctx, ikey, k, m);
return rv == Gfo_invk_.Rv_host ? host : rv; // if returning "this" return host
}
return Unhandled;
}
public static final String_obj_val Unhandled = String_obj_val.new_("Gfo_invk_cmd_mgr Unhandled");
List_adp list = List_adp_.New();
public static Gfo_invk_cmd_mgr new_() {return new Gfo_invk_cmd_mgr();} Gfo_invk_cmd_mgr() {}
}
class GfoInvkCmdItm {
public String Key() {return key;} private String key;
public Gfo_invk Invk() {return invk;} Gfo_invk invk;
public boolean Type_isMgr() {return type_isMgr;} public GfoInvkCmdItm Type_isMgr_(boolean v) {type_isMgr = v; return this;} private boolean type_isMgr;
public boolean Type_isXtn() {return type_isXtn;} public GfoInvkCmdItm Type_isXtn_(boolean v) {type_isXtn = v; return this;} private boolean type_isXtn;
public static GfoInvkCmdItm new_(String key, Gfo_invk invk) {
GfoInvkCmdItm rv = new GfoInvkCmdItm();
rv.key = key; rv.invk = invk;
return rv;
} GfoInvkCmdItm() {}
}

@ -0,0 +1,19 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_invk_cmd_mgr_owner {
Gfo_invk_cmd_mgr InvkMgr();
}

@ -0,0 +1,19 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_invk_root_wkr {
Object Run_str_for(Gfo_invk invk, GfoMsg msg);
}

@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.langs.gfs.*;
public class Gfo_invk_to_str {
public static GfoMsg ReadMsg(Gfo_invk invk, String k) {
GfsCtx ctx = GfsCtx.wtr_();
GfoMsg m = GfoMsg_.rdr_(k);
invk.Invk(ctx, 0, k, m);
String invkKey = GfsCore.Instance.FetchKey(invk);
GfoMsg root = GfoMsg_.new_cast_(invkKey);
root.Subs_add(m);
return root;
}
public static GfoMsg WriteMsg(Gfo_invk invk, String k, Object... ary) {return WriteMsg(GfsCore.Instance.FetchKey(invk), invk, k, ary);}
public static GfoMsg WriteMsg(String invkKey, Gfo_invk invk, String k, Object... ary) {
GfsCtx ctx = GfsCtx.wtr_();
GfoMsg m = GfoMsg_.wtr_();
invk.Invk(ctx, 0, k, m);
GfoMsg rv = GfoMsg_.new_cast_(k);
for (int i = 0; i < m.Args_count(); i++) {
Keyval kv = m.Args_getAt(i);
rv.Add(kv.Key(), ary[i]);
}
GfoMsg root = GfoMsg_.new_cast_(invkKey);
root.Subs_add(rv);
return root;
}
}

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_log {
List_adp Itms();
Gfo_log Itms_(List_adp v);
void Warn(String msg, Object... args);
void Note(String msg, Object... args);
void Info(String msg, Object... args);
void Prog(String msg, Object... args);
void Flush();
}

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.logs.*;
public class Gfo_log_ {
public static Gfo_log Instance = new Gfo_log__mem();
public static Gfo_log Instance__set(Gfo_log v) {
v.Itms_(Instance.Itms());
Instance = v;
return v;
}
public static final String File__fmt = "yyyyMMdd_HHmmss", File__ext = ".log";
public static Io_url New_url(Io_url dir) {
return dir.GenSubFil(Datetime_now.Get().XtoUtc().XtoStr_fmt(Gfo_log_.File__fmt) + Gfo_log_.File__ext);
}
public static Gfo_log New_file(Io_url dir) {
Io_url url = dir.GenSubFil(Datetime_now.Get().XtoStr_fmt(File__fmt) + File__ext);
Gfo_log__file.Delete_old_files(dir, Gfo_log_.Instance);
return new Gfo_log__file(url, new Gfo_log_itm_wtr__csv());
}
}

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Gfo_log_bfr {
private Bry_bfr bfr = Bry_bfr_.Reset(255);
public Gfo_log_bfr Add(String s) {
bfr.Add_str_a7(Datetime_now.Get().XtoUtc().XtoStr_fmt_yyyyMMdd_HHmmss_fff());
bfr.Add_byte_space();
bfr.Add_str_u8(s);
bfr.Add_byte_nl();
return this;
}
public String Xto_str() {return bfr.To_str_and_clear();}
}

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_usr_dlg extends Cancelable {
void Canceled_y_(); void Canceled_n_();
Gfo_usr_dlg__log Log_wkr(); void Log_wkr_(Gfo_usr_dlg__log v);
Gfo_usr_dlg__gui Gui_wkr(); void Gui_wkr_(Gfo_usr_dlg__gui v);
String Log_many(String grp_key, String msg_key, String fmt, Object... args);
String Warn_many(String grp_key, String msg_key, String fmt, Object... args);
Err Fail_many(String grp_key, String msg_key, String fmt, Object... args);
String Prog_many(String grp_key, String msg_key, String fmt, Object... args);
String Prog_none(String grp_key, String msg_key, String fmt);
String Note_many(String grp_key, String msg_key, String fmt, Object... args);
String Note_none(String grp_key, String msg_key, String fmt);
String Note_gui_none(String grp_key, String msg_key, String fmt);
String Prog_one(String grp_key, String msg_key, String fmt, Object arg);
String Prog_direct(String msg);
String Log_direct(String msg);
String Plog_many(String grp_key, String msg_key, String fmt, Object... args);
}

@ -0,0 +1,72 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Gfo_usr_dlg_ {
private static Gfo_usr_dlg_base test__list, test__show;
public static Gfo_usr_dlg Instance = Gfo_usr_dlg_noop.Instance; // NOTE: global instance which can be reassigned
public static final Gfo_usr_dlg Noop = Gfo_usr_dlg_noop.Instance;
public static Gfo_usr_dlg__gui Test__list__init() {
if (test__list == null)
test__list = new Gfo_usr_dlg_base(Gfo_usr_dlg__log_.Noop, Gfo_usr_dlg__gui_.Test);
Gfo_usr_dlg__gui_.Test.Clear();
Instance = test__list;
return Gfo_usr_dlg__gui_.Test;
}
public static String Test__list__term__get_1st() {
Instance = Noop;
String[] rv = ((Gfo_usr_dlg__gui_test)test__list.Gui_wkr()).Warns().To_str_ary_and_clear();
return rv.length == 0 ? "" : rv[0];
}
public static void Test__show__init() {
if (test__show == null)
test__show = new Gfo_usr_dlg_base(Gfo_usr_dlg__log_.Noop, Gfo_usr_dlg__gui_.Console);
Instance = test__show;
}
public static void Test__show__term() {
Instance = Noop;
}
public static Gfo_usr_dlg Test() {
if (test__list == null)
test__list = new Gfo_usr_dlg_base(Gfo_usr_dlg__log_.Noop, Gfo_usr_dlg__gui_.Test);
return test__list;
}
public static Gfo_usr_dlg Test_console() {
if (test_console == null)
test_console = new Gfo_usr_dlg_base(Gfo_usr_dlg__log_.Noop, Gfo_usr_dlg__gui_.Console);
return test_console;
} private static Gfo_usr_dlg_base test_console;
}
class Gfo_usr_dlg_noop implements Gfo_usr_dlg {
public boolean Canceled() {return false;} public void Canceled_y_() {} public void Canceled_n_() {}
public void Cancel() {}
public void Clear() {}
public Gfo_usr_dlg__log Log_wkr() {return Gfo_usr_dlg__log_.Noop;} public void Log_wkr_(Gfo_usr_dlg__log v) {}
public Gfo_usr_dlg__gui Gui_wkr() {return Gfo_usr_dlg__gui_.Noop;} public void Gui_wkr_(Gfo_usr_dlg__gui v) {}
public String Log_many(String grp_key, String msg_key, String fmt, Object... args) {return "";}
public String Warn_many(String grp_key, String msg_key, String fmt, Object... args) {return "";}
public Err Fail_many(String grp_key, String msg_key, String fmt, Object... args) {return Err_.new_wo_type(fmt);}
public String Prog_many(String grp_key, String msg_key, String fmt, Object... args) {return "";}
public String Prog_none(String grp_key, String msg_key, String fmt) {return "";}
public String Note_many(String grp_key, String msg_key, String fmt, Object... args) {return "";}
public String Note_none(String grp_key, String msg_key, String fmt) {return "";}
public String Note_gui_none(String grp_key, String msg_key, String fmt) {return "";}
public String Prog_one(String grp_key, String msg_key, String fmt, Object arg) {return "";}
public String Prog_direct(String msg) {return "";}
public String Log_direct(String msg) {return "";}
public String Plog_many(String grp_key, String msg_key, String fmt, Object... args) {return "";}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return this;}
public static final Gfo_usr_dlg_noop Instance = new Gfo_usr_dlg_noop(); Gfo_usr_dlg_noop() {}
}

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.lists.rings.*;
public interface Gfo_usr_dlg__gui {
void Clear();
Ring__string Prog_msgs();
void Write_prog(String text);
void Write_note(String text);
void Write_warn(String text);
void Write_stop(String text);
}

@ -0,0 +1,50 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.consoles.*; import gplx.core.lists.rings.*;
public class Gfo_usr_dlg__gui_ {
public static final Gfo_usr_dlg__gui Noop = new Gfo_usr_dlg__gui_noop();
public static final Gfo_usr_dlg__gui Console = new Gfo_usr_dlg__gui_console();
public static final Gfo_usr_dlg__gui Test = new Gfo_usr_dlg__gui_test();
public static final Gfo_usr_dlg__gui Mem = new Gfo_usr_dlg__gui_mem_string();
public static String Mem_file() {return ((Gfo_usr_dlg__gui_mem_string)Mem).file;}
}
class Gfo_usr_dlg__gui_noop implements Gfo_usr_dlg__gui {
public void Clear() {}
public Ring__string Prog_msgs() {return ring;} Ring__string ring = new Ring__string().Max_(0);
public void Write_prog(String text) {}
public void Write_note(String text) {}
public void Write_warn(String text) {}
public void Write_stop(String text) {}
}
class Gfo_usr_dlg__gui_console implements Gfo_usr_dlg__gui {
private final Console_adp__sys console = Console_adp__sys.Instance;
public void Clear() {}
public Ring__string Prog_msgs() {return ring;} private final Ring__string ring = new Ring__string().Max_(0);
public void Write_prog(String text) {console.Write_tmp(text);}
public void Write_note(String text) {console.Write_str_w_nl(text);}
public void Write_warn(String text) {console.Write_str_w_nl(text);}
public void Write_stop(String text) {console.Write_str_w_nl(text);}
}
class Gfo_usr_dlg__gui_mem_string implements Gfo_usr_dlg__gui {
public String file = "";
public void Clear() {file = "";}
public Ring__string Prog_msgs() {return ring;} private final Ring__string ring = new Ring__string().Max_(0);
public void Write_prog(String text) {file += text + "\n";}
public void Write_note(String text) {file += text + "\n";}
public void Write_warn(String text) {file += text + "\n";}
public void Write_stop(String text) {file += text + "\n";}
}

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.lists.rings.*;
public class Gfo_usr_dlg__gui_test implements Gfo_usr_dlg__gui {
public List_adp Warns() {return warns;} private final List_adp warns = List_adp_.New();
public List_adp Msgs() {return msgs;} private final List_adp msgs = List_adp_.New();
public Ring__string Prog_msgs() {return ring;} private final Ring__string ring = new Ring__string().Max_(0);
public void Clear() {msgs.Clear(); warns.Clear();}
public void Write_prog(String text) {msgs.Add(text);}
public void Write_note(String text) {msgs.Add(text);}
public void Write_warn(String text) {warns.Add(text);}
public void Write_stop(String text) {msgs.Add(text);}
}

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Gfo_usr_dlg__log extends Gfo_invk {
boolean Enabled(); void Enabled_(boolean v);
boolean Queue_enabled(); void Queue_enabled_(boolean v);
Io_url Log_dir(); void Log_dir_(Io_url v);
Io_url Session_dir();
Io_url Session_fil();
void Log_msg_to_url_fmt(Io_url url, String fmt, Object... args);
void Log_to_session(String txt);
void Log_to_session_fmt(String fmt, Object... args);
void Log_to_session_direct(String txt);
void Log_to_err(String txt);
void Log_term();
}

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Gfo_usr_dlg__log_ {
public static final Gfo_usr_dlg__log Noop = new Gfo_usr_dlg__log_noop();
}
class Gfo_usr_dlg__log_noop implements Gfo_usr_dlg__log {
public Io_url Session_fil() {return Io_url_.Empty;}
public Io_url Session_dir() {return Io_url_.Empty;}
public Io_url Log_dir() {return Io_url_.Empty;} public void Log_dir_(Io_url v) {}
public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled;
public boolean Queue_enabled() {return queue_enabled;} public void Queue_enabled_(boolean v) {queue_enabled = v;} private boolean queue_enabled;
public void Log_msg_to_url_fmt(Io_url url, String fmt, Object... args) {}
public void Log_to_session_fmt(String fmt, Object... args) {}
public void Log_to_session(String txt) {}
public void Log_to_session_direct(String txt) {}
public void Log_to_err(String txt) {}
public void Log_term() {}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return this;}
}

@ -0,0 +1,119 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*; import gplx.core.consoles.*; import gplx.core.brys.fmtrs.*;
public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
private int archive_dirs_max = 8;
private Io_url log_dir, err_fil;
private Ordered_hash queued_list = Ordered_hash_.New();
private Bry_fmtr fmtr = Bry_fmtr.New__tmp(); private Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
public boolean Queue_enabled() {return queue_enabled;} public void Queue_enabled_(boolean v) {queue_enabled = v; if (!v) this.Flush();} private boolean queue_enabled;
public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled = true;
public Io_url Session_dir() {return session_dir;} private Io_url session_dir;
public Io_url Session_fil() {return session_fil;} private Io_url session_fil;
private void Flush() {
int queued_len = queued_list.Count();
for (int i = 0; i < queued_len; i++) {
Usr_log_fil fil = (Usr_log_fil)queued_list.Get_at(i);
if (fil.Url() == null) {
fil.Url_(session_dir.GenSubFil("session.txt"));
}
fil.Flush();
}
}
public Io_url Log_dir() {return log_dir;}
public void Log_dir_(Io_url log_dir) {
this.log_dir = log_dir;
session_dir = log_dir.GenSubDir(Datetime_now.Get().XtoStr_fmt_yyyyMMdd_HHmmss_fff());
session_fil = session_dir.GenSubFil("session.txt");
err_fil = session_dir.GenSubFil("err.txt");
}
public void Log_term() {
if (!enabled) return;
Io_url[] archive_dirs = Io_mgr.Instance.QueryDir_args(log_dir).DirInclude_().DirOnly_().ExecAsUrlAry();
int archive_dirs_len = archive_dirs.length;
int session_cutoff = archive_dirs_len - archive_dirs_max;
for (int i = 0; i < session_cutoff; i++) {
Io_url archive_dir = archive_dirs[i];
Io_mgr.Instance.DeleteDirDeep(archive_dir);
this.Log_to_session("archive dir del: " + session_dir.Raw());
}
this.Log_to_session("app term");
}
public void Log_info(boolean warn, String s) {if (warn) Log_to_err(s); else Log_to_session(s);}
public void Log_msg_to_url_fmt(Io_url url, String fmt, Object... args) {
if (!enabled) return;
String msg = Bld_msg(String_.new_u8(fmtr.Fmt_(fmt).Bld_bry_many(tmp_bfr, args)));
Log_msg(url, msg);
Log_msg(session_fil, msg);
}
public void Log_to_session_fmt(String fmt, Object... args) {Log_to_session(String_.new_u8(fmtr.Fmt_(fmt).Bld_bry_many(tmp_bfr, args)));}
public void Log_to_session(String s) {
if (!enabled) return;
String line = Bld_msg(s);
Log_msg(session_fil, line);
}
public void Log_to_session_direct(String s) {
if (!enabled) return;
Log_msg(session_fil, s);
}
public void Log_to_err(String s) {
if (!enabled) return;
try {
String line = Bld_msg(s);
Log_msg(session_fil, line);
Log_msg(err_fil, line);
}
catch (Exception e) {Err_.Noop(e);} // java.lang.StringBuilder can throw exceptions in some situations when called on a different thread; ignore errors
} private String_bldr sb = String_bldr_.new_thread(); // NOTE: use java.lang.StringBuffer to try to avoid random exceptions when called on a different thread
private String Bld_msg(String s) {return sb.Add(Datetime_now.Get_force().XtoUtc().XtoStr_fmt_yyyyMMdd_HHmmss_fff()).Add(" ").Add(s).Add_char_nl().To_str_and_clear();}
private void Log_msg(Io_url url, String txt) {
if (queue_enabled) {
String url_raw = url == null ? "mem" : url.Raw();
Usr_log_fil fil = (Usr_log_fil)queued_list.Get_by(url_raw);
if (fil == null) {
fil = new Usr_log_fil(url);
queued_list.Add(url_raw, fil);
}
fil.Add(txt);
}
else
Io_mgr.Instance.AppendFilStr(url, txt);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
else if (ctx.Match(k, Invk_archive_dirs_max_)) archive_dirs_max = m.ReadInt("v");
else if (ctx.Match(k, Invk_log_dir_)) log_dir = m.ReadIoUrl("v");
else return Gfo_invk_.Rv_unhandled;
return this;
} public static final String Invk_enabled_ = "enabled_", Invk_archive_dirs_max_ = "archive_dirs_max_", Invk_log_dir_ = "log_dir_";
static final String Dir_name_log = "log";
public static final Gfo_usr_dlg__log_base Instance = new Gfo_usr_dlg__log_base();
}
class Usr_log_fil {
public Usr_log_fil(Io_url url) {this.url = url;}
public Io_url Url() {return url;} public Usr_log_fil Url_(Io_url v) {url = v; return this;} Io_url url;
public void Add(String text) {sb.Add(text);} String_bldr sb = String_bldr_.new_();
public void Flush() {
if (sb.Count() == 0) return;
try {
Io_mgr.Instance.AppendFilStr(url, sb.To_str_and_clear());
}
catch (Exception e) {
Console_adp__sys.Instance.Write_str_w_nl(Err_.Message_gplx_full(e));
}
}
}

@ -0,0 +1,64 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.brys.fmtrs.*;
public class Gfo_usr_dlg_base implements Gfo_usr_dlg {
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
private final Bry_fmtr tmp_fmtr = Bry_fmtr.New__tmp().Fail_when_invalid_escapes_(false); // do not fail b/c msgs may contain excerpt of random text; EX:[[User:A|~A~]] DATE:2014-11-28
public Gfo_usr_dlg_base(Gfo_usr_dlg__log log_wkr, Gfo_usr_dlg__gui gui_wkr) {this.log_wkr = log_wkr; this.gui_wkr = gui_wkr;}
public Gfo_usr_dlg__log Log_wkr() {return log_wkr;} public void Log_wkr_(Gfo_usr_dlg__log v) {log_wkr = v;} private Gfo_usr_dlg__log log_wkr;
public Gfo_usr_dlg__gui Gui_wkr() {return gui_wkr;} public void Gui_wkr_(Gfo_usr_dlg__gui v) {gui_wkr = v;} private Gfo_usr_dlg__gui gui_wkr;
public boolean Canceled() {return canceled;} public void Canceled_y_() {canceled = true;} public void Canceled_n_() {canceled = false;} private boolean canceled;
public void Cancel() {canceled = true;}
public String Log_many(String grp_key, String msg_key, String fmt, Object... args) {String rv = Bld_msg_many(grp_key, msg_key, fmt, args ); log_wkr.Log_to_session(rv); return rv;}
public String Warn_many(String grp_key, String msg_key, String fmt, Object... args) {String rv = Bld_msg_many(grp_key, msg_key, fmt, args ); log_wkr.Log_to_err(rv); gui_wkr.Write_warn(rv); return rv;}
public String Prog_many(String grp_key, String msg_key, String fmt, Object... args) {String rv = Bld_msg_many(grp_key, msg_key, fmt, args ); gui_wkr.Write_prog(rv); return rv;}
public String Prog_one(String grp_key, String msg_key, String fmt, Object arg) {String rv = Bld_msg_one (grp_key, msg_key, fmt, arg ); gui_wkr.Write_prog(rv); return rv;}
public String Prog_none(String grp_key, String msg_key, String fmt) {String rv = Bld_msg_none(grp_key, msg_key, fmt ); gui_wkr.Write_prog(rv); return rv;}
public String Prog_direct(String msg) { gui_wkr.Write_prog(msg); return msg;}
public String Log_direct(String msg) { log_wkr.Log_to_session(msg); return msg;}
public String Note_many(String grp_key, String msg_key, String fmt, Object... args) {String rv = Bld_msg_many(grp_key, msg_key, fmt, args ); log_wkr.Log_to_session(rv); gui_wkr.Write_note(rv); return rv;}
public String Note_none(String grp_key, String msg_key, String fmt) {String rv = Bld_msg_none(grp_key, msg_key, fmt ); log_wkr.Log_to_session(rv); gui_wkr.Write_note(rv); return rv;}
public String Note_gui_none(String grp_key, String msg_key, String fmt) {String rv = Bld_msg_none(grp_key, msg_key, fmt ); gui_wkr.Write_note(rv); return rv;}
public String Plog_many(String grp_key, String msg_key, String fmt, Object... args) {
String rv = Log_many(grp_key, msg_key, fmt, args);
return Prog_direct(rv);
}
public Err Fail_many(String grp_key, String msg_key, String fmt, Object... args) {
Err rv = Err_.new_wo_type(Bld_msg_many(grp_key, msg_key, fmt, args));
log_wkr.Log_to_err(rv.To_str__full());
return rv;
}
private String Bld_msg_many(String grp_key, String msg_key, String fmt, Object[] args) {
synchronized (tmp_fmtr) {
try {
tmp_fmtr.Fmt_(fmt).Bld_bfr_many(tmp_bfr, args);
return tmp_bfr.To_str_and_clear();
}
catch (Exception e) { // NOTE: can fail if fmt has ~{}; callers should proactively remove, but for now, just return fmt if fails; EX:Page_sync and en.w:Web_crawler; DATE:2016-11-17
Err_.Noop(e);
return fmt;
}
}
}
private String Bld_msg_one(String grp_key, String msg_key, String fmt, Object val) {
synchronized (tmp_fmtr) {
tmp_fmtr.Fmt_(fmt).Bld_bfr_one(tmp_bfr, val);
return tmp_bfr.To_str_and_clear();
}
}
private String Bld_msg_none(String grp_key, String msg_key, String fmt) {return fmt;}
}

@ -0,0 +1,63 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class GfsCtx {
public Ordered_hash Vars() {return vars;} Ordered_hash vars = Ordered_hash_.New();
public boolean Fail_if_unhandled() {return fail_if_unhandled;} public GfsCtx Fail_if_unhandled_(boolean v) {fail_if_unhandled = v; return this;} private boolean fail_if_unhandled;
public Gfo_usr_dlg Usr_dlg() {return usr_dlg;} public GfsCtx Usr_dlg_(Gfo_usr_dlg v) {usr_dlg = v; return this;} Gfo_usr_dlg usr_dlg;
public boolean Help_browseMode() {return help_browseMode;} public GfsCtx Help_browseMode_(boolean v) {help_browseMode = v; return this;} private boolean help_browseMode;
public List_adp Help_browseList() {return help_browseList;} List_adp help_browseList = List_adp_.New();
public Object MsgSrc() {return msgSrc;} public GfsCtx MsgSrc_(Object v) {msgSrc = v; return this;} Object msgSrc;
public boolean Match(String k, String match) {
if (help_browseMode) {
help_browseList.Add(match);
return false;
}
else
return String_.Eq(k, match);
}
public boolean MatchPriv(String k, String match) {return help_browseMode ? false : String_.Eq(k, match);}
public boolean MatchIn(String k, String... match) {
if (help_browseMode) {
for (String i : match)
help_browseList.Add(i);
return false;
}
return String_.In(k, match);
}
public boolean Write_note(String fmt, Object... ary) {UsrDlg_.Instance.Note(fmt, ary); return false;}
public boolean Write_warn(String fmt, Object... ary) {UsrDlg_.Instance.Note("! " + fmt, ary); return false;}
public boolean Write_stop(UsrMsg umsg) {UsrDlg_.Instance.Note("* " + umsg.To_str()); return false;}
public boolean Write_stop(String fmt, Object... ary) {UsrDlg_.Instance.Note("* " + fmt, ary); return false;}
public boolean Deny() {return deny;} private boolean deny;
public static final GfsCtx Instance = new GfsCtx();
public static GfsCtx new_() {return new GfsCtx();} GfsCtx() {}
public static GfsCtx rdr_() {
GfsCtx rv = new GfsCtx();
rv.deny = true;
rv.mode = "read";
return rv;
}
public static GfsCtx wtr_() {
GfsCtx rv = new GfsCtx();
rv.deny = true;
rv.mode = Mode_write;
return rv;
}
public String Mode() {return mode;} public GfsCtx Mode_(String v) {mode = v; return this;} private String mode = "regular";
public static final String Mode_write = "write";
public static final int Ikey_null = -1;
}

@ -0,0 +1,20 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Guid_adp {
public Guid_adp(java.util.UUID guid) {this.guid = guid;} java.util.UUID guid;
public String To_str() {return guid.toString();}
}

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Guid_adp_ {
public static final String Cls_ref_name = "Guid";
public static final Guid_adp Empty = Parse("00000000-0000-0000-0000-000000000000");
public static String New_str() {return New().To_str();}
public static Guid_adp New() {return new Guid_adp(java.util.UUID.randomUUID());}
public static Guid_adp Parse(String s) {return new Guid_adp(java.util.UUID.fromString(s));}
}

@ -0,0 +1,26 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Guid_adp__tst {
@Test public void parse() {
tst_parse_("467ffb41-cdfe-402f-b22b-be855425784b");
}
void tst_parse_(String s) {
Guid_adp uuid = Guid_adp_.Parse(s);
Tfds.Eq(uuid.To_str(), s);
}
}

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public interface Hash_adp extends gplx.core.lists.EnumerAble {
int Count();
boolean Has(Object key);
Object Get_by(Object key);
Object Get_by_or_fail(Object key);
void Add(Object key, Object val);
Hash_adp Add_and_more(Object key, Object val);
void Add_as_key_and_val(Object val);
boolean Add_if_dupe_use_1st(Object key, Object val);
void Add_if_dupe_use_nth(Object key, Object val);
void Del(Object key);
void Clear();
}

@ -0,0 +1,36 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*;
public class Hash_adp_ {
public static Hash_adp New() {return new Hash_adp_obj();}
public static final Hash_adp Noop = new Hash_adp_noop();
}
class Hash_adp_obj extends gplx.core.lists.Hash_adp_base implements Hash_adp {}//_20110428
class Hash_adp_noop implements Hash_adp {
public int Count() {return 0;}
public boolean Has(Object key) {return false;}
public Object Get_by(Object key) {return null;}
public Object Get_by_or_fail(Object key) {throw Err_.new_missing_key(Object_.Xto_str_strict_or_null_mark(key));}
public void Add(Object key, Object val) {}
public Hash_adp Add_and_more(Object key, Object val) {return this;}
public void Add_as_key_and_val(Object val) {}
public void Add_if_dupe_use_nth(Object key, Object val) {}
public boolean Add_if_dupe_use_1st(Object key, Object val) {return false;}
public void Del(Object key) {}
public void Clear() {}
public java.util.Iterator iterator() {return gplx.core.lists.Iterator_null.Instance;}
}

@ -0,0 +1,205 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*;
import gplx.core.intls.*;
public class Hash_adp_bry extends gplx.core.lists.Hash_adp_base implements Hash_adp {
private final Hash_adp_bry_itm_base proto, key_ref;
Hash_adp_bry(Hash_adp_bry_itm_base proto) {
this.proto = proto;
this.key_ref = proto.New();
}
@Override protected Object Fetch_base(Object key) {synchronized (key_ref) {return super.Fetch_base(key_ref.Init((byte[])key));}} // TS: DATE:2016-07-06
@Override protected void Del_base(Object key) {synchronized (key_ref) {super.Del_base(key_ref.Init((byte[])key));}}// TS: DATE:2016-07-06
@Override protected boolean Has_base(Object key) {synchronized (key_ref) {return super.Has_base(key_ref.Init((byte[])key));}}// TS: DATE:2016-07-06
public int Get_as_int(byte[] key) {return Get_as_int(key, 0, key.length);}
public int Get_as_int(byte[] key, int bgn, int end) {
int rv = Get_as_int_or(key, bgn, end, Int_.Min_value); if (rv == Int_.Min_value) throw Err_.new_("core", "unknown key", "key", key);
return rv;
}
public int Get_as_int_or(byte[] key, int or) {return Get_as_int_or(key, 0, key.length, or);}
public int Get_as_int_or(byte[] key, int bgn, int end, int or) {
Object o = Get_by_mid(key, bgn, end);
return (o == null) ? or : ((Int_obj_val)o).Val();
}
public byte Get_as_byte_or(byte[] key, byte or) {return Get_as_byte_or(key, 0, key.length, or);}
public byte Get_as_byte_or(byte[] key, int bgn, int end, byte or) {
Object o = Get_by_mid(key, bgn, end);
return o == null ? or : ((Byte_obj_val)o).Val();
}
public Object Get_by_bry(byte[] src) {synchronized (key_ref) {return super.Fetch_base(key_ref.Init(src));}} // TS: DATE:2016-07-06
public Object Get_by_mid(byte[] src, int bgn, int end) {synchronized (key_ref) {return super.Fetch_base(key_ref.Init(src, bgn, end));}}// TS: DATE:2016-07-06
public Hash_adp_bry Add_byte_int(byte key, int val) {this.Add_base(new byte[]{key}, new Int_obj_val(val)); return this;}
public Hash_adp_bry Add_bry_byte(byte[] key, byte val) {this.Add_base(key, Byte_obj_val.new_(val)); return this;}
public Hash_adp_bry Add_bry_int(byte[] key, int val) {this.Add_base(key, new Int_obj_val(val)); return this;}
public Hash_adp_bry Add_bry_bry(byte[] key) {this.Add_base(key, key); return this;}
public Hash_adp_bry Add_str_byte(String key, byte val) {this.Add_base(Bry_.new_u8(key), Byte_obj_val.new_(val)); return this;}
public Hash_adp_bry Add_str_int(String key, int val) {this.Add_base(Bry_.new_u8(key), new Int_obj_val(val)); return this;}
public Hash_adp_bry Add_str_obj(String key, Object val) {this.Add_base(Bry_.new_u8(key), val); return this;}
public Hash_adp_bry Add_bry_obj(byte[] key, Object val) {this.Add_base(key, val); return this;}
public Hash_adp_bry Add_many_str(String... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
String itm = ary[i];
byte[] bry = Bry_.new_u8(itm);
Add_bry_bry(bry);
}
return this;
}
public Hash_adp_bry Add_many_bry(byte[]... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++)
Add_bry_bry(ary[i]);
return this;
}
@Override protected void Add_base(Object key, Object val) {
byte[] key_bry = (byte[])key;
Hash_adp_bry_itm_base key_itm = proto.New();
key_itm.Init(key_bry, 0, key_bry.length);
super.Add_base(key_itm, val);
}
public static Hash_adp_bry cs() {return new Hash_adp_bry(Hash_adp_bry_itm_cs.Instance);}
public static Hash_adp_bry ci_a7() {return new Hash_adp_bry(Hash_adp_bry_itm_ci_a7.Instance);}
public static Hash_adp_bry ci_u8(Gfo_case_mgr case_mgr) {return new Hash_adp_bry(Hash_adp_bry_itm_ci_u8.get_or_new(case_mgr));}
public static Hash_adp_bry c__u8(boolean case_match, Gfo_case_mgr case_mgr) {return case_match ? cs() : ci_u8(case_mgr);}
}
abstract class Hash_adp_bry_itm_base {
public abstract Hash_adp_bry_itm_base New();
public Hash_adp_bry_itm_base Init(byte[] src) {return this.Init(src, 0, src.length);}
public abstract Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end);
}
class Hash_adp_bry_itm_cs extends Hash_adp_bry_itm_base {
private byte[] src; int src_bgn, src_end;
@Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_cs();}
@Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;}
@Override public int hashCode() {
int rv = 0;
for (int i = src_bgn; i < src_end; i++) {
int b_int = src[i] & 0xFF; // JAVA: patch
rv = (31 * rv) + b_int;
}
return rv;
}
@Override public boolean equals(Object obj) {
if (obj == null) return false;
Hash_adp_bry_itm_cs comp = (Hash_adp_bry_itm_cs)obj;
byte[] comp_src = comp.src; int comp_bgn = comp.src_bgn, comp_end = comp.src_end;
int comp_len = comp_end - comp_bgn, src_len = src_end - src_bgn;
if (comp_len != src_len) return false;
for (int i = 0; i < comp_len; i++) {
int src_pos = src_bgn + i;
if (src_pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
if (src[src_pos] != comp_src[i + comp_bgn]) return false;
}
return true;
}
public static final Hash_adp_bry_itm_cs Instance = new Hash_adp_bry_itm_cs(); Hash_adp_bry_itm_cs() {}
}
class Hash_adp_bry_itm_ci_a7 extends Hash_adp_bry_itm_base {
private byte[] src; int src_bgn, src_end;
@Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_ci_a7();}
@Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;}
@Override public int hashCode() {
int rv = 0;
for (int i = src_bgn; i < src_end; i++) {
int b_int = src[i] & 0xFF; // JAVA: patch
if (b_int > 64 && b_int < 91) // 64=before A; 91=after Z; NOTE: lowering upper-case on PERF assumption that there will be more lower-case letters than upper-case
b_int += 32;
rv = (31 * rv) + b_int;
}
return rv;
}
@Override public boolean equals(Object obj) {
if (obj == null) return false;
Hash_adp_bry_itm_ci_a7 comp = (Hash_adp_bry_itm_ci_a7)obj;
byte[] comp_src = comp.src; int comp_bgn = comp.src_bgn, comp_end = comp.src_end;
int comp_len = comp_end - comp_bgn, src_len = src_end - src_bgn;
if (comp_len != src_len) return false;
for (int i = 0; i < comp_len; i++) {
int src_pos = src_bgn + i;
if (src_pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
byte src_byte = src[src_pos];
if (src_byte > 64 && src_byte < 91) src_byte += 32;
byte comp_byte = comp_src[i + comp_bgn];
if (comp_byte > 64 && comp_byte < 91) comp_byte += 32;
if (src_byte != comp_byte) return false;
}
return true;
}
public static final Hash_adp_bry_itm_ci_a7 Instance = new Hash_adp_bry_itm_ci_a7(); Hash_adp_bry_itm_ci_a7() {}
}
class Hash_adp_bry_itm_ci_u8 extends Hash_adp_bry_itm_base {
private final Gfo_case_mgr case_mgr;
Hash_adp_bry_itm_ci_u8(Gfo_case_mgr case_mgr) {this.case_mgr = case_mgr;}
private byte[] src; int src_bgn, src_end;
@Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_ci_u8(case_mgr);}
@Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;}
@Override public int hashCode() {
int rv = 0;
for (int i = src_bgn; i < src_end; i++) {
byte b = src[i];
int b_int = b & 0xFF; // JAVA: patch
Gfo_case_itm itm = case_mgr.Get_or_null(b, src, i, src_end);
if (itm == null) { // unknown itm; byte is a number, symbol, or unknown; just use the existing byte
}
else { // known itm; use its hash_code
b_int = itm.Hashcode_lo();
int b_len = Utf8_.Len_of_char_by_1st_byte(b); // NOTE: must calc b_len for langs with asymmetric upper / lower; PAGE:tr.w:Zvishavane DATE:2015-09-07
i += b_len - 1;
}
rv = (31 * rv) + b_int;
}
return rv;
}
@Override public boolean equals(Object obj) {
if (obj == null) return false;
Hash_adp_bry_itm_ci_u8 trg_itm = (Hash_adp_bry_itm_ci_u8)obj;
byte[] trg = trg_itm.src; int trg_bgn = trg_itm.src_bgn, trg_end = trg_itm.src_end;
int src_c_bgn = src_bgn;
int trg_c_bgn = trg_bgn;
while ( src_c_bgn < src_end
&& trg_c_bgn < trg_end) { // exit once one goes out of bounds
byte src_c = src[src_c_bgn];
byte trg_c = trg[trg_c_bgn];
int src_c_len = Utf8_.Len_of_char_by_1st_byte(src_c);
int trg_c_len = Utf8_.Len_of_char_by_1st_byte(trg_c);
int src_c_end = src_c_bgn + src_c_len;
int trg_c_end = trg_c_bgn + trg_c_len;
Gfo_case_itm src_c_itm = case_mgr.Get_or_null(src_c, src, src_c_bgn, src_c_end);
Gfo_case_itm trg_c_itm = case_mgr.Get_or_null(trg_c, trg, trg_c_bgn, trg_c_end);
if (src_c_itm != null && trg_c_itm == null) return false; // src == ltr; trg != ltr; EX: a, 1
else if (src_c_itm == null && trg_c_itm != null) return false; // src != ltr; trg == ltr; EX: 1, a
else if (src_c_itm == null && trg_c_itm == null) { // src != ltr; trg != ltr; EX: 1, 2; _, Ⓐ
if (!Bry_.Match(src, src_c_bgn, src_c_end, trg, trg_c_bgn, trg_c_end)) return false;// syms do not match; return false;
}
else {
if (src_c_itm.Utf8_id_lo() != trg_c_itm.Utf8_id_lo()) return false; // lower-case utf8-ids don't match; return false; NOTE: using utf8-ids instead of hash-code to handle asymmetric brys; DATE:2015-09-07
}
src_c_bgn = src_c_end;
trg_c_bgn = trg_c_end;
}
return src_c_bgn == src_end && trg_c_bgn == trg_end; // only return true if both src and trg read to end of their brys, otherwise "a","ab" will match
}
public static Hash_adp_bry_itm_ci_u8 get_or_new(Gfo_case_mgr case_mgr) {
switch (case_mgr.Tid()) {
case Gfo_case_mgr_.Tid_a7: if (Itm_a7 == null) Itm_a7 = new Hash_adp_bry_itm_ci_u8(case_mgr); return Itm_a7;
case Gfo_case_mgr_.Tid_u8: if (Itm_u8 == null) Itm_u8 = new Hash_adp_bry_itm_ci_u8(case_mgr); return Itm_u8;
case Gfo_case_mgr_.Tid_custom: return new Hash_adp_bry_itm_ci_u8(case_mgr);
default: throw Err_.new_unhandled(case_mgr.Tid());
}
}
private static Hash_adp_bry_itm_ci_u8 Itm_a7, Itm_u8;
}

@ -0,0 +1,66 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Hash_adp_bry_tst {
@Before public void setup() {fxt.Clear();} private Hash_adp_bry_fxt fxt = new Hash_adp_bry_fxt();
@Test public void Add_bry() {
fxt .New_cs()
.Add("a0").Add("b0").Add("c0")
.Get_bry_tst("a0").Get_bry_tst("b0").Get_bry_tst("c0").Get_bry_tst("A0", null)
;
}
@Test public void Get_mid() {
fxt .New_cs()
.Add("a0").Add("b0").Add("c0")
.Get_mid_tst("xyza0xyz", 3, 5, "a0")
.Get_mid_tst("xyza0xyz", 3, 4, null)
;
}
@Test public void Case_insensitive() {
fxt .New_ci()
.Add("a0").Add("B0").Add("c0")
.Get_bry_tst("a0", "a0")
.Get_bry_tst("A0", "a0")
.Get_bry_tst("b0", "B0")
.Get_bry_tst("B0", "B0")
.Get_mid_tst("xyza0xyz", 3, 5, "a0")
.Get_mid_tst("xyzA0xyz", 3, 5, "a0")
.Count_tst(3)
;
}
}
class Hash_adp_bry_fxt {
Hash_adp_bry hash;
public void Clear() {}
public Hash_adp_bry_fxt New_cs() {hash = Hash_adp_bry.cs(); return this;}
public Hash_adp_bry_fxt New_ci() {hash = Hash_adp_bry.ci_a7(); return this;}
public Hash_adp_bry_fxt Add(String key) {byte[] key_bry = Bry_.new_u8(key); hash.Add(key_bry, key_bry); return this;}
public Hash_adp_bry_fxt Count_tst(int expd) {Tfds.Eq(expd, hash.Count()); return this;}
public Hash_adp_bry_fxt Get_bry_tst(String key) {return Get_bry_tst(key, key);}
public Hash_adp_bry_fxt Get_bry_tst(String key, String expd) {
byte[] key_bry = Bry_.new_u8(key);
byte[] actl_bry = (byte[])hash.Get_by_bry(key_bry);
Tfds.Eq(expd, String_.new_u8(actl_bry));
return this;
}
public Hash_adp_bry_fxt Get_mid_tst(String key, int bgn, int end, String expd) {
byte[] key_bry = Bry_.new_u8(key);
byte[] actl_bry = (byte[])hash.Get_by_mid(key_bry, bgn, end);
Tfds.Eq(expd, String_.new_u8(actl_bry));
return this;
}
}

@ -0,0 +1,220 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*; import gplx.langs.gfs.*;
public class Int_ {
public static final String Cls_val_name = "int";
public static final Class<?> Cls_ref_type = Integer.class;
public static final int
Min_value = Integer.MIN_VALUE
, Max_value = Integer.MAX_VALUE
, Max_value__31 = 2147483647
, Neg1 = -1
, Null = Int_.Min_value
, Base1 = 1 // for super 1 lists / arrays; EX: PHP; [a, b, c]; [1] => a
, Offset_1 = 1 // common symbol for + 1 after current pos; EX: String_.Mid(lhs + Offset_1, rhs)
;
public static int Cast(Object obj) {
try {
return (Integer)obj;
}
catch(Exception exc) {
throw Err_.new_type_mismatch_w_exc(exc, int.class, obj);
}
}
public static int Cast_or(Object obj, int or) {
try {
return (Integer)obj;
}
catch(Exception e) {
Err_.Noop(e);
return or;
}
}
public static int Coerce(Object v) {
try {
String s = String_.as_(v);
return s == null ? Int_.Cast(v) : Int_.Parse(s);
}
catch (Exception e) {throw Err_.new_cast(e, int.class, v);}
}
public static int Parse(String raw) {try {return Integer.parseInt(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, int.class, raw);}}
public static int Parse_or(String raw, int or) {
if (raw == null) return or;
int rawLen = String_.Len(raw); if (rawLen == 0) return or;
int rv = 0, tmp = 0, factor = 1;
for (int i = rawLen; i > 0; i--) {
char c = String_.CharAt(raw, i - 1);
switch (c) {
case '0': tmp = 0; break; case '1': tmp = 1; break; case '2': tmp = 2; break; case '3': tmp = 3; break; case '4': tmp = 4; break;
case '5': tmp = 5; break; case '6': tmp = 6; break; case '7': tmp = 7; break; case '8': tmp = 8; break; case '9': tmp = 9; break;
case '-': rv *= -1; continue; // NOTE: note continue
default: return or;
}
rv += (tmp * factor);
factor *= 10;
}
return rv;
}
public static int By_double(double v) {return (int)v;}
public static int By_hex_bry(byte[] src) {return By_hex_bry(src, 0, src.length);}
public static int By_hex_bry(byte[] src, int bgn, int end) {
int rv = 0; int factor = 1;
for (int i = end - 1; i >= bgn; i--) {
int val = By_hex_byte(src[i]);
rv += (val * factor);
factor *= 16;
}
return rv;
}
public static int By_hex_byte(byte b) {
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
return b - Byte_ascii.Num_0;
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E: case Byte_ascii.Ltr_F:
return b - Byte_ascii.Ltr_A + 10;
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e: case Byte_ascii.Ltr_f:
return b - Byte_ascii.Ltr_a + 10;
default:
return -1;
}
}
public static byte[] To_bry(int v) {return Bry_.new_a7(To_str(v));}
public static String To_str(int v) {return new Integer(v).toString();}
public static String To_str_fmt(int v, String fmt) {return new java.text.DecimalFormat(fmt).format(v);}
public static String To_str_pad_bgn_space(int val, int reqd_len) {return To_str_pad(val, reqd_len, Bool_.Y, Byte_ascii.Space);} // EX: 1, 3 returns " 1"
public static String To_str_pad_bgn_zero (int val, int reqd_len) {return To_str_pad(val, reqd_len, Bool_.Y, Byte_ascii.Num_0);} // EX: 1, 3 returns "001"
private static String To_str_pad(int val, int reqd_len, boolean bgn, byte pad_chr) {
// get val_len and pad_len; exit early, if no padding needed
int val_len = DigitCount(val);
int pad_len = reqd_len - val_len;
if (pad_len < 0)
return Int_.To_str(val);
// padding needed
Bry_bfr bfr = Bry_bfr_.New();
// handle negative numbers; EX: -1 -> "-001", not "00-1"
if (val < 0) {
bfr.Add_byte(Byte_ascii.Dash);
val *= -1;
--val_len;
}
// build outpt
if (!bgn)
bfr.Add_int_fixed(val, val_len);
bfr.Add_byte_repeat(pad_chr, pad_len);
if (bgn)
bfr.Add_int_fixed(val, val_len);
return bfr.To_str();
}
public static String To_str_hex(int v) {return To_str_hex(Bool_.Y, Bool_.Y, v);}
public static String To_str_hex(boolean zero_pad, boolean upper, int v) {
String rv = Integer.toHexString(v);
int rv_len = String_.Len(rv);
if (zero_pad && rv_len < 8) rv = String_.Repeat("0", 8 - rv_len) + rv;
return upper ? String_.Upper(rv) : rv;
}
public static int Compare(int lhs, int rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
public static boolean In(int v, int comp0, int comp1) {return v == comp0 || v == comp1;}
public static boolean In(int v, int... ary) {
for (int itm : ary)
if (v == itm) return true;
return false;
}
public static boolean Between(int v, int lhs, int rhs) {
int lhsCompare = v == lhs ? 0 : (v < lhs ? -1 : 1);
int rhsCompare = v == rhs ? 0 : (v < rhs ? -1 : 1);
return (lhsCompare * rhsCompare) != 1; // 1 when v is (a) greater than both or (b) less than both
}
public static boolean RangeCheck(int v, int max) {return v >= 0 && v < max;}
public static void RangeCheckOrFail_list(int v, int max, String s) {if (v < 0 || v >= max) throw Err_.new_wo_type("bounds check failed", "msg", s, "v", v, "min", 0, "max", max - 1);}
public static boolean Bounds_chk(int bgn, int end, int len) {return bgn > -1 && end < len;}
public static int BoundEnd(int v, int end) {return v >= end ? end - 1 : v;}
public static int EnsureLessThan(int v, int max) {return v >= max ? max : v;}
public static int Min(int lhs, int rhs) {return lhs < rhs ? lhs : rhs;}
public static int Max(int lhs, int rhs) {return lhs > rhs ? lhs : rhs;}
public static int Min_many(int... ary) {
int len = ary.length; if (len == 0) throw Err_.new_wo_type("Min_many requires at least 1 value");
boolean init = true;
int min = Int_.Min_value;
for (int i = 0; i < len; ++i) {
int val = ary[i];
if (init) {
min = val;
init = false;
}
else {
if (val < min)
min = val;
}
}
return min;
}
public static int Subtract_long(long lhs, long rhs) {return (int)(lhs - rhs);}
public static int Div(int v, float divisor) {return (int)((float)v / divisor);}
public static int DivAndRoundUp(int v, int divisor) {
int whole = v / divisor;
int partial = v % divisor == 0 ? 0 : 1;
return whole + partial;
}
public static int Mult(int v, float multiplier) {
float product = ((float)v * multiplier); // WORKAROUND (DotNet): (int)((float)v * multiplier) returns 0 for 100 and .01f
return (int)product;
}
public static int[] Log10Ary = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, Int_.Max_value};
public static int Log10AryLen = 11;
public static int Log10(int v) {
if (v == 0) return 0;
int sign = 1;
if (v < 0) {
if (v == Int_.Min_value) return -9; // NOTE: Int_.Min_value * -1 = Int_.Min_value
v *= -1;
sign = -1;
}
int rv = Log10AryLen - 2; // rv will only happen when v == Int_.Max_value
int bgn = 0;
if (v > 1000) { // optimization to reduce number of ops to < 5
bgn = 3;
if (v > 1000000) bgn = 6;
}
for (int i = bgn; i < Log10AryLen; i++) {
if (v < Log10Ary[i]) {rv = i - 1; break;}
}
return rv * sign;
}
public static int DigitCount(int v) {
int log10 = Log10(v);
return v > -1 ? log10 + 1 : log10 * -1 + 2;
}
}

@ -0,0 +1,97 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Int__tst {
@Test public void XtoStr_PadBgn() {
tst_XtoStr_PadLeft_Zeroes(1 , 3, "001"); // pad
tst_XtoStr_PadLeft_Zeroes(123 , 3, "123"); // no pad
tst_XtoStr_PadLeft_Zeroes(1234 , 3, "1234"); // val exceeds pad; confirm noop
tst_XtoStr_PadLeft_Zeroes(-1 , 3, "-01"); // negative
tst_XtoStr_PadLeft_Zeroes(-12 , 3, "-12"); // negative
tst_XtoStr_PadLeft_Zeroes(-123 , 3, "-123"); // negative
tst_XtoStr_PadLeft_Zeroes(-1234 , 3, "-1234"); // negative
} void tst_XtoStr_PadLeft_Zeroes(int val, int zeros, String expd) {Tfds.Eq(expd, Int_.To_str_pad_bgn_zero(val, zeros));}
@Test public void parseOr_() {
tst_ParseOr("", -1); // empty
tst_ParseOr("123", 123); // single
tst_ParseOr("1a", -1); // fail
} void tst_ParseOr(String raw, int expd) {Tfds.Eq(expd, Int_.Parse_or(raw, -1));}
@Test public void Between() {
tst_Between(1, 0, 2, true); // simple true
tst_Between(3, 0, 2, false); // simple false
tst_Between(0, 0, 2, true); // bgn true
tst_Between(2, 0, 2, true); // end true
} void tst_Between(int val, int lhs, int rhs, boolean expd) {Tfds.Eq(expd, Int_.Between(val, lhs, rhs));}
@Test public void Xto_fmt() {
tst_XtoStr_fmt(1, "1");
tst_XtoStr_fmt(1000, "1,000");
} void tst_XtoStr_fmt(int v, String expd) {Tfds.Eq(expd, Int_.To_str_fmt(v, "#,###"));}
@Test public void Log10_pos() {
tst_Log10(0, 0);
tst_Log10(1, 0);
tst_Log10(9, 0);
tst_Log10(10, 1);
tst_Log10(100, 2);
tst_Log10(1000000, 6);
tst_Log10(1000000000, 9);
tst_Log10(Int_.Max_value, 9);
}
@Test public void Log10_neg() {
tst_Log10(-1, 0);
tst_Log10(-10, -1);
tst_Log10(-100, -2);
tst_Log10(-1000000, -6);
tst_Log10(-1000000000, -9);
tst_Log10(Int_.Min_value, -9);
tst_Log10(Int_.Min_value + 1, -9);
}
void tst_Log10(int val, int expd) {Tfds.Eq(expd, Int_.Log10(val));}
@Test public void DigitCount() {
tst_DigitCount(0, 1);
tst_DigitCount(9, 1);
tst_DigitCount(100, 3);
tst_DigitCount(-1, 2);
tst_DigitCount(-100, 4);
} void tst_DigitCount(int val, int expd) {Tfds.Eq(expd, Int_.DigitCount(val), Int_.To_str(val));}
@Test public void Log10() {
tst_Log10( 0, 0);
tst_Log10( 1, 0);
tst_Log10( 2, 0);
tst_Log10( 10, 1);
tst_Log10( 12, 1);
tst_Log10( 100, 2);
tst_Log10( 123, 2);
tst_Log10( 1000, 3);
tst_Log10( 1234, 3);
tst_Log10( 10000, 4);
tst_Log10( 12345, 4);
tst_Log10( 100000, 5);
tst_Log10( 123456, 5);
tst_Log10( 1000000, 6);
tst_Log10( 1234567, 6);
tst_Log10( 10000000, 7);
tst_Log10( 12345678, 7);
tst_Log10( 100000000, 8);
tst_Log10( 123456789, 8);
tst_Log10( 1000000000, 9);
tst_Log10( 1234567890, 9);
tst_Log10(Int_.Max_value, 9);
}
@Test public void Xto_int_hex_tst() {
Xto_int_hex("007C", 124);
} void Xto_int_hex(String raw, int expd) {Tfds.Eq(expd, Int_.By_hex_bry(Bry_.new_a7(raw)));}
}

@ -0,0 +1,163 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*;
public class Int_ary_ {//RF:DATE:2017-10-09
public static int[] Empty = new int[0];
public static int[] New(int... v) {return v;}
public static void Copy_to(int[] src, int src_len, int[] trg) {
for (int i = 0; i < src_len; ++i)
trg[i] = src[i];
}
public static String To_str(String spr, int... ary) {
Bry_bfr bfr = Bry_bfr_.New();
int len = ary.length;
for (int i = 0; i < len; ++i) {
if (i != 0) bfr.Add_str_u8(spr);
int itm = ary[i];
bfr.Add_int_variable(itm);
}
return bfr.To_str_and_clear();
}
public static int[] Parse(String raw, String spr) {
String[] ary = String_.Split(raw, spr);
int len = ary.length;
int[] rv = new int[len];
for (int i = 0; i < len; i++)
rv[i] = Int_.Parse(ary[i]);
return rv;
}
// parses to a reqd len; EX: "1" -> "[1, 0]"
public static int[] Parse(String raw_str, int reqd_len, int[] or) {
byte[] raw_bry = Bry_.new_a7(raw_str);
int raw_bry_len = raw_bry.length;
int[] rv = new int[reqd_len];
int cur_val = 0, cur_mult = 1, cur_idx = reqd_len - 1; boolean signed = false;
for (int i = raw_bry_len - 1; i > -2; i--) {
byte b = i == -1 ? Byte_ascii.Comma : raw_bry[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
if (signed) return or;
cur_val += (b - Byte_ascii.Num_0) * cur_mult;
cur_mult *= 10;
break;
case Byte_ascii.Space: case Byte_ascii.Nl: case Byte_ascii.Cr: case Byte_ascii.Tab:
break;
case Byte_ascii.Comma:
if (cur_idx < 0) return or;
rv[cur_idx--] = cur_val;
cur_val = 0; cur_mult = 1;
signed = false;
break;
case Byte_ascii.Dash:
if (signed) return or;
cur_val *= -1;
signed = true;
break;
case Byte_ascii.Plus: // noop; all values positive by default
if (signed) return or;
signed = true;
break;
default:
return or;
}
}
return cur_idx == -1 ? rv : or; // cur_idx == -1 checks for unfilled; EX: Ary_parse("1,2", 3, null) is unfilled
}
// optimizes parse
public static int[] Parse_or(byte[] src, int[] or) {
try {
if (Bry_.Len_eq_0(src)) return or; // null, "" should return [0]
int raw_len = src.length;
int[] rv = null; int rv_idx = 0, rv_len = 0;
int pos = 0;
int num_bgn = -1, num_end = -1;
boolean itm_done = false, itm_is_rng = false;
int rng_bgn = Int_.Min_value;
while (true) {
boolean pos_is_last = pos == raw_len;
if ( itm_done
|| pos_is_last
) {
if (num_bgn == -1) return or; // empty itm; EX: "1,"; "1,,2"
int num = Bry_.To_int_or(src, num_bgn, num_end, Int_.Min_value);
if (num == Int_.Min_value) return or; // not a number; parse failed
if (rv_len == 0) { // rv not init'd
rv_len = (raw_len / 2) + 1; // default rv_len to len of String / 2; + 1 to avoid fraction rounding down
rv = new int[rv_len];
}
int add_len = 1;
if (itm_is_rng) {
add_len = num - rng_bgn + List_adp_.Base1;
if (add_len == 0) return or; // bgn >= end;
}
if (add_len + rv_idx > rv_len) { // ary out of space; resize
rv_len = (add_len + rv_idx) * 2;
rv = (int[])Array_.Resize(rv, rv_len);
}
if (itm_is_rng) {
for (int i = rng_bgn; i <= num; i++)
rv[rv_idx++] = i;
}
else {
rv[rv_idx++] = num;
}
num_bgn = num_end = -1;
itm_done = itm_is_rng = false;
rng_bgn = Int_.Min_value;
if (pos_is_last) break;
}
byte b = src[pos];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
if (num_bgn == -1) // num_bgn not set
num_bgn = pos;
num_end = pos + 1; // num_end is always after pos; EX: "9": num_end = 1; "98,7": num_end=2
break;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: // NOTE: parseNumList replaces ws with '', so "1 1" will become "11"
break;
case Byte_ascii.Comma:
if (pos == raw_len -1) return or; // eos; EX: "1,"
if (num_bgn == -1) return or; // empty itm; EX: ","; "1,,2"
itm_done = true;
break;
case Byte_ascii.Dash:
if (pos == raw_len -1) return or; // eos; EX: "1-"
if (num_bgn == -1) return or; // no rng_bgn; EX: "-2"
rng_bgn = Bry_.To_int_or(src, num_bgn, pos, Int_.Min_value);
if (rng_bgn == Int_.Min_value) return or;
num_bgn = -1;
itm_is_rng = true;
break;
default:
return or;
}
++pos;
}
return (rv_idx == rv_len) // on the off-chance that rv_len == rv_idx; EX: "1"
? rv
: (int[])Array_.Resize(rv, rv_idx);
} catch (Exception e) {Err_.Noop(e); return or;}
}
}

@ -0,0 +1,58 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*;
public class Int_ary__tst {
private Int_ary__fxt fxt = new Int_ary__fxt();
@Test public void Parse() {
fxt.Test__Parse("1,2,3" , 3, Int_ary_.Empty, 1, 2, 3);
fxt.Test__Parse("123,321,213" , 3, Int_ary_.Empty, 123, 321, 213);
fxt.Test__Parse(" 1, 2,3" , 3, Int_ary_.Empty, 1, 2, 3);
fxt.Test__Parse("-1,+2,-3" , 3, Int_ary_.Empty, -1, 2, -3);
fxt.Test__Parse(Int_.To_str(Int_.Min_value) , 1, Int_ary_.Empty, Int_.Min_value);
fxt.Test__Parse(Int_.To_str(Int_.Max_value) , 1, Int_ary_.Empty, Int_.Max_value);
fxt.Test__Parse("1,2" , 1, Int_ary_.Empty);
fxt.Test__Parse("1" , 2, Int_ary_.Empty);
fxt.Test__Parse("a" , 1, Int_ary_.Empty);
fxt.Test__Parse("1-2," , 1, Int_ary_.Empty);
}
@Test public void Parse_list_or_() {
fxt.Test__Parse_or("1", 1);
fxt.Test__Parse_or("123", 123);
fxt.Test__Parse_or("1,2,123", 1, 2, 123);
fxt.Test__Parse_or("1,2,12,123", 1, 2, 12, 123);
fxt.Test__Parse_or("1-5", 1, 2, 3, 4, 5);
fxt.Test__Parse_or("1-1", 1);
fxt.Test__Parse_or("1-3,7,11-13,21", 1, 2, 3, 7, 11, 12, 13, 21);
fxt.Test__Parse_or__empty("1 2"); // NOTE: MW would gen 12; treat as invalid
fxt.Test__Parse_or__empty("1,"); // eos
fxt.Test__Parse_or__empty("1,,2"); // empty comma
fxt.Test__Parse_or__empty("1-"); // eos
fxt.Test__Parse_or__empty("3-1"); // bgn > end
fxt.Test__Parse_or__empty("1,a,2");
fxt.Test__Parse_or__empty("a-1,2");
fxt.Test__Parse_or__empty("-1"); // no rng bgn
}
}
class Int_ary__fxt {
public void Test__Parse_or__empty(String raw) {Tfds.Eq_ary(Int_ary_.Empty, Int_ary_.Parse_or(Bry_.new_a7(raw), Int_ary_.Empty));}
public void Test__Parse_or(String raw, int... expd) {Tfds.Eq_ary(expd, Int_ary_.Parse_or(Bry_.new_a7(raw), Int_ary_.Empty));}
public void Test__Parse(String raw, int reqd_len, int[] or, int... expd) {Gftest.Eq__ary(expd, Int_ary_.Parse(raw, reqd_len, or), "failed to parse: {0}", raw);}
}

@ -0,0 +1,17 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public @interface Internal {}

@ -0,0 +1,176 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.primitives.*; import gplx.core.ios.*; /*IoItmFil, IoItmDir..*/ import gplx.core.ios.streams.*; import gplx.core.ios.loaders.*;
public class Io_mgr implements Gfo_evt_mgr_owner { // exists primarily to gather all cmds under gplx namespace; otherwise need to use gplx.core.ios whenever copying/deleting file
public Io_mgr() {evt_mgr = new Gfo_evt_mgr(this);}
public Gfo_evt_mgr Evt_mgr() {return evt_mgr;} private final Gfo_evt_mgr evt_mgr;
public boolean Exists(Io_url url) {return url.Type_dir() ? ExistsDir(url) : ExistsFil(url);}
public boolean ExistsFil(Io_url url) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).ExistsFil_api(url);}
public void ExistsFilOrFail(Io_url url) {if (!ExistsFil(url)) throw Err_.new_wo_type("could not find file", "url", url);}
public void SaveFilStr(String url, String text) {SaveFilStr_args(Io_url_.new_fil_(url), text).Exec();}
public void SaveFilStr(Io_url url, String text) {SaveFilStr_args(url, text).Exec();}
public IoEngine_xrg_saveFilStr SaveFilStr_args(Io_url url, String text) {return IoEngine_xrg_saveFilStr.new_(url, text);}
public void AppendFilStr(String url, String text) {AppendFilStr(Io_url_.new_fil_(url), text);}
public void AppendFilStr(Io_url url, String text) {SaveFilStr_args(url, text).Append_(true).Exec();}
public void DeleteFil(Io_url url) {DeleteFil_args(url).Exec();}
public IoEngine_xrg_deleteFil DeleteFil_args(Io_url url) {return IoEngine_xrg_deleteFil.new_(url);}
public void MoveFil(Io_url src, Io_url trg) {IoEngine_xrg_xferFil.move_(src, trg).Exec();}
public IoEngine_xrg_xferFil MoveFil_args(Io_url src, Io_url trg, boolean overwrite) {return IoEngine_xrg_xferFil.move_(src, trg).Overwrite_(overwrite);}
public void CopyFil(Io_url src, Io_url trg, boolean overwrite) {IoEngine_xrg_xferFil.copy_(src, trg).Overwrite_(overwrite).Exec();}
public IoEngine_xrg_xferFil CopyFil_args(Io_url src, Io_url trg, boolean overwrite) {return IoEngine_xrg_xferFil.copy_(src, trg).Overwrite_(overwrite);}
public IoRecycleBin RecycleBin() {return recycleBin;} private IoRecycleBin recycleBin = IoRecycleBin.Instance;
public Io_loader Loader() {return loader;} public void Loader_(Io_loader v) {this.loader = v;} private Io_loader loader;
public IoStream OpenStreamWrite(Io_url url) {return OpenStreamWrite_args(url).Exec();}
public IoEngine_xrg_openWrite OpenStreamWrite_args(Io_url url) {return IoEngine_xrg_openWrite.new_(url);}
public IoItmFil QueryFil(Io_url url) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).QueryFil(url);}
public void UpdateFilAttrib(Io_url url, IoItmAttrib attrib) {IoEnginePool.Instance.Get_by(url.Info().EngineKey()).UpdateFilAttrib(url, attrib);}
public void UpdateFilModifiedTime(Io_url url, DateAdp modified) {IoEnginePool.Instance.Get_by(url.Info().EngineKey()).UpdateFilModifiedTime(url, modified);}
public boolean ExistsDir(Io_url url) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).ExistsDir(url);}
public void CreateDir(Io_url url) {IoEnginePool.Instance.Get_by(url.Info().EngineKey()).CreateDir(url);}
public boolean CreateDirIfAbsent(Io_url url) {
boolean exists = ExistsDir(url);
if (!exists) {
CreateDir(url);
return true;
}
return false;
}
public void Create_fil_ary(Io_fil[] fil_ary) {
for (Io_fil fil : fil_ary)
SaveFilStr(fil.Url(), fil.Data());
}
public Io_url[] QueryDir_fils(Io_url dir) {return QueryDir_args(dir).ExecAsUrlAry();}
public IoEngine_xrg_queryDir QueryDir_args(Io_url dir) {return IoEngine_xrg_queryDir.new_(dir);}
public void DeleteDirSubs(Io_url url) {IoEngine_xrg_deleteDir.new_(url).Exec();}
public IoEngine_xrg_deleteDir DeleteDir_cmd(Io_url url) {return IoEngine_xrg_deleteDir.new_(url);}
public void DeleteDirDeep(Io_url url) {IoEngine_xrg_deleteDir.new_(url).Recur_().Exec();}
public void DeleteDirDeep_ary(Io_url... urls) {for (Io_url url : urls) IoEngine_xrg_deleteDir.new_(url).Recur_().Exec();}
public int Delete_dir_empty(Io_url url) {return Io_mgr_.Delete_dir_empty(url);}
public void Delete_sub_by_wildcard() {
}
public boolean Truncate_fil(Io_url url, long size) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).Truncate_fil(url, size);}
public void MoveDirDeep(Io_url src, Io_url trg) {IoEngine_xrg_xferDir.move_(src, trg).Recur_().Exec();}
public IoEngine_xrg_xferDir CopyDir_cmd(Io_url src, Io_url trg) {return IoEngine_xrg_xferDir.copy_(src, trg);}
public void CopyDirSubs(Io_url src, Io_url trg) {IoEngine_xrg_xferDir.copy_(src, trg).Exec();}
public void CopyDirDeep(Io_url src, Io_url trg) {IoEngine_xrg_xferDir.copy_(src, trg).Recur_().Exec();}
public void DeleteDirIfEmpty(Io_url url) {
if (Array_.Len(QueryDir_fils(url)) == 0)
this.DeleteDirDeep(url);
}
public void AliasDir_sysEngine(String srcRoot, String trgRoot) {AliasDir(srcRoot, trgRoot, IoEngine_.SysKey);}
public void AliasDir(String srcRoot, String trgRoot, String engineKey) {IoUrlInfoRegy.Instance.Reg(IoUrlInfo_.alias_(srcRoot, trgRoot, engineKey));}
public IoStream OpenStreamRead(Io_url url) {return OpenStreamRead_args(url).ExecAsIoStreamOrFail();}
public IoEngine_xrg_openRead OpenStreamRead_args(Io_url url) {return IoEngine_xrg_openRead.new_(url);}
public String LoadFilStr(String url) {return LoadFilStr_args(Io_url_.new_fil_(url)).Exec();}
public String LoadFilStr(Io_url url) {return LoadFilStr_args(url).Exec();}
public IoEngine_xrg_loadFilStr LoadFilStr_args(Io_url url) {return IoEngine_xrg_loadFilStr.new_(url);}
public byte[] LoadFilBryOrNull(Io_url url) {return LoadFilBryOr(url, null);}
public byte[] LoadFilBryOr(Io_url url, byte[] or) {return ExistsFil(url) ? LoadFilBry(url) : or;}
public byte[] LoadFilBry(String url) {return LoadFilBry_reuse(Io_url_.new_fil_(url), Bry_.Empty, Int_obj_ref.New_zero());}
public byte[] LoadFilBry(Io_url url) {return LoadFilBry_reuse(url, Bry_.Empty, Int_obj_ref.New_zero());}
public void LoadFilBryByBfr(Io_url url, Bry_bfr bfr) {
Int_obj_ref len = Int_obj_ref.New_zero();
byte[] bry = LoadFilBry_reuse(url, Bry_.Empty, len);
bfr.Bfr_init(bry, len.Val());
}
public static final byte[] LoadFilBry_fail = Bry_.Empty;
public byte[] LoadFilBry_reuse(Io_url url, byte[] ary, Int_obj_ref ary_len) {
if (loader != null) {
byte[] rv = loader.Load_fil_as_bry(url);
if (rv != null) return rv;
}
if (!ExistsFil(url)) {
ary_len.Val_(0);
return LoadFilBry_fail;
}
IoStream stream = IoStream_.Null;
try {
stream = OpenStreamRead(url);
int stream_len = (int)stream.Len();
ary_len.Val_(stream_len);
if (stream_len > ary.length)
ary = new byte[stream_len];
stream.ReadAry(ary);
return ary;
}
catch (Exception e) {throw Err_.new_wo_type("failed to load file", "url", url.Xto_api(), "e", Err_.Message_lang(e));}
finally {stream.Rls();}
}
public byte[] LoadFilBry_loose(Io_url url) {return Bry_.new_u8(LoadFilStr_loose(url));}
public String LoadFilStr_loose(Io_url url) {
String rv = LoadFilStr_args(url).BomUtf8Convert_(Bool_.Y).MissingIgnored_(Bool_.Y).Exec();
if (String_.Has(rv, "\r\n"))
rv = String_.Replace(rv, "\r\n", "\n");
return rv;
}
public void AppendFilBfr(Io_url url, Bry_bfr bfr) {AppendFilByt(url, bfr.Bfr(), 0, bfr.Len()); bfr.ClearAndReset();}
public void AppendFilByt(Io_url url, byte[] val) {AppendFilByt(url, val, 0, val.length);}
public void AppendFilByt(Io_url url, byte[] val, int len) {AppendFilByt(url, val, 0, len);}
public void AppendFilByt(Io_url url, byte[] val, int bgn, int len) {
IoStream stream = IoStream_.Null;
try {
stream = OpenStreamWrite_args(url).Mode_(IoStream_.Mode_wtr_append).Exec();
stream.Write(val, bgn, len);
} finally {stream.Rls();}
}
public void SaveFilBfr(Io_url url, Bry_bfr bfr) {SaveFilBry(url, bfr.Bfr(), bfr.Len()); bfr.Clear();}
public void SaveFilBry(String urlStr, byte[] val) {SaveFilBry(Io_url_.new_fil_(urlStr), val);}
public void SaveFilBry(Io_url url, byte[] val) {SaveFilBry(url, val, val.length);}
public void SaveFilBry(Io_url url, byte[] val, int len) {SaveFilBry(url, val, 0, len);}
public void SaveFilBry(Io_url url, byte[] val, int bgn, int len) {
IoStream stream = IoStream_.Null;
try {
stream = OpenStreamWrite(url);
stream.Write(val, bgn, len);
} finally {stream.Rls();}
}
public IoEngine InitEngine_mem() {return IoEngine_.Mem_init_();}
public IoEngine InitEngine_mem_(String key) {
IoEngine engine = IoEngine_.mem_new_(key);
IoEnginePool.Instance.Add_if_dupe_use_nth(engine);
IoUrlInfoRegy.Instance.Reg(IoUrlInfo_.mem_(key, key));
return engine;
}
public boolean DownloadFil(String src, Io_url trg) {return IoEngine_xrg_downloadFil.new_(src, trg).Exec();}
public IoEngine_xrg_downloadFil DownloadFil_args(String src, Io_url trg) {return IoEngine_xrg_downloadFil.new_(src, trg);}
public static final Io_mgr Instance = new Io_mgr();
public static final int Len_kb = 1024, Len_mb = 1048576, Len_gb = 1073741824, Len_gb_2 = 2147483647;
public static final long Len_mb_long = Len_mb;
public static final long Len_null = -1;
public static final String Evt__fil_created = "fil_created";
}
class Io_mgr_ {
public static int Delete_dir_empty(Io_url url) {
IoItmDir dir = Io_mgr.Instance.QueryDir_args(url).ExecAsDir();
int sub_dirs_len = dir.SubDirs().Count();
int deleted_dirs = 0;
for (int i = 0; i < sub_dirs_len; ++i) {
IoItmDir sub_dir = (IoItmDir)dir.SubDirs().Get_at(i);
deleted_dirs += Io_mgr.Instance.Delete_dir_empty(sub_dir.Url());
}
if ( dir.SubFils().Count() == 0
&& deleted_dirs == sub_dirs_len
) {
Io_mgr.Instance.DeleteDirIfEmpty(url);
return 1;
}
else
return 0;
}
}

@ -0,0 +1,98 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Io_mgr__tst {
@Before public void init() {fxt.Clear();} private final Io_mgr__fxt fxt = new Io_mgr__fxt();
@Test public void Dir_delete_empty__basic() {
fxt.Exec_itm_create("mem/dir/");
fxt.Exec_dir_delete_empty("mem/dir/");
fxt.Test_itm_exists_n("mem/dir/");
}
@Test public void Dir_delete_empty__no_delete() {
fxt.Exec_itm_create
( "mem/dir/"
, "mem/dir/fil.txt"
);
fxt.Exec_dir_delete_empty("mem/dir/");
fxt.Test_itm_exists_y("mem/dir/");
}
@Test public void Dir_delete_empty__nested_simple() {
fxt.Exec_itm_create
( "mem/dir/"
, "mem/dir/1/"
, "mem/dir/1/11/"
);
fxt.Exec_dir_delete_empty("mem/dir/");
fxt.Test_itm_exists_n("mem/dir/");
}
@Test public void Dir_delete_empty__nested_many() {
fxt.Exec_itm_create
( "mem/dir/"
, "mem/dir/1/"
, "mem/dir/1/11/"
, "mem/dir/2/22/"
, "mem/dir/2/22/222a/"
, "mem/dir/2/22/222b/"
);
fxt.Exec_dir_delete_empty("mem/dir/");
fxt.Test_itm_exists_n("mem/dir/");
}
@Test public void Dir_delete_empty__nested_some() {
fxt.Exec_itm_create
( "mem/dir/"
, "mem/dir/1/"
, "mem/dir/1/11/"
, "mem/dir/2/22/"
, "mem/dir/2/22/a.txt"
, "mem/dir/2/22/222a/"
, "mem/dir/2/22/222b/"
);
fxt.Exec_dir_delete_empty("mem/dir/");
fxt.Test_itm_exists_n
( "mem/dir/1/"
, "mem/dir/1/11/"
, "mem/dir/2/22/222a/"
, "mem/dir/2/22/222b/"
);
fxt.Test_itm_exists_y
( "mem/dir/"
, "mem/dir/2/22/"
);
}
}
class Io_mgr__fxt {
public void Clear() {Io_mgr.Instance.InitEngine_mem();}
public void Exec_itm_create(String... ary) {
for (String itm : ary) {
Io_url url = Io_url_.new_any_(itm);
if (url.Type_dir())
Io_mgr.Instance.CreateDir(url);
else
Io_mgr.Instance.SaveFilStr(url, url.NameAndExt());
}
}
public void Exec_dir_delete_empty(String url) {Io_mgr.Instance.Delete_dir_empty(Io_url_.mem_dir_(url));}
public void Test_itm_exists_n(String... ary) {Test_itm_exists(Bool_.N, ary);}
public void Test_itm_exists_y(String... ary) {Test_itm_exists(Bool_.Y, ary);}
public void Test_itm_exists(boolean expd, String... ary) {
for (String itm : ary) {
Io_url url = Io_url_.new_any_(itm);
boolean actl = url.Type_dir() ? Io_mgr.Instance.ExistsDir(url) : Io_mgr.Instance.ExistsFil(url);
Tfds.Eq(expd, actl, itm);
}
}
}

@ -0,0 +1,89 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*; import gplx.core.ios.*; /*IoUrlInfo*/ import gplx.core.envs.*; import gplx.langs.htmls.*; import gplx.core.interfaces.*;
public class Io_url implements CompareAble, ParseAble, Gfo_invk { //_20101005 URL:doc/Io_url.txt
public IoUrlInfo Info() {return info;} IoUrlInfo info;
public String Raw() {return raw;} final String raw;
public byte[] RawBry() {return Bry_.new_u8(raw);}
public String To_http_file_str() {return String_.Len_eq_0(raw) ? String_.Empty : String_.Concat (Http_file_str, Http_file_str_encoder.Encode_str(raw));}
public byte[] To_http_file_bry() {return String_.Len_eq_0(raw) ? Bry_.Empty : Bry_.Add (Http_file_bry, Http_file_str_encoder.Encode_bry(raw));}
public static Url_encoder_interface Http_file_str_encoder = Url_encoder_interface_same.Instance;
public static final String Http_file_str = "file:///";
public static final int Http_file_len = String_.Len(Http_file_str);
public static final byte[] Http_file_bry = Bry_.new_a7(Http_file_str);
public boolean Type_dir() {return info.IsDir(raw);} public boolean Type_fil() {return !info.IsDir(raw);}
public Io_url OwnerDir() {return Io_url_.new_inf_(info.OwnerDir(raw), info);}
public Io_url OwnerRoot() {return Io_url_.new_inf_(info.OwnerRoot(raw), info);}
public String NameAndExt() {return info.NameAndExt(raw);}
public String NameAndExt_noDirSpr() {return this.Type_dir() ? this.NameOnly() : this.NameAndExt();}
public String NameOnly() {return info.NameOnly(raw);}
public String Ext() {return info.Ext(raw);}
public String Xto_api() {return info.Xto_api(raw);}
public String XtoCaseNormalized() {return String_.CaseNormalize(info.CaseSensitive(), raw);}
public Io_url GenSubDir(String subDirName) {return Io_url_.new_inf_(String_.Concat(raw, subDirName, info.DirSpr()), info);}
public Io_url GenSubDir_nest(String... ary) {return GenSub(false, ary);}
public Io_url GenSubFil(String val) {return Io_url_.new_inf_(raw + val, info);}
public Io_url GenSubFil_ary(String... ary) {return Io_url_.new_inf_(raw + String_.Concat(ary), info);}
public Io_url GenSubFil_nest(String... ary) {return GenSub(true, ary);}
public Io_url GenNewNameAndExt(String val) {return this.OwnerDir().GenSubFil(val);}
public Io_url GenNewNameOnly(String val) {return this.OwnerDir().GenSubFil(val + this.Ext());}
public Io_url GenNewExt(String val) {return this.OwnerDir().GenSubFil(this.NameOnly() + val);}
public String Gen_sub_path_for_os(String val) {
if (Op_sys.Cur().Tid_is_wnt()) val = String_.Replace(val, Op_sys.Lnx.Fsys_dir_spr_str(), Op_sys.Wnt.Fsys_dir_spr_str());
return raw + val;
}
public String GenRelUrl_orEmpty(Io_url dir) {
String dirRaw = dir.Raw();
return String_.Has_at_bgn(raw, dirRaw)
? String_.DelBgn(raw, String_.Len(dirRaw))
: String_.Empty;
}
public List_adp XtoNames() {
List_adp list = List_adp_.New();
Io_url cur = this;
while (!cur.EqNull()) {
list.Add(cur.NameAndExt_noDirSpr());
cur = cur.OwnerDir();
}
list.Reverse();
return list;
}
public Io_url GenParallel(Io_url oldRoot, Io_url newRoot) {return newRoot.GenSubFil_ary(GenRelUrl_orEmpty(oldRoot));}
public boolean Eq(Object obj) {if (obj == null) return false; return String_.Eq(raw, ((Io_url)obj).raw);}
public boolean EqNull() {return this.Eq(Io_url_.Empty);}
Io_url GenSub(boolean isFil, String[] ary) {
String_bldr sb = String_bldr_.new_().Add(raw);
int len = Array_.Len(ary);
for (int i = 0; i < len; i++) {
sb.Add(ary[i]);
if (isFil && i == len - 1) break; // do not add closing backslash if last term
sb.Add(info.DirSpr());
}
return Io_url_.new_inf_(sb.To_str(), info);
}
public Object ParseAsObj(String raw) {return Io_url_.new_any_(raw);}
@Override public String toString() {return raw;}
public int compareTo(Object obj) {return CompareAble_.Compare_obj(raw, ((Io_url)obj).raw);}
@Override public boolean equals(Object obj) {return String_.Eq(raw, Io_url_.as_(obj).raw);}
@Override public int hashCode() {return raw.hashCode();}
@gplx.Internal protected Io_url(String raw, IoUrlInfo info) {this.raw = raw; this.info = info;}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_to_http_file)) return To_http_file_str();
else if (ctx.Match(k, Invk_gen_sub_path_for_os)) return Gen_sub_path_for_os(m.ReadStr("v"));
else return Gfo_invk_.Rv_unhandled;
} static final String Invk_to_http_file = "to_http_file", Invk_gen_sub_path_for_os = "gen_sub_path_for_os";
}

@ -0,0 +1,111 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.ios.*; /*IoUrlInfo_*/ import gplx.core.stores.*; import gplx.core.envs.*;
public class Io_url_ {
public static final Io_url Empty = new Io_url("", IoUrlInfo_.Nil);
public static final Io_url NullPtr = null;
public static final Io_url Parser = new Io_url("", IoUrlInfo_.Nil);
public static Io_url as_(Object obj) {return obj instanceof Io_url ? (Io_url)obj : null;}
public static Io_url cast(Object obj) {try {return (Io_url)obj;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, Io_url.class, obj);}}
public static Io_url Usr() {
if (usr_dir == null) {
switch (Op_sys.Cur().Tid()) {
case Op_sys.Tid_wnt: usr_dir = Io_url_.new_inf_("C:\\", IoUrlInfo_.Wnt); break;
case Op_sys.Tid_lnx: usr_dir = Io_url_.new_inf_(String_.Format("/home/{0}/", System_.Prop__user_name()), IoUrlInfo_.Lnx); break;
case Op_sys.Tid_osx: usr_dir = Io_url_.new_inf_(String_.Format("/Users/{0}/", System_.Prop__user_name()), IoUrlInfo_.Lnx); break;
case Op_sys.Tid_drd: usr_dir = Io_url_.new_inf_(String_.Format("/mnt/{0}/", System_.Prop__user_name()), IoUrlInfo_.Lnx); break;
default: throw Err_.new_unhandled(Op_sys.Cur().Tid());
}
}
return usr_dir;
} static Io_url usr_dir;
public static Io_url Usr_Gplx() {return Usr().GenSubDir("gplx");}
public static Io_url mem_dir_(String raw) {
raw = EndsWith_or_add(raw, Op_sys.Lnx.Fsys_dir_spr_str());
return new Io_url(raw, IoUrlInfoRegy.Instance.Match(raw));
}
public static Io_url mem_fil_(String raw) {return new_inf_(raw, IoUrlInfoRegy.Instance.Match(raw));}
public static Io_url wnt_fil_(String raw) {return new_inf_(raw, IoUrlInfo_.Wnt);}
public static Io_url wnt_dir_(String raw) {return new_inf_(EndsWith_or_add(raw, Op_sys.Wnt.Fsys_dir_spr_str()), IoUrlInfo_.Wnt);}
public static Io_url lnx_fil_(String raw) {return new_inf_(raw, IoUrlInfo_.Lnx);}
public static Io_url lnx_dir_(String raw) {return new_inf_(EndsWith_or_add(raw, Op_sys.Lnx.Fsys_dir_spr_str()), IoUrlInfo_.Lnx);}
public static Io_url new_fil_(String raw) {return new_any_(raw);}
public static Io_url new_dir_(String raw) {return new_any_(raw);} // NOTE: for now, same as new_fil; stack overflow when doing new_dir
public static Io_url new_dir_infer(String raw) {return Op_sys.Cur().Tid_is_wnt() ? wnt_dir_(raw) : lnx_dir_(raw);}
public static Io_url new_any_(String raw) {return new_inf_(raw, IoUrlInfoRegy.Instance.Match(raw));}
public static Io_url new_inf_(String raw, IoUrlInfo info) {return String_.Eq(raw, "") ? Io_url_.Empty : new Io_url(raw, info);}
public static Io_url New__http_or_fail(String raw) {return New__http_or_fail(Bry_.new_u8(raw));}
public static Io_url New__http_or_fail(byte[] raw) {
Io_url rv = New__http_or_null(raw);
if (rv == null) throw Err_.new_wo_type("url:invalid http_file raw", "raw", raw);
return rv;
}
public static Io_url New__http_or_null(String raw) {return New__http_or_null(Bry_.new_u8(raw));}
public static Io_url New__http_or_null(byte[] raw) {
int len = raw.length;
if (!Bry_.Has_at_bgn(raw, Io_url.Http_file_bry, 0, len)) return null; // doesn't start with "file:///"; return null;
// bld rv; note that wnt has to convert / to \
byte[] rv = null;
if (Op_sys.Cur().Tid_is_wnt()) {
int rv_len = len - Io_url.Http_file_len;
rv = new byte[rv_len];
for (int i = 0; i < rv_len; ++i) {
byte b = raw[i + Io_url.Http_file_len];
if (b == Op_sys.Dir_spr__lnx) b = Op_sys.Dir_spr__wnt;
rv[i] = b;
}
}
else
rv = Bry_.Mid(raw, Io_url.Http_file_len);
return rv == null ? null : new_any_(String_.new_u8(rv));
}
public static Io_url store_orFail_(SrlMgr mgr, String key, Io_url v) {
String s = mgr.SrlStrOr(key, v.Raw());
return (mgr.Type_rdr()) ? Io_url_.new_any_(s) : v;
}
public static Io_url store_orSelf_(SrlMgr mgr, String key, Io_url v) {
String s = mgr.SrlStrOr(key, v.Raw());
return (mgr.Type_rdr()) ? Io_url_.new_any_(s) : v;
}
public static Io_url rdrOr_(DataRdr rdr, String key, Io_url or) {
String val = rdr.ReadStrOr(key, null); if (val == null) return or; // NOTE: val == null also checks for rdr == DataRdr_.Null
return Io_url_.new_any_(val);
}
static String EndsWith_or_add(String raw, String endsWith) {
if (String_.Has_at_end(raw, endsWith)) return raw;
return raw += endsWith;
}
public static Io_url Rel_dir(String s) {return IsAbs(s) ? Io_url_.new_dir_(s) : Env_.AppUrl().OwnerDir().GenSubDir(s);}
public static Io_url Rel_fil(String s) {return IsAbs(s) ? Io_url_.new_fil_(s) : Env_.AppUrl().OwnerDir().GenSubFil(s);}
static boolean IsAbs(String s) {
return String_.Has_at_bgn(s, Op_sys.Lnx.Fsys_dir_spr_str())
|| (String_.Len(s) > 2
&& ( (String_.CharAt(s, 1) == ':' && String_.CharAt(s, 2) == '\\')
|| (String_.CharAt(s, 1) == '\\' && String_.CharAt(s, 2) == '\\')
)
);
}
public static Io_url[] Ary(String... ary) {
int len = ary.length;
Io_url[] rv = new Io_url[len];
for (int i = 0; i < len; ++i)
rv[i] = Io_url_.new_any_(ary[i]);
return rv;
}
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.tests.*; import gplx.core.envs.*;
public class Io_url__tst {
@Before public void init() {fxt.Clear();} private final Io_url__fxt fxt = new Io_url__fxt();
@Test public void Basic__lnx() {fxt.Test__New__http_or_null(Bool_.N, "file:///C:/a.txt", "C:/a.txt");}
@Test public void Basic__wnt() {fxt.Test__New__http_or_null(Bool_.Y, "file:///C:/a.txt", "C:\\a.txt");}
@Test public void Null() {fxt.Test__New__http_or_null(Bool_.N, "C:/a.txt", null);}
}
class Io_url__fxt {
public void Clear() {Io_mgr.Instance.InitEngine_mem();}
public void Test__New__http_or_null(boolean os_is_wnt, String raw, String expd) {
Op_sys.Cur_(os_is_wnt ? Op_sys.Tid_wnt : Op_sys.Tid_lnx);
Gftest.Eq__obj_or_null(expd, Io_url_.New__http_or_null(raw));
}
}

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Keyval implements To_str_able {
@gplx.Internal protected Keyval(int key_tid, Object key, Object val) {this.key_tid = key_tid; this.key = key; this.val = val;}
public String Key() {return Object_.Xto_str_strict_or_null(key);}
public Object Key_as_obj() {return key;} private Object key;
public int Key_tid() {return key_tid;} private int key_tid;
public Object Val() {return val;} private Object val;
public String Val_to_str_or_empty() {return Object_.Xto_str_strict_or_empty(val);}
public String Val_to_str_or_null() {return Object_.Xto_str_strict_or_null(val);}
public byte[] Val_to_bry() {return Bry_.new_u8(Object_.Xto_str_strict_or_null(val));}
public Keyval Key_(Object v) {this.key = v; return this;}
public Keyval Val_(Object v) {this.val = v; return this;}
public String To_str() {return Key() + "=" + Object_.Xto_str_strict_or_null_mark(val);}
@Override public String toString() {return To_str();}
}

@ -0,0 +1,105 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*;
public class Keyval_ {
public static final Keyval[] Ary_empty = new Keyval[0];
public static Keyval[] Ary(Keyval... ary) {return ary;}
public static Keyval[] Ary_cast_(Object o) {
try {return (Keyval[])o;}
catch (Exception e) {throw Err_.new_cast(e, Keyval.class, o);}
}
public static Keyval[] Ary_insert(Keyval[] orig, boolean insert_at_end, Keyval... vals) {
int orig_len = orig.length, vals_len = vals.length;
int rv_len = orig_len + vals_len;
Keyval[] rv = new Keyval[rv_len];
int vals_bgn = 0 , vals_end = vals_len;
int orig_bgn = vals_len , orig_end = rv_len;
if (insert_at_end) {
orig_bgn = 0 ; orig_end = orig_len;
vals_bgn = orig_len ; vals_end = rv_len;
}
for (int i = orig_bgn; i < orig_end; i++)
rv[i] = orig[i - orig_bgn];
for (int i = vals_bgn; i < vals_end; i++)
rv[i] = vals[i - vals_bgn];
return rv;
}
public static String Ary_to_str(Keyval... ary) {
String_bldr sb = String_bldr_.new_();
int len = ary.length;
for (int i = 0; i < len; i++) {
Keyval itm = ary[i];
if (itm == null) {
sb.Add("<<NULL>>");
continue;
}
sb.Add(itm.Key()).Add("=");
Object itm_val = itm.Val();
if (Type_.Eq_by_obj(itm_val, Keyval[].class))
sb.Add(Ary_to_str((Keyval[])itm_val));
else
sb.Add(Object_.Xto_str_strict_or_null_mark(itm_val));
sb.Add_char_nl();
}
return sb.To_str();
}
public static Object Ary_get_by_key_or_null(Keyval[] ary, String key) {
int len = ary.length;
for (int i = 0; i < len; i++) {
Keyval kv = ary[i];
if (String_.Eq(kv.Key(), key)) return kv.Val();
}
return null;
}
public static String Ary__to_str__nest(Keyval... ary) {
Bry_bfr bfr = Bry_bfr_.New();
Ary__to_str__nest(bfr, 0, ary);
return bfr.To_str_and_clear();
}
private static void Ary__to_str__nest(Bry_bfr bfr, int indent, Keyval[] ary) {
int len = ary.length;
for (int i = 0; i < len; ++i) {
Keyval itm = ary[i];
if (indent > 0)
bfr.Add_byte_repeat(Byte_ascii.Space, indent * 2); // add indent : " "
bfr.Add_str_u8(Object_.Xto_str_strict_or_empty(itm.Key())).Add_byte_eq();// add key + eq : "key="
Object val = itm.Val();
if (val == null)
bfr.Add_str_a7(String_.Null_mark);
else {
Class<?> val_type = Type_.Type_by_obj(val);
if (Type_.Eq(val_type, Keyval[].class)) { // val is Keyval[]; recurse
bfr.Add_byte_nl(); // add nl : "\n"
Ary__to_str__nest(bfr, indent + 1, (Keyval[])val);
continue; // don't add \n below
}
else if (Type_.Eq(val_type, Bool_.Cls_ref_type)) { // val is boolean
boolean val_as_bool = Bool_.Cast(val);
bfr.Add(val_as_bool ? Bool_.True_bry : Bool_.False_bry); // add "true" or "false"; don't call toString
}
else
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(val)); // call toString()
}
bfr.Add_byte_nl();
}
}
public static Keyval as_(Object obj) {return obj instanceof Keyval ? (Keyval)obj : null;}
public static Keyval new_(String key) {return new Keyval(Type_ids_.Id__str, key, key);}
public static Keyval new_(String key, Object val) {return new Keyval(Type_ids_.Id__str, key, val);}
public static Keyval int_(int key, Object val) {return new Keyval(Type_ids_.Id__int, key, val);}
public static Keyval obj_(Object key, Object val) {return new Keyval(Type_ids_.Id__obj, key, val);}
}

@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Keyval_hash {
private final Ordered_hash hash = Ordered_hash_.New();
public int Count() {return hash.Count();}
public int Len() {return hash.Count();}
public Keyval_hash Clear() {hash.Clear(); return this;}
public boolean Has(String key) {return hash.Has(key);}
public Keyval Get_at(int i) {return (Keyval)hash.Get_at(i);}
public Object Get_val_or(String key, Object or) {Keyval rv = Get_kvp_or_null(key); return rv == null ? or : rv.Val();}
public Object Get_val_or_null(String key) {return Get_val_or(key, null);}
public Object Get_val_or_fail(String key) {return Keyval_.as_(hash.Get_by_or_fail(key)).Val();}
public String Get_val_as_str_or_fail(String key) {return (String)Get_val_or_fail(key);}
public Keyval Get_kvp_or_null(String key) {return Keyval_.as_(hash.Get_by(key));}
public Keyval_hash Add(Keyval kv) {hash.Add(kv.Key(), kv); return this;}
public Keyval_hash Add(String key, Object val) {hash.Add(key, Keyval_.new_(key, val)); return this;}
public Keyval_hash Add_if_dupe_use_nth(String key, Object val) {hash.Add_if_dupe_use_nth(key, Keyval_.new_(key, val)); return this;}
public void Del(String key) {hash.Del(key);}
public Keyval[] To_ary() {
int len = this.Count();
Keyval[] rv = new Keyval[len];
for (int i = 0; i < len; ++i)
rv[i] = this.Get_at(i);
return rv;
}
}

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Keyval_list {
public int Count() {return list.Count();} private final List_adp list = List_adp_.New();
public void Clear() {list.Clear();}
public Keyval Get_at(int i) {return (Keyval)list.Get_at(i);}
public Keyval_list Add(String key, Object val) {list.Add(Keyval_.new_(key, val)); return this;}
public Keyval[] To_ary() {return (Keyval[])list.To_ary(Keyval.class);}
public String To_str() {
Bry_bfr bfr = Bry_bfr_.New();
int len = list.Count();
for (int i = 0; i < len; ++i) {
Keyval kv = (Keyval)list.Get_at(i);
if (i == 0) bfr.Add_byte_space();
bfr.Add_str_u8(kv.Key()).Add_byte_eq().Add_str_u8(kv.Val_to_str_or_empty());
}
return bfr.To_str_and_clear();
}
public static Keyval_list New_with_one(String key, Object val) {return new Keyval_list().Add(key, val);}
}

@ -0,0 +1,75 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.lists.*; /*EnumerAble,ComparerAble*/
public interface List_adp extends EnumerAble, List_adp__getable {
int Count();
Object Get_at_last();
void Add(Object o);
void Add_at(int i, Object o);
void Add_many(Object... ary);
void Del(Object o);
void Del_at(int i);
void Del_range(int bgn, int end);
void Clear();
int Idx_of(Object o);
int Idx_last();
Object To_ary(Class<?> memberType);
Object To_ary_and_clear(Class<?> memberType);
String[] To_str_ary();
String[] To_str_ary_and_clear();
String To_str();
Object[] To_obj_ary();
void Resize_bounds(int i);
void Move_to(int src, int trg);
void Reverse();
void Sort();
void Sort_by(ComparerAble comparer);
void Shuffle();
}
class List_adp_obj extends List_adp_base implements List_adp {
public List_adp_obj() {super();}
public List_adp_obj(int v) {super(v);}
}
class List_adp_noop implements List_adp {
public int Count() {return 0;}
public int Len() {return 0;}
public Object Get_at(int i) {return null;}
public Object Get_at_last() {return null;}
public Object PopLast() {return null;}
public void Add(Object o) {}
public void Add_at(int i, Object o) {}
public void Add_many(Object... ary) {}
public void Del(Object o) {}
public void Del_at(int i) {}
public void Del_range(int bgn, int end) {}
public void Clear() {}
public int Idx_last() {return -1;}
public int Idx_of(Object o) {return List_adp_.Not_found;}
public void Move_to(int elemPos, int newPos) {}
public void Resize_bounds(int i) {}
public Object To_ary(Class<?> memberType) {return Object_.Ary_empty;}
public Object To_ary_and_clear(Class<?> memberType) {return Object_.Ary_empty;}
public String[] To_str_ary() {return String_.Ary_empty;}
public String[] To_str_ary_and_clear() {return To_str_ary();}
public String To_str() {return "";}
public Object[] To_obj_ary() {return Object_.Ary_empty;}
public java.util.Iterator iterator() {return Iterator_null.Instance;}
public void Reverse() {}
public void Sort() {}
public void Sort_by(ComparerAble comparer) {}
public void Shuffle() {}
}

@ -0,0 +1,53 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.lists.*;
public class List_adp_ {
public static final List_adp Noop = new List_adp_noop();
public static List_adp New() {return new List_adp_obj();}
public static List_adp New_w_size(int v) {return new List_adp_obj(v);}
public static List_adp New_by_many(Object... ary) {
List_adp rv = new List_adp_obj();
rv.Add_many(ary);
return rv;
}
public static void Del_at_last(List_adp list) {list.Del_at(list.Count() - 1);}
public static Object Pop(List_adp list) {
int lastIdx = list.Count() - 1;
Object rv = list.Get_at(lastIdx);
list.Del_at(lastIdx);
return rv;
}
public static Object Pop_first(List_adp list) { // NOTE: dirty way of implementing FIFO queue; should not be used with lists with many members
Object rv = list.Get_at(0);
list.Del_at(0);
return rv;
}
public static Object Pop_last(List_adp list) {
int last_idx = list.Count() - 1;
Object rv = list.Get_at(last_idx);
list.Del_at(last_idx);
return rv;
}
public static Object Pop_or(List_adp list, Object or) {
int list_len = list.Count(); if (list_len == 0) return or;
int last_idx = list_len - 1;
Object rv = list.Get_at(last_idx);
list.Del_at(last_idx);
return rv;
}
public static final int Not_found = -1, Base1 = 1;
}

@ -0,0 +1,173 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import gplx.core.strings.*; import gplx.core.lists.*;
public abstract class List_adp_base implements List_adp, Gfo_invk {
private Object[] list; private int count;
public List_adp_base(int capacity) {
this.list = new Object[capacity];
}
public java.util.Iterator iterator() {
if (count == 0)
return Iterator_null.Instance;
else
return new Iterator_objAry(list, count);
}
public void Add_many(Object... ary) {for (Object o : ary) Add_base(o);}
public int Len() {return count;}
public int Count() {return count;}
public int Idx_last() {return count - 1;}
protected Object Get_at_base(int index) {if (index >= count || index < 0) throw Err_.new_missing_idx(index, count);
return list[index];
}
protected void Add_base(Object o) {
if (count == Array_.Len_obj(list)) Resize_expand();
list[count] = o;
count++;
}
protected int Del_base(Object o) {
int index = IndexOf_base(o); if (index == List_adp_.Not_found) return List_adp_.Not_found;
this.Del_at(index);
return index;
}
public void Del_range(int delBgn, int delEnd) {
BoundsChk(delBgn, delEnd, count);
if (delBgn == 0 && delEnd == count - 1) { // entire list deleted; call .Clear, else will have 0 elem array
this.Clear();
return;
}
int delLen = (delEnd - delBgn) + 1; // EX: 0,2 creates 3 len ary
int newLen = count - delLen;
Object[] newList = new Object[newLen];
if (delBgn != 0) // copy elements < delBgn; skip if delBgn == 0
Array_.Copy_to(list, 0, newList, 0, delBgn);
if (delEnd != count -1 ) // copy elements > delEnd; skip if delEnd == lastIdx
Array_.Copy_to(list, delEnd + 1, newList, delBgn, newLen - delBgn);
list = newList;
count = list.length;
}
protected int IndexOf_base(Object o) {
for (int i = 0; i < count; i++)
if (Object_.Eq(list[i], o)) return i;
return List_adp_.Not_found;
}
@gplx.Virtual public void Clear() {
for (int i = 0; i < count; i++)
list[i] = null;
count = 0;
}
@gplx.Virtual public void Del_at(int index) {if (index >= count || index < 0) throw Err_.new_missing_idx(index, count);
Collapse(index);
count--;
}
public void Move_to(int src, int trg) {if (src >= count || src < 0) throw Err_.new_missing_idx(src, count); if (trg >= count || trg < 0) throw Err_.new_missing_idx(trg, count);
if (src == trg) return; // position not changed
Object o = list[src];
int dif = trg > src ? 1 : -1;
for (int i = src; i != trg; i += dif)
list[i] = list[i + dif];
list[trg] = o;
}
protected void AddAt_base(int pos, Object o) {
if (count + 1 >= Array_.Len_obj(list)) Resize_expand();
for (int i = count; i > pos; i--)
list[i] = list[i - 1];
list[pos] = o;
count = count + 1;
}
public void Resize_bounds(int i) {
Resize_expand(i);
}
public void Sort() {Sort_by(null);}
public void Sort_by(ComparerAble comparer) {List_adp_sorter.new_().Sort(list, count, true, comparer);}
public void Reverse() {
int mid = count / 2; // no need to reverse pivot; ex: for 3 elements, only 1 and 3 need to be exchanged; 2 stays inplace
for (int lhs = 0; lhs < mid; lhs++) {
int rhs = count - lhs - 1; // -1 b/c list[count] is not real element
Object temp = list[lhs];
list[lhs] = list[rhs];
list[rhs] = temp;
}
}
@gplx.Virtual public void Shuffle() {// REF: Fisher-Yates shuffle
RandomAdp random = RandomAdp_.new_();
for (int i = count; i > 1; i--) {
int rndIdx = random.Next(i);
Object tmp = list[rndIdx];
list[rndIdx] = list[i-1];
list[i-1] = tmp;
}
}
public Object Get_at(int i) {return Get_at_base(i);}
public Object Get_at_last() {if (count == 0) throw Err_.new_invalid_op("cannot call Get_at_last on empty list"); return Get_at_base(count - 1);}
public void Add(Object item) {Add_base(item);}
public void Add_at(int i, Object o) {AddAt_base(i, o);}
public void Del(Object item) {Del_base(item);}
public int Idx_of(Object o) {return IndexOf_base(o);}
public List_adp_base() {
list = new Object[Len_initial];
}
private static final int Len_initial = 8;
public Object To_ary_and_clear(Class<?> memberType) {Object rv = To_ary(memberType); this.Clear(); return rv;}
public Object To_ary(Class<?> memberType) {
Object rv = Array_.Create(memberType, count);
for (int i = 0; i < count; i++)
Array_.Set_at(rv, i, list[i]);
return rv;
}
public String[] To_str_ary_and_clear() {String[] rv = To_str_ary(); this.Clear(); return rv;}
public String[] To_str_ary() {return (String[])To_ary(String.class);}
public Object[] To_obj_ary() {
Object[] rv = new Object[count];
for (int i = 0; i < count; ++i)
rv[i] = list[i];
return rv;
}
public String To_str() {
Bry_bfr bfr = Bry_bfr_.New();
for (int i = 0; i < count; ++i)
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(list[i])).Add_byte_nl();
return bfr.To_str_and_clear();
}
private void BoundsChk(int bgn, int end, int len) {
if ( bgn >= 0 && bgn < len
&& end >= 0 && end < len
&& bgn <= end
) return;
throw Err_.new_wo_type("bounds check failed", "bgn", bgn, "end", end, "len", len);
}
void Resize_expand() {Resize_expand(count * 2);}
void Resize_expand(int newCount) {
Object[] trg = new Object[newCount];
for (int i = 0; i < count; i++) {
trg[i] = list[i];
list[i] = null;
}
list = trg;
}
void Collapse(int index) {
for (int i = index; i < count; i++) {
list[i] = (i == count - 1) ? null : list[i + 1];
}
}
@gplx.Internal protected int Capacity() {return Array_.Len_obj(list);}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_len)) return count;
else if (ctx.Match(k, Invk_get_at)) return Get_at(m.ReadInt("v"));
else return Gfo_invk_.Rv_unhandled;
// return this;
} private static final String Invk_len = "len", Invk_get_at = "get_at";
}

@ -0,0 +1,220 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class List_adp_tst {
@Before public void setup() {
list = List_adp_.New();
listBase = (List_adp_base)list;
} List_adp list; List_adp_base listBase;
@Test public void Add() {
Tfds.Eq(0, list.Count());
list.Add("0");
Tfds.Eq(1, list.Count());
}
@Test public void Add_changeCapacity() {
int capacity = 8;
for (int i = 0; i < capacity; i++)
list.Add("0");
Tfds.Eq(capacity, list.Count());
Tfds.Eq(capacity, listBase.Capacity());
list.Add(capacity); // forces resize
Tfds.Eq(capacity + 1, list.Count());
Tfds.Eq(capacity * 2, listBase.Capacity());
}
@Test public void Get_at() {
list.Add("0");
Tfds.Eq("0", list.Get_at(0));
}
@Test public void Fetch_many() {
list_AddMany("0", "1");
Tfds.Eq("0", list.Get_at(0));
Tfds.Eq("1", list.Get_at(1));
}
@Test public void FetchAt_fail() {
try {list.Get_at(0);}
catch (Exception exc) {Err_.Noop(exc); return;}
Tfds.Fail("Get_at should fail for out of bound index");
}
@Test public void Del_at() {
list.Add("0");
Tfds.Eq(1, list.Count());
list.Del_at(0);
Tfds.Eq(0, list.Count());
}
@Test public void DelAt_shiftDown() {
list_AddMany("0", "1");
Tfds.Eq(list.Count(), 2);
list.Del_at(0);
Tfds.Eq(1, list.Count());
Tfds.Eq("1", list.Get_at(0));
}
@Test public void DelAt_fail() {
try {list.Del_at(0);}
catch (Exception exc) {Err_.Noop(exc); return;}
Tfds.Fail("Del_at should fail for out of bound index");
}
@Test public void Del() {
list.Add("0");
Tfds.Eq(1, list.Count());
list.Del("0");
Tfds.Eq(0, list.Count());
}
@Test public void Del_matchMember() {
list_AddMany("0", "1");
Tfds.Eq(2, list.Count());
list.Del("1");
Tfds.Eq(1, list.Count());
Tfds.Eq("0", list.Get_at(0));
}
@Test public void Del_matchFirst() {
list_AddMany("0", "1", "0");
Tfds.Eq(3, list.Count());
list.Del("0");
tst_Enumerator("1", "0");
}
@Test public void Enumerator() {
list_AddMany("0", "1", "2");
tst_Enumerator("0", "1", "2");
}
@Test public void Enumerator_stateLess() { // run 2x, to confirm no state is being cached
list_AddMany("0", "1", "2");
tst_Enumerator("0", "1", "2");
tst_Enumerator("0", "1", "2");
}
@Test public void Enumerator_recursive() { // confirm separate enumerator objects are used
int pos = 0;
list_AddMany("0", "1", "2");
for (Object valObj : list) {
String val = (String)valObj;
Tfds.Eq(Int_.To_str(pos++), val);
tst_Enumerator("0", "1", "2");
}
}
@Test public void Clear() {
int capacity = 8;
for (int i = 0; i < capacity + 1; i++)
list.Add("0");
Tfds.Eq(capacity * 2, listBase.Capacity());
list.Clear();
Tfds.Eq(0, list.Count());
Tfds.Eq(16, listBase.Capacity()); // check that capacity has increased
}
@Test public void Clear_empty() { // confirm no failure
list.Clear();
Tfds.Eq(0, list.Count());
}
@Test public void Reverse() {
list_AddMany("0", "1", "2");
list.Reverse();
tst_Enumerator("2", "1", "0");
}
@Test public void Reverse_empty() {list.Reverse();}
@Test public void Sort() {
list_AddMany("2", "0", "1");
list.Sort();
tst_Enumerator("0", "1", "2");
}
@Test public void Sort_empty() {list.Sort();}
@Test public void Xto_bry() {
list_AddMany("0", "1");
String[] ary = (String[])list.To_ary(String.class);
Tfds.Eq_nullNot(ary);
Tfds.Eq(2, Array_.Len(ary));
}
@Test public void XtoAry_empty() {
String[] ary = (String[])list.To_ary(String.class);
Tfds.Eq_nullNot(ary);
Tfds.Eq(0, Array_.Len(ary));
}
@Test public void Shuffle() {
for (int i = 0; i < 25; i++)
list.Add(i);
list.Shuffle();
int hasMovedCount = 0;
for (int i = 0; i < list.Count(); i++) {
int val = Int_.Cast(list.Get_at(i));
if (val != i) hasMovedCount++;
}
Tfds.Eq_true(hasMovedCount > 0, "all documents have the same index"); // NOTE: may still fail occasionally (1%)
int count = list.Count();
for (int i = 0; i < count; i++)
list.Del(i);
Tfds.Eq(0, list.Count(), "shuffled list does not have the same contents as original list");
}
@Test public void Shuffle_empty() {list.Shuffle();}
@Test public void Move_to() {
run_ClearAndAdd("0", "1", "2").run_MoveTo(0, 1).tst_Order("1", "0", "2");
run_ClearAndAdd("0", "1", "2").run_MoveTo(0, 2).tst_Order("1", "2", "0");
run_ClearAndAdd("0", "1", "2").run_MoveTo(2, 1).tst_Order("0", "2", "1");
run_ClearAndAdd("0", "1", "2").run_MoveTo(2, 0).tst_Order("2", "0", "1");
}
@Test public void Del_range() {
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(0, 2, "3");
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(0, 3);
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(1, 2, "0", "3");
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(1, 3, "0");
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(0, 3);
run_ClearAndAdd("0", "1", "2", "3").tst_DelRange(0, 0, "1", "2", "3");
}
void tst_DelRange(int bgn, int end, String... expd) {
list.Del_range(bgn, end);
Tfds.Eq_ary_str(expd, list.To_str_ary());
}
List_adp_tst run_ClearAndAdd(String... ary) {
list.Clear();
for (int i = 0; i < Array_.Len(ary); i++) {
String val = ary[i];
list.Add(val);
}
return this;
}
List_adp_tst run_MoveTo(int elemPos, int newPos) {list.Move_to(elemPos, newPos); return this;}
List_adp_tst tst_Order(String... expd) {
String[] actl = (String[])list.To_ary(String.class);
Tfds.Eq_ary(expd, actl);
return this;
}
void list_AddMany(String... ary) {
for (int i = 0; i < Array_.Len(ary); i++) {
String val = ary[i];
list.Add(val);
}
}
void tst_Enumerator(String... expd) {
int pos = 0;
int expdLength = Array_.Len(expd);
for (int i = 0; i < expdLength; i++) {
String val = expd[i];
Tfds.Eq(expd[pos++], val);
}
Tfds.Eq(pos, expdLength);
}
}

@ -0,0 +1,110 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Long_ {
public static final String Cls_val_name = "long";
public static final Class<?> Cls_ref_type = Long.class;
public static final int Log10Ary_len = 21;
public static long[] Log10Ary = new long[]
{ 1, 10, 100, 1000, 10000
, 100000, 1000000, 10000000, 100000000, 1000000000
, Long_.Pow(10, 10), Long_.Pow(10, 11), Long_.Pow(10, 12), Long_.Pow(10, 13), Long_.Pow(10, 14)
, Long_.Pow(10, 15), Long_.Pow(10, 16), Long_.Pow(10, 17), Long_.Pow(10, 18), Long_.Pow(10, 19)
, Long_.Max_value
};
public static long parse(String raw) {try {return Long.parseLong(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, long.class, raw);}}
public static long cast(Object obj) {try {return (Long)obj;} catch(Exception e) {throw Err_.new_type_mismatch_w_exc(e, long.class, obj);}}
public static long coerce_(Object v) {
try {String s = String_.as_(v); return s == null ? Long_.cast(v) : Long_.parse(s);}
catch (Exception e) {throw Err_.new_cast(e, long.class, v);}
}
public static String To_str(long v) {return Long.toString(v);}
public static String To_str_PadBgn(long v, int reqdPlaces) {return String_.Pad(To_str(v), reqdPlaces, "0", true);} // ex: 1, 3 returns 001
public static long parse_or(String raw, long or) {
if (raw == null) return or;
try {
int rawLen = String_.Len(raw);
if (raw == null || rawLen == 0) return or;
long rv = 0, factor = 1; int tmp = 0;
for (int i = rawLen; i > 0; i--) {
tmp = Char_.To_int_or(String_.CharAt(raw, i - 1), Int_.Min_value);
if (tmp == Int_.Min_value) return or;
rv += (tmp * factor);
factor *= 10;
}
return rv;
} catch (Exception e) {Err_.Noop(e); return or;}
}
public static int Compare(long lhs, long rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
private static int FindIdx(long[] ary, long find_val) {
int ary_len = ary.length;
int adj = 1;
int prv_pos = 0;
int prv_len = ary_len;
int cur_len = 0;
int cur_idx = 0;
long cur_val = 0;
while (true) {
cur_len = prv_len / 2;
if (prv_len % 2 == 1) ++cur_len;
cur_idx = prv_pos + (cur_len * adj);
if (cur_idx < 0) cur_idx = 0;
else if (cur_idx >= ary_len) cur_idx = ary_len - 1;
cur_val = ary[cur_idx];
if (find_val < cur_val) adj = -1;
else if (find_val > cur_val) adj = 1;
else if (find_val == cur_val) return cur_idx;
if (cur_len == 1) {
if (adj == -1 && cur_idx > 0)
return --cur_idx;
return cur_idx;
}
prv_len = cur_len;
prv_pos = cur_idx;
}
}
public static int DigitCount(long v) {
int adj = Int_.Base1;
if (v < 0) {
if (v == Long_.Min_value) return 19; // NOTE: Long_.Min_value * -1 = Long_.Min_value
v *= -1;
++adj;
}
return FindIdx(Log10Ary, v) + adj;
}
public static long Pow(int val, int exp) {
long rv = val;
for (int i = 1; i < exp; i++)
rv *= val;
return rv;
}
public static long Int_merge(int hi, int lo) {return (long)hi << 32 | (lo & 0xFFFFFFFFL);}
public static int Int_split_lo(long v) {return (int)(v);}
public static int Int_split_hi(long v) {return (int)(v >> 32);}
public static final long
Min_value = Long.MIN_VALUE
, Max_value = Long.MAX_VALUE
;
}
/* alternate for Int_merge; does not work in java
public static long MergeInts(int lo, int hi) {return (uint)(hi << 32) | (lo & 0xffffffff);}
public static int SplitLo(long v) {return (int)(((ulong)v & 0x00000000ffffffff));}
public static int SplitHi(long v) {return (int)(((ulong)v & 0xffffffff00000000)) >> 32;}
*/

@ -0,0 +1,47 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Long__tst {
@Test public void DigitCount() {
tst_DigitCount(0, 1);
tst_DigitCount(1, 1);
tst_DigitCount(9, 1);
tst_DigitCount(10, 2);
tst_DigitCount(100, 3);
tst_DigitCount(10000, 5);
tst_DigitCount(100000, 6);
tst_DigitCount(1000000, 7);
tst_DigitCount(1000000000, 10);
tst_DigitCount(10000000000L, 11);
tst_DigitCount(100000000000L, 12);
tst_DigitCount(10000000000000000L, 17);
tst_DigitCount(-1, 2);
} void tst_DigitCount(long val, int expd) {Tfds.Eq(expd, Long_.DigitCount(val));}
@Test public void Int_merge() {
tst_Int_merge(123, 456, 528280977864L);
tst_Int_merge(123, 457, 528280977865L);
}
void tst_Int_merge(int hi, int lo, long expd) {
Tfds.Eq(expd, Long_.Int_merge(hi, lo));
Tfds.Eq(hi, Long_.Int_split_hi(expd));
Tfds.Eq(lo, Long_.Int_split_lo(expd));
}
@Test public void parse_or() {
parse_or_tst("10000000000", 10000000000L);
}
void parse_or_tst(String raw, long expd) {Tfds.Eq(expd, Long_.parse_or(raw, -1));}
}

@ -0,0 +1,72 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Math_ {
public static double Pow(double val, double exponent) {return java.lang.Math.pow(val, exponent);}
public static double Pi = java.lang.Math.PI;
public static double E = java.lang.Math.E;
public static int Ceil_as_int(double v) {return (int)Ceil(v);}
public static double Ceil(double v) {return java.lang.Math.ceil(v);}
public static int Floor_as_int(double v) {return (int)Floor(v);}
public static double Floor(double v) {return java.lang.Math.floor(v);}
public static double Round(double v, int places) {
return java.math.BigDecimal.valueOf(v).setScale(places, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static int Trunc(double v) {return (int)v;}
public static double Exp(double v) {return java.lang.Math.exp(v);}
public static double Log(double v) {return java.lang.Math.log(v);}
public static double Sin(double v) {return java.lang.Math.sin(v);}
public static double Cos(double v) {return java.lang.Math.cos(v);}
public static double Tan(double v) {return java.lang.Math.tan(v);}
public static double Asin(double v) {return java.lang.Math.asin(v);}
public static double Acos(double v) {return java.lang.Math.acos(v);}
public static double Atan(double v) {return java.lang.Math.atan(v);}
public static double Sqrt(double v) {return java.lang.Math.sqrt(v);}
public static int Abs(int val) {return val > 0 ? val : val * -1;}
public static long Abs(long val) {return val > 0 ? val : val * -1;}
public static float Abs(float val) {return val > 0 ? val : val * -1;}
public static double Abs_double(double val) {return val > 0 ? val : val * -1;}
public static int Log10(int val) {
if (val <= 0) return Int_.Min_value;
int rv = -1, baseVal = 10;
while (val != 0) {
val = (val / baseVal);
rv++;
}
return rv;
}
public static int Div_safe_as_int(int val, int divisor) {return divisor == 0 ? 0 : val / divisor;}
public static long Div_safe_as_long(long val, long divisor) {return divisor == 0 ? 0 : val / divisor;}
public static double Div_safe_as_double(double val, double divisor) {return divisor == 0 ? 0 : val / divisor;}
public static int Min(int val0, int val1) {return val0 < val1 ? val0 : val1;}
public static int Max(int val0, int val1) {return val0 > val1 ? val0 : val1;}
public static int[] Base2Ary(int v, int max) {
int[] idxs = new int[32];
int cur = v, mult = max, idx = 0;
while (mult > 0) {
int tmp = cur / mult;
if (tmp >= 1) {
idxs[idx++] = mult;
cur -= mult;
}
mult /= 2;
}
int[] rv = new int[idx];
for (int i = 0; i < idx; i++)
rv[i] = idxs[idx - i - 1];
return rv;
}
}

@ -0,0 +1,59 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Math__tst {
@Test public void Abs() {
tst_Abs(1, 1);
tst_Abs(-1, 1);
tst_Abs(0, 0);
} void tst_Abs(int val, int expd) {Tfds.Eq(expd, Math_.Abs(val));}
@Test public void Log10() {
tst_Log10(0, Int_.Min_value);
tst_Log10(9, 0);
tst_Log10(10, 1);
tst_Log10(99, 1);
tst_Log10(100, 2);
} void tst_Log10(int val, int expd) {Tfds.Eq(expd, Math_.Log10(val));}
@Test public void Min() {
tst_Min(0, 1, 0);
tst_Min(1, 0, 0);
tst_Min(0, 0, 0);
} void tst_Min(int val0, int val1, int expd) {Tfds.Eq(expd, Math_.Min(val0, val1));}
@Test public void Pow() {
tst_Pow(2, 0, 1);
tst_Pow(2, 1, 2);
tst_Pow(2, 2, 4);
} void tst_Pow(int val, int exponent, double expd) {Tfds.Eq(expd, Math_.Pow(val, exponent));}
@Test public void Mult() {
tst_Mult(100, .01f, 1);
} void tst_Mult(int val, float multiplier, int expd) {Tfds.Eq(expd, Int_.Mult(val, multiplier));}
@Test public void Base2Ary() {
tst_Base2Ary( 1, 256, 1);
tst_Base2Ary( 2, 256, 2);
tst_Base2Ary( 3, 256, 1, 2);
tst_Base2Ary( 4, 256, 4);
tst_Base2Ary( 5, 256, 1, 4);
tst_Base2Ary( 6, 256, 2, 4);
tst_Base2Ary(511, 256, 1, 2, 4, 8, 16, 32, 64, 128, 256);
} void tst_Base2Ary(int v, int max, int... expd) {Tfds.Eq_ary(expd, Math_.Base2Ary(v, max));}
@Test public void Round() {
tst_Round(1.5 , 0, 2);
tst_Round(2.5 , 0, 3);
tst_Round(2.123 , 2, 2.12);
tst_Round(21.1 , -1, 20);
} void tst_Round(double v, int places, double expd) {Tfds.Eq(expd, Math_.Round(v, places));}
}

@ -0,0 +1,17 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public @interface New {}

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class ObjAry {
public Object[] Ary() {return ary;} Object[] ary;
public Object Get(int i) {return ary[i];}
public Object Get0() {return ary[0];}
public Object Get1() {return ary[1];}
public static ObjAry pair_(Object val0, Object val1) {
ObjAry rv = new ObjAry();
rv.ary = new Object[2];
rv.ary[0] = val0;
rv.ary[1] = val1;
return rv;
} ObjAry() {}
public static ObjAry many_(Object... ary) {
ObjAry rv = new ObjAry();
rv.ary = ary;
return rv;
}
}

@ -0,0 +1,59 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Object_ {
public static final String Cls_val_name = "Object";
public static final Object[] Ary_empty = new Object[0];
public static Object[] Ary(Object... ary) {return ary;}
public static Object[] Ary_add(Object[] lhs, Object[] rhs) {
int lhs_len = lhs.length, rhs_len = rhs.length;
if (lhs_len == 0) return rhs;
else if (rhs_len == 0) return lhs;
int rv_len = lhs_len + rhs_len;
Object[] rv = new Object[rv_len];
for (int i = 0; i < lhs_len; ++i)
rv[i] = lhs[i];
for (int i = lhs_len; i < rv_len; ++i)
rv[i] = rhs[i - lhs_len];
return rv;
}
public static boolean Eq(Object lhs, Object rhs) {
if (lhs == null && rhs == null) return true;
else if (lhs == null || rhs == null) return false;
else return lhs.equals(rhs);
}
public static String Xto_str_or(Object v, String or) {return v == null ? or : ToString_lang(v);}
public static String Xto_str_strict_or_null(Object v) {return v == null ? null : ToString_lang(v);}
public static String Xto_str_strict_or_null_mark(Object v) {return v == null ? String_.Null_mark : ToString_lang(v);}
public static String Xto_str_strict_or_empty(Object v) {return v == null ? String_.Empty : ToString_lang(v);}
private static String ToString_lang(Object v) {
Class<?> c = v.getClass();
if (Type_.Eq(c, String_.Cls_ref_type)) return (String)v;
else if (Type_.Eq(c, Bry_.Cls_ref_type)) return String_.new_u8((byte[])v);
else return v.toString();
}
public static String Xto_str_loose_or(Object v, String or) { // tries to pretty-print doubles; also standardizes true/false; DATE:2014-07-14
if (v == null) return null;
Class<?> c = Type_.Type_by_obj(v);
if (Type_.Eq(c, String_.Cls_ref_type)) return (String)v;
else if (Type_.Eq(c, Bry_.Cls_ref_type)) return String_.new_u8((byte[])v);
else if (Type_.Eq(c, Bool_.Cls_ref_type)) return Bool_.Cast(v) ? Bool_.True_str : Bool_.False_str; // always return "true" / "false"
else if (Type_.Eq(c, Double_.Cls_ref_type)) return Double_.To_str_loose(Double_.cast(v));
else return v.toString();
}
public static final Object Null = null;
public static final byte[] Bry__null = Bry_.new_a7("null");
}

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*;
public class Object__tst {
@Before public void init() {} private Object__fxt fxt = new Object__fxt();
@Test public void Eq() {
fxt.Test_eq(null, null, true); // both null
fxt.Test_eq(5, 5, true); // both non-null
fxt.Test_eq(5, null, false); // rhs non-null
fxt.Test_eq(null, 5, false); // lhs non-null
}
@Test public void Xto_str_loose_or_null() {
fxt.Test_xto_str_loose_or_null(null, null);
fxt.Test_xto_str_loose_or_null(2449.6000000000004d, "2449.6");
}
}
class Object__fxt {
public void Test_eq(Object lhs, Object rhs, boolean expd) {Tfds.Eq(expd, Object_.Eq(lhs, rhs));}
public void Test_xto_str_loose_or_null(Object v, String expd) {Tfds.Eq(expd, Object_.Xto_str_loose_or(v, null));}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save