mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.11.4.1
This commit is contained in:
117
100_core/src/gplx/Array_.java
Normal file
117
100_core/src/gplx/Array_.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 addPos) {
|
||||
int curLen = cur.length, addLen = add.length;
|
||||
Object[] rv = (Object[])Array_.Create(Array_.Component_type(cur), curLen + addLen);
|
||||
for (int i = 0; i < addPos; i++) // copy old up to addPos
|
||||
rv[i] = cur[i];
|
||||
for (int i = 0; i < addLen; i++) // insert add
|
||||
rv[i + addPos] = add[i];
|
||||
for (int i = addPos; i < curLen; i++) // copy old after addPos
|
||||
rv[i + addLen] = 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_adp_.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;
|
||||
}
|
||||
}
|
||||
41
100_core/src/gplx/Array__tst.java
Normal file
41
100_core/src/gplx/Array__tst.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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;}
|
||||
}
|
||||
40
100_core/src/gplx/Bitmask_.java
Normal file
40
100_core/src/gplx/Bitmask_.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class Bitmask_ {
|
||||
public static boolean Has_int(int val, int find) {return find == (val & find);}
|
||||
public static int Flip_int(boolean enable, int val, int find) {
|
||||
boolean has = find == (val & find);
|
||||
return (has ^ enable) ? val ^ find : val;
|
||||
}
|
||||
public static int Add_int(int lhs, int rhs) {return lhs | rhs;}
|
||||
public static int Add_int_ary(int... ary) {
|
||||
int rv = 0;
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int itm = ary[i];
|
||||
if (rv == 0)
|
||||
rv = itm;
|
||||
else
|
||||
rv = Flip_int(true, rv, itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static boolean Has_byte(byte val, byte find) {return find == (val & find);}
|
||||
public static byte Add_byte(byte flag, byte itm) {return (byte)(flag | itm);}
|
||||
}
|
||||
971
100_core/src/gplx/Bry_.java
Normal file
971
100_core/src/gplx/Bry_.java
Normal file
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.lang.*;
|
||||
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.ios.*;
|
||||
public class Bry_ {
|
||||
public static final String Cls_val_name = "byte[]";
|
||||
public static final byte[] Empty = new byte[0];
|
||||
public static final byte[][] Ary_empty = new byte[0][];
|
||||
public static final Class<?> Cls_ref_type = byte[].class;
|
||||
public static byte[] new_bytes(byte... ary) {return ary;}
|
||||
public static byte[] new_ints(int... ary) {
|
||||
int len = ary.length;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = (byte)ary[i];
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Coalesce_to_empty(byte[] v) {return v == null ? Bry_.Empty : v;}
|
||||
public static byte[] Coalesce(byte[] v, byte[] or) {return v == null ? or : v;}
|
||||
public static byte[] new_a7(String str) {
|
||||
if (str == null) return null;
|
||||
int str_len = str.length();
|
||||
if (str_len == 0) return Bry_.Empty;
|
||||
byte[] rv = new byte[str_len];
|
||||
for (int i = 0; i < str_len; ++i) {
|
||||
char c = str.charAt(i);
|
||||
if (c > 128) c = '?';
|
||||
rv[i] = (byte)c;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] new_u8_safe(String str) {return str == null ? null : new_u8(str);}
|
||||
public static byte[] new_u8(String str) {
|
||||
try {
|
||||
int str_len = str.length();
|
||||
int bry_len = new_u8__by_len(str, str_len);
|
||||
byte[] rv = new byte[bry_len];
|
||||
new_u8__write(str, str_len, rv, 0);
|
||||
return rv;
|
||||
}
|
||||
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
|
||||
}
|
||||
public static int new_u8__by_len(String s, int s_len) {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < s_len; ++i) {
|
||||
char c = s.charAt(i);
|
||||
int c_len = 0;
|
||||
if ( c < 128) c_len = 1; // 1 << 7
|
||||
else if ( c < 2048) c_len = 2; // 1 << 11
|
||||
else if ( (c > 55295) // 0xD800
|
||||
&& (c < 56320)) c_len = 4; // 0xDFFF
|
||||
else c_len = 3; // 1 << 16
|
||||
if (c_len == 4) ++i; // surrogate is 2 wide, not 1
|
||||
rv += c_len;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static void new_u8__write(String str, int str_len, byte[] bry, int bry_pos) {
|
||||
for (int i = 0; i < str_len; ++i) {
|
||||
char c = str.charAt(i);
|
||||
if ( c < 128) {
|
||||
bry[bry_pos++] = (byte)c;
|
||||
}
|
||||
else if ( c < 2048) {
|
||||
bry[bry_pos++] = (byte)(0xC0 | (c >> 6));
|
||||
bry[bry_pos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if ( (c > 55295) // 0xD800
|
||||
&& (c < 56320)) { // 0xDFFF
|
||||
if (i >= str_len) throw Err_.new_wo_type("incomplete surrogate pair at end of String", "char", c);
|
||||
char nxt_char = str.charAt(i + 1);
|
||||
int v = 0x10000 + (c - 0xD800) * 0x400 + (nxt_char - 0xDC00);
|
||||
bry[bry_pos++] = (byte)(0xF0 | (v >> 18));
|
||||
bry[bry_pos++] = (byte)(0x80 | (v >> 12) & 0x3F);
|
||||
bry[bry_pos++] = (byte)(0x80 | (v >> 6) & 0x3F);
|
||||
bry[bry_pos++] = (byte)(0x80 | (v & 0x3F));
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
bry[bry_pos++] = (byte)(0xE0 | (c >> 12));
|
||||
bry[bry_pos++] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
bry[bry_pos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static byte[] Copy(byte[] src) {
|
||||
int src_len = src.length;
|
||||
byte[] trg = new byte[src_len];
|
||||
for (int i = 0; i < src_len; ++i)
|
||||
trg[i] = src[i];
|
||||
return trg;
|
||||
}
|
||||
public static byte[] Resize(byte[] src, int trg_len) {return Resize(src, 0, trg_len);}
|
||||
public static byte[] Resize(byte[] src, int src_bgn, int trg_len) {
|
||||
byte[] trg = new byte[trg_len];
|
||||
int src_len = src.length; if (src_len > trg_len) src_len = trg_len; // trg_len can be less than src_len
|
||||
Copy_by_len(src, src_bgn, src_len, trg, 0);
|
||||
return trg;
|
||||
}
|
||||
public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);}
|
||||
public static byte[] Repeat(byte b, int len) {
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte[] src, byte b) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len + 1];
|
||||
Copy_by_pos(src, 0, src_len, rv, 0);
|
||||
rv[src_len] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte b, byte[] src) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len + 1];
|
||||
Copy_by_pos(src, 0, src_len, rv, 1);
|
||||
rv[0] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte[]... all) {
|
||||
int all_len = all.length, rv_len = 0;
|
||||
for (int i = 0; i < all_len; ++i) {
|
||||
byte[] cur = all[i]; if (cur == null) continue;
|
||||
rv_len += cur.length;
|
||||
}
|
||||
byte[] rv = new byte[rv_len];
|
||||
int rv_idx = 0;
|
||||
for (int i = 0; i < all_len; ++i) {
|
||||
byte[] cur = all[i]; if (cur == null) continue;
|
||||
int cur_len = cur.length;
|
||||
for (int j = 0; j < cur_len; ++j)
|
||||
rv[rv_idx++] = cur[j];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add_w_dlm(byte[] dlm, byte[]... ary) {
|
||||
int ary_len = ary.length;
|
||||
if (ary_len == 0) return Bry_.Empty;
|
||||
int dlm_len = dlm.length;
|
||||
int rv_len = dlm_len * (ary_len - 1); // rv will have at least as many dlms as itms - 1
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (itm != null) rv_len += itm.length;
|
||||
}
|
||||
int rv_pos = 0;
|
||||
byte[] rv = new byte[rv_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (i != 0) {
|
||||
for (int j = 0; j < dlm_len; j++) {
|
||||
rv[rv_pos++] = dlm[j];
|
||||
}
|
||||
}
|
||||
if (itm == null) continue;
|
||||
int itm_len = itm.length;
|
||||
for (int j = 0; j < itm_len; j++) {
|
||||
rv[rv_pos++] = itm[j];
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add_w_dlm(byte dlm, byte[]... ary) {
|
||||
int ary_len = ary.length;
|
||||
if (ary_len == 0) return Bry_.Empty;
|
||||
int rv_len = ary_len - 1; // rv will have at least as many dlms as itms - 1
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (itm != null) rv_len += itm.length;
|
||||
}
|
||||
int rv_pos = 0;
|
||||
byte[] rv = new byte[rv_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (i != 0) rv[rv_pos++] = dlm;
|
||||
if (itm == null) continue;
|
||||
int itm_len = itm.length;
|
||||
for (int j = 0; j < itm_len; j++) {
|
||||
rv[rv_pos++] = itm[j];
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int Len(byte[] v) {return v == null ? 0 : v.length;}
|
||||
public static boolean Len_gt_0(byte[] v) {return v != null && v.length > 0;}
|
||||
public static boolean Len_eq_0(byte[] v) {return v == null || v.length == 0;}
|
||||
public static byte Get_at_end(byte[] bry) {return bry[bry.length - 1];} // don't bother checking for errors; depend on error trace
|
||||
public static boolean Has_at(byte[] src, int src_len, int pos, byte b) {return (pos < src_len) && (src[pos] == b);}
|
||||
public static boolean Has(byte[] src, byte[] lkp) {return Bry_find_.Find_fwd(src, lkp) != Bry_find_.Not_found;}
|
||||
public static boolean Has(byte[] src, byte lkp) {
|
||||
if (src == null) return false;
|
||||
int len = src.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
if (src[i] == lkp) return true;
|
||||
return false;
|
||||
}
|
||||
public static boolean Has_at_bgn(byte[] src, byte[] lkp) {return Has_at_bgn(src, lkp, 0, src.length);}
|
||||
public static boolean Has_at_bgn(byte[] src, byte[] lkp, int src_bgn, int src_end) {
|
||||
int lkp_len = lkp.length;
|
||||
if (lkp_len + src_bgn > src_end) return false; // lkp is longer than src
|
||||
for (int i = 0; i < lkp_len; i++) {
|
||||
if (lkp[i] != src[i + src_bgn]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Has_at_end(byte[] src, byte[] lkp) {int src_len = src.length; return Has_at_end(src, lkp, src_len - lkp.length, src_len);}
|
||||
public static boolean Has_at_end(byte[] src, byte[] lkp, int src_bgn, int src_end) {
|
||||
int lkp_len = lkp.length;
|
||||
if (src_bgn < 0) return false;
|
||||
int pos = src_end - lkp_len; if (pos < src_bgn) return false; // lkp is longer than src
|
||||
for (int i = 0; i < lkp_len; i++) {
|
||||
if (lkp[i] != src[i + pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Has_at_bgn(byte[] src, byte lkp, int src_bgn) {return src_bgn < src.length ? src[src_bgn] == lkp : false;}
|
||||
public static void Set(byte[] src, int bgn, int end, byte[] repl) {
|
||||
int repl_len = repl.length;
|
||||
for (int i = 0; i < repl_len; i++)
|
||||
src[i + bgn] = repl[i];
|
||||
}
|
||||
public static void Copy_by_pos(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
|
||||
int trg_adj = trg_bgn - src_bgn;
|
||||
for (int i = src_bgn; i < src_end; i++)
|
||||
trg[i + trg_adj] = src[i];
|
||||
}
|
||||
private static void Copy_by_len(byte[] src, int src_bgn, int src_len, byte[] trg, int trg_bgn) {
|
||||
for (int i = 0; i < src_len; i++)
|
||||
trg[i + trg_bgn] = src[i + src_bgn];
|
||||
}
|
||||
public static byte[] Replace_one(byte[] src, byte[] find, byte[] repl) {
|
||||
int src_len = src.length;
|
||||
int findPos = Bry_find_.Find(src, find, 0, src_len, true); if (findPos == Bry_find_.Not_found) return src;
|
||||
int findLen = find.length, replLen = repl.length;
|
||||
int rvLen = src_len + replLen - findLen;
|
||||
byte[] rv = new byte[rvLen];
|
||||
Copy_by_len(src , 0 , findPos , rv, 0 );
|
||||
Copy_by_len(repl, 0 , replLen , rv, findPos );
|
||||
Copy_by_len(src , findPos + findLen , src_len - findPos - findLen , rv, findPos + replLen);
|
||||
return rv;
|
||||
}
|
||||
public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);}
|
||||
public static void Replace_all_direct(byte[] src, byte find, byte repl, int bgn, int end) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
if (b == find) src[i] = repl;
|
||||
}
|
||||
}
|
||||
public static byte[] Limit(byte[] src, int len) {
|
||||
if (src == null) return null;
|
||||
int src_len = src.length;
|
||||
return len < src_len ? Bry_.Mid(src, 0, len) : src;
|
||||
}
|
||||
public static byte[] Mid_by_nearby(byte[] src, int pos, int around) {
|
||||
int bgn = pos - around; if (bgn < 0) bgn = 0;
|
||||
int src_len = src.length;
|
||||
int end = pos + around; if (end > src_len) end = src_len;
|
||||
return Mid(src, bgn, end);
|
||||
}
|
||||
public static byte[] Mid_by_len(byte[] src, int bgn, int len) {return Mid(src, bgn, bgn + len);}
|
||||
public static byte[] Mid_by_len_safe(byte[] src, int bgn, int len) {
|
||||
int src_len = src.length;
|
||||
if (bgn < 0) bgn = 0;
|
||||
if (len + bgn > src_len) len = (src_len - bgn);
|
||||
return Mid(src, bgn, bgn + len);
|
||||
}
|
||||
public static String MidByLenToStr(byte[] src, int bgn, int len) {
|
||||
int end = bgn + len; end = Int_.BoundEnd(end, src.length);
|
||||
byte[] ary = Bry_.Mid(src, bgn, end);
|
||||
return String_.new_u8(ary);
|
||||
}
|
||||
public static byte[] Mid_safe(byte[] src, int bgn, int end) {
|
||||
if (src == null) return null;
|
||||
int src_len = src.length;
|
||||
if (bgn < 0) bgn = 0;
|
||||
if (end >= src_len) end = src_len;
|
||||
if (bgn > end) bgn = end;
|
||||
else if (end < bgn) end = bgn;
|
||||
return Mid(src, bgn, end);
|
||||
}
|
||||
public static byte[] Mid(byte[] src, int bgn) {return Mid(src, bgn, src.length);}
|
||||
public static byte[] Mid_or(byte[] src, int bgn, int end, byte[] or) {
|
||||
int src_len = src.length;
|
||||
if ( src == null
|
||||
|| (bgn < 0 || bgn > src_len)
|
||||
|| (end < 0 || end > src_len)
|
||||
|| (end < bgn)
|
||||
)
|
||||
return or;
|
||||
return Mid(src, bgn, src.length);
|
||||
}
|
||||
public static byte[] Mid(byte[] src, int bgn, int end) {
|
||||
try {
|
||||
int len = end - bgn; if (len == 0) return Bry_.Empty;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = bgn; i < end; i++)
|
||||
rv[i - bgn] = src[i];
|
||||
return rv;
|
||||
} catch (Exception e) {Err_.Noop(e); throw Err_.new_("Bry_", "mid failed", "bgn", bgn, "end", end);}
|
||||
}
|
||||
public static byte[] Mid_w_trim(byte[] src, int bgn, int end) {
|
||||
int len = end - bgn; if (len == 0) return Bry_.Empty;
|
||||
int actl_bgn = bgn, actl_end = end;
|
||||
// trim at bgn
|
||||
boolean chars_seen = false;
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
switch (src[i]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
|
||||
break;
|
||||
default:
|
||||
chars_seen = true;
|
||||
actl_bgn = i;
|
||||
i = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!chars_seen) return Bry_.Empty; // all ws
|
||||
// trim at end
|
||||
for (int i = end - 1; i >= actl_bgn; --i) {
|
||||
switch (src[i]) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
|
||||
break;
|
||||
default:
|
||||
actl_end = i + 1;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// extract mid
|
||||
len = actl_end - actl_bgn; if (len == 0) return Bry_.Empty;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = actl_bgn; i < actl_end; ++i)
|
||||
rv[i - actl_bgn] = src[i];
|
||||
return rv;
|
||||
}
|
||||
public static byte[] mask_(int len, byte... itms) {
|
||||
byte[] rv = new byte[len];
|
||||
int itms_len = itms.length;
|
||||
for (int i = 0; i < itms_len; i++) {
|
||||
byte itm = itms[i];
|
||||
rv[itm & 0xFF] = itm; // PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final byte[] Trim_ary_ws = mask_(256, Byte_ascii.Tab, Byte_ascii.Nl, Byte_ascii.Cr, Byte_ascii.Space);
|
||||
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
|
||||
int txt_bgn = bgn, txt_end = end;
|
||||
boolean all_ws = true;
|
||||
if (trim_bgn) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
|
||||
txt_bgn = i;
|
||||
i = end;
|
||||
all_ws = false;
|
||||
}
|
||||
}
|
||||
if (all_ws) return Bry_.Empty;
|
||||
}
|
||||
if (trim_end) {
|
||||
for (int i = end - 1; i > -1; i--) {
|
||||
byte b = src[i];
|
||||
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
|
||||
txt_end = i + 1;
|
||||
i = -1;
|
||||
all_ws = false;
|
||||
}
|
||||
}
|
||||
if (all_ws) return Bry_.Empty;
|
||||
}
|
||||
return Bry_.Mid(src, txt_bgn, txt_end);
|
||||
}
|
||||
public static byte[] Trim_end(byte[] v, byte trim, int end) {
|
||||
boolean trimmed = false;
|
||||
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len
|
||||
for (; pos > -1; pos--) {
|
||||
if (v[pos] == trim) {
|
||||
trimmed = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return trimmed ? Bry_.Mid(v, 0, pos + 1) : v;
|
||||
}
|
||||
public static int Compare(byte[] lhs, byte[] rhs) {
|
||||
if (lhs == null) return CompareAble_.More;
|
||||
else if (rhs == null) return CompareAble_.Less;
|
||||
else return Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
|
||||
}
|
||||
public static int Compare(byte[] lhs, int lhs_bgn, int lhs_end, byte[] rhs, int rhs_bgn, int rhs_end) {
|
||||
int lhs_len = lhs_end - lhs_bgn, rhs_len = rhs_end - rhs_bgn;
|
||||
int min = lhs_len < rhs_len ? lhs_len : rhs_len;
|
||||
int rv = CompareAble_.Same;
|
||||
for (int i = 0; i < min; i++) {
|
||||
rv = (lhs[i + lhs_bgn] & 0xff) - (rhs[i + rhs_bgn] & 0xff); // PATCH.JAVA:need to convert to unsigned byte
|
||||
if (rv != CompareAble_.Same) return rv > CompareAble_.Same ? CompareAble_.More : CompareAble_.Less; // NOTE: changed from if (rv != CompareAble_.Same) return rv; DATE:2013-04-25
|
||||
}
|
||||
return Int_.Compare(lhs_len, rhs_len); // lhs and rhs share same beginning bytes; return len comparisons
|
||||
}
|
||||
public static boolean Eq(byte[] src, byte[] val) {return Eq(src, 0, src == null ? 0 : src.length, val);}
|
||||
public static boolean Eq(byte[] src, int src_bgn, int src_end, byte[] val) {
|
||||
if (src == null && val == null) return true;
|
||||
else if (src == null || val == null) return false;
|
||||
if (src_bgn < 0) return false;
|
||||
int val_len = val.length;
|
||||
if (val_len != src_end - src_bgn) return false;
|
||||
int src_len = src.length;
|
||||
for (int i = 0; i < val_len; i++) {
|
||||
int src_pos = i + src_bgn;
|
||||
if (src_pos == src_len) return false;
|
||||
if (val[i] != src[src_pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Eq_ci_a7(byte[] lhs, byte[] rhs, int rhs_bgn, int rhs_end) {
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
int lhs_len = lhs.length;
|
||||
int rhs_len = rhs_end - rhs_bgn;
|
||||
if (lhs_len != rhs_len) return false;
|
||||
for (int i = 0; i < lhs_len; i++) {
|
||||
byte lhs_b = lhs[i]; if (lhs_b > 64 && lhs_b < 91) lhs_b += 32; // lowercase
|
||||
byte rhs_b = rhs[i + rhs_bgn]; if (rhs_b > 64 && rhs_b < 91) rhs_b += 32; // lowercase
|
||||
if (lhs_b != rhs_b) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Match(byte[] src, byte[] find) {return Match(src, 0, src.length, find, 0, find.length);}
|
||||
public static boolean Match(byte[] src, int src_bgn, byte[] find) {return Match(src, src_bgn, src.length, find, 0, find.length);}
|
||||
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find) {return Match(src, src_bgn, src_end, find, 0, find.length);}
|
||||
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end) {
|
||||
int src_len = src.length;
|
||||
if (src_end > src_len) src_end = src_len; // must limit src_end to src_len, else ArrayIndexOutOfBounds below; DATE:2015-01-31
|
||||
int find_len = find_end - find_bgn;
|
||||
if (find_len != src_end - src_bgn) return false;
|
||||
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
|
||||
for (int i = 0; i < find_len; i++) {
|
||||
int pos = src_bgn + i;
|
||||
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
|
||||
if (src[pos] != find[i + find_bgn]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Match_w_swap(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end, byte swap_src, byte swap_trg) {// same as above, but used by XOWA for ttl matches;
|
||||
int src_len = src.length;
|
||||
if (src_end > src_len) src_end = src_len; // must limit src_end to src_len, else ArrayIndexOutOfBounds below; DATE:2015-01-31
|
||||
int find_len = find_end - find_bgn;
|
||||
if (find_len != src_end - src_bgn) return false;
|
||||
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
|
||||
for (int i = 0; i < find_len; i++) {
|
||||
int pos = src_bgn + i;
|
||||
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
|
||||
byte src_byte = src[pos]; if (src_byte == swap_src) src_byte = swap_trg;
|
||||
byte trg_byte = find[i + find_bgn]; if (trg_byte == swap_src) trg_byte = swap_trg;
|
||||
if (src_byte != trg_byte) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Match_bwd_any(byte[] src, int src_end, int src_bgn, byte[] find) { // NOTE: utf8 doesn't matter (matching byte for byte)
|
||||
int find_len = find.length;
|
||||
for (int i = 0; i < find_len; i++) {
|
||||
int src_pos = src_end - i;
|
||||
int find_pos = find_len - i - 1;
|
||||
if (src_pos < src_bgn) return false; // ran out of src; exit; EX: src=ab; find=abc
|
||||
if (src[src_pos] != find[find_pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static int To_int_by_a7(byte[] v) {
|
||||
int v_len = v.length;
|
||||
int mod = 8 * (v_len - 1);
|
||||
int rv = 0;
|
||||
for (int i = 0; i < v_len; i++) {
|
||||
rv |= v[i] << mod;
|
||||
mod -= 8;
|
||||
}
|
||||
return rv;
|
||||
// return ((0xFF & v[0]) << 24)
|
||||
// | ((0xFF & v[1]) << 16)
|
||||
// | ((0xFF & v[2]) << 8)
|
||||
// | (0xFF & v[3]);
|
||||
}
|
||||
public static byte[] To_a7_bry(int val, int pad_len) {return To_a7_bry(val, null, 0, pad_len);}
|
||||
public static byte[] To_a7_bry(int val, byte[] ary, int aryPos, int pad_len) {
|
||||
int neg = 0;
|
||||
if (val < 0) {
|
||||
val *= -1;
|
||||
neg = 1;
|
||||
}
|
||||
int digits = val == 0 ? 0 : Math_.Log10(val);
|
||||
digits += 1; // digits = log + 1; EX: Log(1-9) = 0, Log(10-99) = 1
|
||||
int ary_len = digits + neg, aryBgn = aryPos, pad = 0;
|
||||
if (ary_len < pad_len) { // padding specified
|
||||
pad = pad_len - ary_len;
|
||||
ary_len = pad_len;
|
||||
}
|
||||
if (ary == null) ary = new byte[ary_len];
|
||||
long factor = 1; // factor needs to be long to handle 1 billion (for which factor would be 10 billion)
|
||||
for (int i = 0; i < digits; i++) // calc maxFactor
|
||||
factor *= 10;
|
||||
if (neg == 1) ary[0] = Byte_NegSign;
|
||||
|
||||
for (int i = 0; i < pad; i++) // fill ary with pad
|
||||
ary[i + aryBgn] = Byte_ascii.To_a7_str(0);
|
||||
aryBgn += pad; // advance aryBgn by pad
|
||||
for (int i = neg; i < ary_len - pad; i++) {
|
||||
int denominator = (int)(factor / 10); // cache denominator to check for divide by 0
|
||||
int digit = denominator == 0 ? 0 : (int)((val % factor) / denominator);
|
||||
ary[aryBgn + i] = Byte_ascii.To_a7_str(digit);
|
||||
factor /= 10;
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
public static byte[] new_by_int(int v) {
|
||||
byte b0 = (byte)(v >> 24);
|
||||
byte b1 = (byte)(v >> 16);
|
||||
byte b2 = (byte)(v >> 8);
|
||||
byte b3 = (byte)(v);
|
||||
if (b0 != 0) return new byte[] {b0, b1, b2, b3};
|
||||
else if (b1 != 0) return new byte[] {b1, b2, b3};
|
||||
else if (b2 != 0) return new byte[] {b2, b3};
|
||||
else return new byte[] {b3};
|
||||
}
|
||||
public static boolean To_bool_by_int(byte[] ary) {
|
||||
int rv = To_int_or(ary, 0, ary.length, Int_.Min_value, Bool_.Y, null);
|
||||
switch (rv) {
|
||||
case 0: return false;
|
||||
case 1: return true;
|
||||
default: throw Err_.new_wo_type("could not parse to boolean int", "val", String_.new_u8(ary));
|
||||
}
|
||||
}
|
||||
public static byte To_int_as_byte(byte[] ary, int bgn, int end, byte or) {return (byte)To_int_or(ary, bgn, end, or);}
|
||||
public static int To_int(byte[] ary) {
|
||||
int rv = To_int_or(ary, 0, ary.length, Int_.Min_value, Bool_.Y, null);
|
||||
if (rv == Int_.Min_value) throw Err_.new_wo_type("could not parse to int", "val", String_.new_u8(ary));
|
||||
return rv;
|
||||
}
|
||||
public static int To_int_or_neg1(byte[] ary) {return To_int_or(ary, 0 , ary.length, -1, Bool_.Y, null);}
|
||||
public static int To_int_or(byte[] ary, int or) {return To_int_or(ary, 0 , ary.length, or, Bool_.Y, null);}
|
||||
public static int To_int_or(byte[] ary, int bgn, int end, int or) {return To_int_or(ary, bgn , end , or, Bool_.Y, null);}
|
||||
public static int To_int_or__strict(byte[] ary, int or) {return To_int_or(ary, 0 , ary.length, or, Bool_.N, null);}
|
||||
private static int To_int_or(byte[] ary, int bgn, int end, int or, boolean sign_is_valid, byte[] ignore_ary) {
|
||||
if ( ary == null
|
||||
|| end == bgn // null-len
|
||||
) return or;
|
||||
int rv = 0, multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[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:
|
||||
rv += multiple * (b - Byte_ascii.Num_0);
|
||||
multiple *= 10;
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
return i == bgn && sign_is_valid ? rv * -1 : or;
|
||||
case Byte_ascii.Plus:
|
||||
return i == bgn && sign_is_valid ? rv : or;
|
||||
default:
|
||||
boolean invalid = true;
|
||||
if (ignore_ary != null) {
|
||||
int ignore_ary_len = ignore_ary.length;
|
||||
for (int j = 0; j < ignore_ary_len; j++) {
|
||||
if (b == ignore_ary[j]) {
|
||||
invalid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid) return or;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int To_int_or__trim_ws(byte[] ary, int bgn, int end, int or) { // NOTE: same as To_int_or, except trims ws at bgn / end; DATE:2014-02-09
|
||||
if (end == bgn) return or; // null len
|
||||
int rv = 0, multiple = 1;
|
||||
boolean numbers_seen = false, ws_seen = false;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[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:
|
||||
rv += multiple * (b - Byte_ascii.Num_0);
|
||||
multiple *= 10;
|
||||
if (ws_seen) // "number ws number" pattern; invalid ws in middle; see tests
|
||||
return or;
|
||||
numbers_seen = true;
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
return i == bgn ? rv * -1 : or;
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
|
||||
if (numbers_seen)
|
||||
ws_seen = true;
|
||||
break;
|
||||
default: return or;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int To_int_or__lax(byte[] ary, int bgn, int end, int or) {
|
||||
if (end == bgn) return or; // null-len
|
||||
int end_num = end;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = ary[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:
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
if (i != bgn) {
|
||||
end_num = i;
|
||||
i = end;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
end_num = i;
|
||||
i = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return To_int_or(ary, bgn, end_num, or);
|
||||
}
|
||||
public static long To_long_or(byte[] ary, long or) {return To_long_or(ary, null, 0, ary.length, or);}
|
||||
public static long To_long_or(byte[] ary, byte[] ignore_ary, int bgn, int end, long or) {
|
||||
if ( ary == null
|
||||
|| end == bgn // null-len
|
||||
) return or;
|
||||
long rv = 0, multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[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:
|
||||
rv += multiple * (b - Byte_ascii.Num_0);
|
||||
multiple *= 10;
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
return i == bgn ? rv * -1 : or;
|
||||
case Byte_ascii.Plus:
|
||||
return i == bgn ? rv : or;
|
||||
default:
|
||||
boolean invalid = true;
|
||||
if (ignore_ary != null) {
|
||||
int ignore_ary_len = ignore_ary.length;
|
||||
for (int j = 0; j < ignore_ary_len; j++) {
|
||||
if (b == ignore_ary[j]) {
|
||||
invalid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid) return or;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static double To_double(byte[] ary, int bgn, int end) {return Double_.parse(String_.new_u8(ary, bgn, end));}
|
||||
public static double To_double_or(byte[] bry, double or) {return Double_.parse_or(String_.new_u8(bry, 0, bry.length), or);}
|
||||
public static double To_double_or(byte[] ary, int bgn, int end, double or) {return Double_.parse_or(String_.new_u8(ary, bgn, end), or);}
|
||||
public static Decimal_adp To_decimal(byte[] ary, int bgn, int end) {return Decimal_adp_.parse(String_.new_u8(ary, bgn, end));}
|
||||
public static byte[][] Ary_add(byte[][] lhs, byte[][] rhs) {
|
||||
int lhs_len = lhs.length, rhs_len = rhs.length;
|
||||
if (lhs_len == 0) return rhs;
|
||||
else if (rhs_len == 0) return lhs;
|
||||
else {
|
||||
byte[][] rv = new byte[lhs_len + rhs_len][];
|
||||
for (int i = 0; i < lhs_len; i++)
|
||||
rv[i] = lhs[i];
|
||||
for (int i = 0; i < rhs_len; i++)
|
||||
rv[i + lhs_len] = rhs[i];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
public static byte[][] Ary(byte[]... ary) {return ary;}
|
||||
public static byte[][] Ary(String... ary) {
|
||||
int ary_len = ary.length;
|
||||
byte[][] rv = new byte[ary_len][];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
String itm = ary[i];
|
||||
rv[i] = itm == null ? null : Bry_.new_u8(itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[][] Ary_obj(Object... ary) {
|
||||
if (ary == null) return Bry_.Ary_empty;
|
||||
int ary_len = ary.length;
|
||||
byte[][] rv = new byte[ary_len][];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
Object itm = ary[i];
|
||||
rv[i] = itm == null ? null : Bry_.new_u8(Object_.Xto_str_strict_or_empty(itm));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static boolean Ary_eq(byte[][] lhs, byte[][] rhs) {
|
||||
int lhs_len = lhs.length;
|
||||
int rhs_len = rhs.length;
|
||||
if (lhs_len != rhs_len) return false;
|
||||
for (int i = 0; i < lhs_len; ++i)
|
||||
if (!Bry_.Eq(lhs[i], rhs[i])) return false;
|
||||
return true;
|
||||
}
|
||||
public static final byte Dlm_fld = (byte)'|', Dlm_row = (byte)'\n', Dlm_quote = (byte)'"', Dlm_null = 0, Ascii_zero = 48;
|
||||
public static final String Fmt_csvDte = "yyyyMMdd HHmmss.fff";
|
||||
public static DateAdp ReadCsvDte(byte[] ary, Int_obj_ref posRef, byte lkp) {// ASSUME: fmt = yyyyMMdd HHmmss.fff
|
||||
int y = 0, M = 0, d = 0, H = 0, m = 0, s = 0, f = 0;
|
||||
int bgn = posRef.Val();
|
||||
y += (ary[bgn + 0] - Ascii_zero) * 1000;
|
||||
y += (ary[bgn + 1] - Ascii_zero) * 100;
|
||||
y += (ary[bgn + 2] - Ascii_zero) * 10;
|
||||
y += (ary[bgn + 3] - Ascii_zero);
|
||||
M += (ary[bgn + 4] - Ascii_zero) * 10;
|
||||
M += (ary[bgn + 5] - Ascii_zero);
|
||||
d += (ary[bgn + 6] - Ascii_zero) * 10;
|
||||
d += (ary[bgn + 7] - Ascii_zero);
|
||||
H += (ary[bgn + 9] - Ascii_zero) * 10;
|
||||
H += (ary[bgn + 10] - Ascii_zero);
|
||||
m += (ary[bgn + 11] - Ascii_zero) * 10;
|
||||
m += (ary[bgn + 12] - Ascii_zero);
|
||||
s += (ary[bgn + 13] - Ascii_zero) * 10;
|
||||
s += (ary[bgn + 14] - Ascii_zero);
|
||||
f += (ary[bgn + 16] - Ascii_zero) * 100;
|
||||
f += (ary[bgn + 17] - Ascii_zero) * 10;
|
||||
f += (ary[bgn + 18] - Ascii_zero);
|
||||
if (ary[bgn + 19] != lkp) throw Err_.new_wo_type("csv date is invalid", "txt", String_.new_u8__by_len(ary, bgn, 20));
|
||||
posRef.Val_add(19 + 1); // +1=lkp.len
|
||||
return DateAdp_.new_(y, M, d, H, m, s, f);
|
||||
}
|
||||
public static String ReadCsvStr(byte[] ary, Int_obj_ref posRef, byte lkp) {return String_.new_u8(ReadCsvBry(ary, posRef, lkp, true));}
|
||||
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp) {return ReadCsvBry(ary, posRef, lkp, true);}
|
||||
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp, boolean make) {
|
||||
int bgn = posRef.Val(), aryLen = ary.length;
|
||||
Bry_bfr bb = null;
|
||||
if (aryLen > 0 && ary[0] == Dlm_quote) {
|
||||
int pos = bgn + 1; // +1 to skip quote
|
||||
if (make) bb = Bry_bfr.new_(16);
|
||||
while (true) {
|
||||
if (pos == aryLen) throw Err_.new_wo_type("endOfAry reached, but no quote found", "txt", String_.new_u8__by_len(ary, bgn, pos));
|
||||
byte b = ary[pos];
|
||||
if (b == Dlm_quote) {
|
||||
if (pos == aryLen - 1) throw Err_.new_wo_type("endOfAry reached, quote found but lkp not", "txt", String_.new_u8__by_len(ary, bgn, pos));
|
||||
byte next = ary[pos + 1];
|
||||
if (next == Dlm_quote) { // byte followed by quote
|
||||
if (make) bb.Add_byte(b);
|
||||
pos += 2;
|
||||
}
|
||||
else if (next == lkp) {
|
||||
posRef.Val_(pos + 2); // 1=endQuote;1=lkp;
|
||||
return make ? bb.To_bry() : Bry_.Empty;
|
||||
}
|
||||
else throw Err_.new_wo_type("quote found, but not doubled", "txt", String_.new_u8__by_len(ary, bgn, pos + 1));
|
||||
}
|
||||
else {
|
||||
if (make) bb.Add_byte(b);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = bgn; i < aryLen; i++) {
|
||||
if (ary[i] == lkp) {
|
||||
posRef.Val_(i + 1); // +1 = lkp.Len
|
||||
return make ? Bry_.Mid(ary, bgn, i) : Bry_.Empty;
|
||||
}
|
||||
}
|
||||
throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "txt", String_.new_u8__by_len(ary, bgn, aryLen));
|
||||
}
|
||||
}
|
||||
public static int ReadCsvInt(byte[] ary, Int_obj_ref posRef, byte lkp) {
|
||||
int bgn = posRef.Val();
|
||||
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
|
||||
if (pos == Bry_find_.Not_found) throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "bgn", bgn);
|
||||
int rv = Bry_.To_int_or(ary, posRef.Val(), pos, -1);
|
||||
posRef.Val_(pos + 1); // +1 = lkp.Len
|
||||
return rv;
|
||||
}
|
||||
public static double ReadCsvDouble(byte[] ary, Int_obj_ref posRef, byte lkp) {
|
||||
int bgn = posRef.Val();
|
||||
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
|
||||
if (pos == Bry_find_.Not_found) throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "bgn", bgn);
|
||||
double rv = Bry_.To_double(ary, posRef.Val(), pos);
|
||||
posRef.Val_(pos + 1); // +1 = lkp.Len
|
||||
return rv;
|
||||
}
|
||||
public static void ReadCsvNext(byte[] ary, Int_obj_ref posRef, byte lkp) {
|
||||
int bgn = posRef.Val();
|
||||
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
|
||||
posRef.Val_(pos + 1); // +1 = lkp.Len
|
||||
}
|
||||
public static byte Byte_NegSign = (byte)'-';
|
||||
public static byte[] Replace_create(byte[] src, byte find, byte replace) {
|
||||
byte[] rv = Bry_.Copy(src);
|
||||
Replace_reuse(rv, find, replace);
|
||||
return rv;
|
||||
}
|
||||
public static void Replace_reuse(byte[] src, byte find, byte replace) {
|
||||
int src_len = src.length;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
if (src[i] == find) src[i] = replace;
|
||||
}
|
||||
}
|
||||
public static byte[] Replace(byte[] src, byte find, byte replace) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len];
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
byte b = src[i];
|
||||
rv[i] = b == find ? replace : b;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Replace_safe(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {
|
||||
if (src == null || find == null || repl == null) return null;
|
||||
return Replace(bfr, src, find, repl, 0, src.length);
|
||||
}
|
||||
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {return Replace(bfr, src, find, repl, 0, src.length);}
|
||||
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl, int src_bgn, int src_end) {return Replace(bfr, src, find, repl, src_bgn, src_end, Int_.Max_value);}
|
||||
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl, int src_bgn, int src_end, int limit) {
|
||||
int pos = src_bgn;
|
||||
boolean dirty = false;
|
||||
int find_len = find.length;
|
||||
int bfr_bgn = pos;
|
||||
int replace_count = 0;
|
||||
while (pos < src_end) {
|
||||
int find_pos = Bry_find_.Find_fwd(src, find, pos);
|
||||
if (find_pos == Bry_find_.Not_found) break;
|
||||
dirty = true;
|
||||
bfr.Add_mid(src, bfr_bgn, find_pos);
|
||||
bfr.Add(repl);
|
||||
pos = find_pos + find_len;
|
||||
bfr_bgn = pos;
|
||||
++replace_count;
|
||||
if (replace_count == limit) break;
|
||||
}
|
||||
if (dirty)
|
||||
bfr.Add_mid(src, bfr_bgn, src_end);
|
||||
return dirty ? bfr.To_bry_and_clear() : src;
|
||||
}
|
||||
public static byte[] Replace(byte[] src, byte[] find, byte[] replace) {return Replace_between(src, find, null, replace);}
|
||||
public static byte[] Replace_between(byte[] src, byte[] bgn, byte[] end, byte[] replace) {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
boolean replace_all = end == null;
|
||||
int src_len = src.length, bgn_len = bgn.length, end_len = replace_all ? 0 : end.length;
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
if (pos >= src_len) break;
|
||||
int bgn_pos = Bry_find_.Find_fwd(src, bgn, pos);
|
||||
if (bgn_pos == Bry_find_.Not_found) {
|
||||
bfr.Add_mid(src, pos, src_len);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int bgn_rhs = bgn_pos + bgn_len;
|
||||
int end_pos = replace_all ? bgn_rhs : Bry_find_.Find_fwd(src, end, bgn_rhs);
|
||||
if (end_pos == Bry_find_.Not_found) {
|
||||
bfr.Add_mid(src, pos, src_len);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
bfr.Add_mid(src, pos, bgn_pos);
|
||||
bfr.Add(replace);
|
||||
pos = end_pos + end_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
public static int Trim_end_pos(byte[] src, int end) {
|
||||
for (int i = end - 1; i > -1; i--) {
|
||||
switch (src[i]) {
|
||||
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: case Byte_ascii.Space:
|
||||
break;
|
||||
default:
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public static byte[] Increment_last(byte[] ary) {return Increment_last(ary, ary.length - 1);}
|
||||
public static byte[] Increment_last(byte[] ary, int end_idx) {
|
||||
for (int i = end_idx; i > -1; i--) {
|
||||
byte end_val_old = ary[i];
|
||||
byte end_val_new = (byte)(end_val_old + 1);
|
||||
ary[i] = end_val_new;
|
||||
if (end_val_new > (end_val_old & 0xff)) break; // PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
public static byte[] Ucase__all(byte[] src) {return Xcase__all(Bool_.Y, src, 0, -1);}
|
||||
public static byte[] Lcase__all(byte[] src) {return Xcase__all(Bool_.N, src, 0, -1);}
|
||||
public static byte[] Lcase__all(byte[] src, int bgn, int end) {return Xcase__all(Bool_.N, src, bgn, end);}
|
||||
private static byte[] Xcase__all(boolean upper, byte[] src, int bgn, int end) {
|
||||
if (src == null) return null;
|
||||
int len = end == -1 ? src.length : end - bgn; if (len == 0) return src;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = src[i + bgn];
|
||||
if (upper) {
|
||||
if (b > 96 && b < 123) b -= 32;
|
||||
}
|
||||
else {
|
||||
if (b > 64 && b < 91) b += 32;
|
||||
}
|
||||
rv[i] = b;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Ucase__1st(byte[] src) {return Xcase__1st(Bool_.Y, src);}
|
||||
public static byte[] Lcase__1st(byte[] src) {return Xcase__1st(Bool_.N, src);}
|
||||
private static byte[] Xcase__1st(boolean upper, byte[] src) {
|
||||
if (src == null) return null;
|
||||
int len = src.length; if (len == 0) return src;
|
||||
byte[] rv = new byte[len];
|
||||
byte b = src[0];
|
||||
if (upper) {
|
||||
if (b > 96 && b < 123) b -= 32;
|
||||
}
|
||||
else {
|
||||
if (b > 64 && b < 91) b += 32;
|
||||
}
|
||||
rv[0] = b;
|
||||
for (int i = 1; i < len; ++i) {
|
||||
rv[i] = src[i];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Null_if_empty(byte[] v) {return Len_eq_0(v) ? null : v;}
|
||||
|
||||
public static byte[] Escape_ws(byte[] bry) {Bry_bfr bfr = Bry_bfr_.Get(); byte[] rv = Escape_ws(bfr, bry); bfr.Mkr_rls(); return rv;}
|
||||
public static byte[] Escape_ws(Bry_bfr bfr, byte[] src) {
|
||||
boolean dirty = false;
|
||||
int len = src.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = src[i];
|
||||
byte escape = Byte_.Zero;
|
||||
switch (b) {
|
||||
case Byte_ascii.Tab: escape = Byte_ascii.Ltr_t; break;
|
||||
case Byte_ascii.Nl: escape = Byte_ascii.Ltr_n; break;
|
||||
case Byte_ascii.Cr: escape = Byte_ascii.Ltr_r; break;
|
||||
default: if (dirty) bfr.Add_byte(b); break;
|
||||
}
|
||||
if (escape != Byte_.Zero) {
|
||||
if (!dirty) {
|
||||
dirty = true;
|
||||
bfr.Add_mid(src, 0, i);
|
||||
}
|
||||
bfr.Add_byte_backslash().Add_byte(escape);
|
||||
}
|
||||
}
|
||||
return dirty ? bfr.To_bry_and_clear() : src;
|
||||
}
|
||||
}
|
||||
287
100_core/src/gplx/Bry__tst.java
Normal file
287
100_core/src/gplx/Bry__tst.java
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*;
|
||||
public class Bry__tst {
|
||||
private final Bry__fxt fxt = new Bry__fxt();
|
||||
@Test public void new_ascii_() {
|
||||
fxt.Test_new_a7("a" , Bry_.new_ints(97)); // one
|
||||
fxt.Test_new_a7("abc" , Bry_.new_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_a7("" , Bry_.Empty); // none
|
||||
fxt.Test_new_a7("¢€𤭢" , Bry_.new_ints(63, 63, 63, 63)); // non-ascii -> ?
|
||||
}
|
||||
@Test public void new_u8() {
|
||||
fxt.Test_new_u8("a" , Bry_.new_ints(97)); // one
|
||||
fxt.Test_new_u8("abc" , Bry_.new_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_u8("¢" , Bry_.new_ints(194, 162)); // bry_len=2; cent
|
||||
fxt.Test_new_u8("€" , Bry_.new_ints(226, 130, 172)); // bry_len=3; euro
|
||||
fxt.Test_new_u8("𤭢" , Bry_.new_ints(240, 164, 173, 162)); // bry_len=3; 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.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); // ∃
|
||||
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.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.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.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.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
|
||||
}
|
||||
}
|
||||
class Bry__fxt {
|
||||
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)));}
|
||||
}
|
||||
584
100_core/src/gplx/Bry_bfr.java
Normal file
584
100_core/src/gplx/Bry_bfr.java
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.encoders.*;
|
||||
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 (mkr_mgr) {
|
||||
mkr_mgr.Rls(mkr_idx);
|
||||
}
|
||||
synchronized (this) {
|
||||
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 (mkr_mgr) {
|
||||
mkr_mgr.Rls(mkr_idx);
|
||||
}
|
||||
mkr_mgr = null;
|
||||
mkr_idx = -1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private 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_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_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_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) {
|
||||
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(val);
|
||||
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_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 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 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();
|
||||
}
|
||||
@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;
|
||||
}
|
||||
public static Bry_bfr new_() {return new Bry_bfr(16);}
|
||||
public static Bry_bfr new_(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
|
||||
Bry_bfr(int bfr_max) {
|
||||
this.bfr_max = bfr_max;
|
||||
this.bfr = new byte[bfr_max];
|
||||
}
|
||||
}
|
||||
41
100_core/src/gplx/Bry_bfr_.java
Normal file
41
100_core/src/gplx/Bry_bfr_.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.brys.*;
|
||||
public class Bry_bfr_ {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
227
100_core/src/gplx/Bry_bfr_tst.java
Normal file
227
100_core/src/gplx/Bry_bfr_tst.java
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class Bry_bfr_tst {
|
||||
private Bry_bfr bb = Bry_bfr.new_(16);
|
||||
@Before public void setup() {bb.Clear();} private ByteAryBfr_fxt fxt = new ByteAryBfr_fxt();
|
||||
@Test public void AddByte() {
|
||||
bb = Bry_bfr.new_(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_(2);
|
||||
tst_AddByte("abcd", "abcd", 12);
|
||||
}
|
||||
@Test public void Add_byte_repeat() { // NOTE: make sure auto-expands
|
||||
bb = Bry_bfr.new_(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)
|
||||
}
|
||||
@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");
|
||||
}
|
||||
}
|
||||
class ByteAryBfr_fxt {
|
||||
private Bry_bfr bfr = Bry_bfr.reset_(16);
|
||||
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 val, String expd) {
|
||||
byte[] val_bry = Bry_.new_u8(val);
|
||||
Tfds.Eq(expd, bfr.Add_bry_escape(Byte_ascii.Apos, Byte_.Ary(Byte_ascii.Apos, Byte_ascii.Apos), val_bry, 0, val_bry.length).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());}
|
||||
}
|
||||
336
100_core/src/gplx/Bry_find_.java
Normal file
336
100_core/src/gplx/Bry_find_.java
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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_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);}
|
||||
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 - CompareAble_.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 - CompareAble_.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_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_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_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_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
|
||||
}
|
||||
}
|
||||
77
100_core/src/gplx/Bry_find__tst.java
Normal file
77
100_core/src/gplx/Bry_find__tst.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
132
100_core/src/gplx/Bry_split_.java
Normal file
132
100_core/src/gplx/Bry_split_.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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) {
|
||||
synchronized (thread_lock) {
|
||||
Bry_split_wkr__to_ary wkr = Bry_split_wkr__to_ary.Instance;
|
||||
Split(src, 0, src == null ? 0 : src.length, 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, itm_bgn, itm_end);} // 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) {
|
||||
if (Bry_.Len_eq_0(src)) return Bry_.Ary_empty;
|
||||
int cur_pos = 0, src_len = src.length, 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_len) break; // dlm is last sequence in src; do not create empty itm
|
||||
find_pos = src_len;
|
||||
}
|
||||
rv.Add(Bry_.Mid(src, cur_pos, find_pos));
|
||||
if (find_pos == src_len) break;
|
||||
cur_pos = find_pos + dlm_len;
|
||||
}
|
||||
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 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() {}
|
||||
}
|
||||
64
100_core/src/gplx/Bry_split__tst.java
Normal file
64
100_core/src/gplx/Bry_split__tst.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
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
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
152
100_core/src/gplx/DateAdp.java
Normal file
152
100_core/src/gplx/DateAdp.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
import java.text.SimpleDateFormat;
|
||||
public class DateAdp implements CompareAble, GfoInvkAble {
|
||||
public int compareTo(Object obj) {DateAdp comp = (DateAdp)obj; return under.compareTo(comp.under);}
|
||||
@Override public String toString() {return XtoStr_gplx_long();}
|
||||
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 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 GfoInvkAble_.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_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 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 TimeSpanAdp Diff(DateAdp earlier) {
|
||||
long diff = this.under.getTimeInMillis() - earlier.under.getTimeInMillis();
|
||||
return TimeSpanAdp_.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;
|
||||
}
|
||||
119
100_core/src/gplx/DateAdp_.java
Normal file
119
100_core/src/gplx/DateAdp_.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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;
|
||||
public class DateAdp_ implements GfoInvkAble {
|
||||
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 Now();
|
||||
else return GfoInvkAble_.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 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 final String Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss";
|
||||
public static String Xto_str_fmt_or(DateAdp v, String fmt, String or) {
|
||||
return v == null ? or : v.XtoStr_fmt(fmt);
|
||||
}
|
||||
}
|
||||
68
100_core/src/gplx/DateAdp__tst.java
Normal file
68
100_core/src/gplx/DateAdp__tst.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class DateAdp__tst {
|
||||
@Test public void Parse_gplx() {
|
||||
tst_Parse_gplx("99991231_235959.999", "99991231_235959.999");
|
||||
tst_Parse_gplx("20090430_213200.123", "20090430_213200.123");
|
||||
tst_Parse_gplx("20090430_213200" , "20090430_213200.000");
|
||||
tst_Parse_gplx("20090430" , "20090430_000000.000");
|
||||
}
|
||||
@Test public void Parse_separators() {
|
||||
tst_Parse_gplx("2009-04-30 21:32:00.123", "20090430_213200.123");
|
||||
tst_Parse_gplx("2009-04-30 21:32:00" , "20090430_213200.000");
|
||||
tst_Parse_gplx("2009-04-30" , "20090430_000000.000");
|
||||
}
|
||||
@Test public void DayOfWeek() {
|
||||
tst_DayOfWeek("2012-01-18", 3); //3=Wed
|
||||
} void tst_DayOfWeek(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).DayOfWeek());}
|
||||
@Test public void WeekOfYear() {
|
||||
tst_WeekOfYear("2006-02-01", 5); // 1-1:Sun;2-1:Wed
|
||||
tst_WeekOfYear("2007-02-01", 5); // 1-1:Mon;2-1:Thu
|
||||
tst_WeekOfYear("2008-02-01", 5); // 1-1:Tue;2-1:Fri
|
||||
tst_WeekOfYear("2009-02-01", 6); // 1-1:Thu;2-1:Sun
|
||||
tst_WeekOfYear("2010-02-01", 6); // 1-1:Fri;2-1:Mon
|
||||
tst_WeekOfYear("2011-02-01", 6); // 1-1:Sat;2-1:Tue
|
||||
} void tst_WeekOfYear(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).WeekOfYear());}
|
||||
@Test public void DayOfYear() {
|
||||
tst_DayOfYear("2012-01-01", 1);
|
||||
tst_DayOfYear("2012-02-29", 60);
|
||||
tst_DayOfYear("2012-12-31", 366);
|
||||
} void tst_DayOfYear(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).DayOfYear());}
|
||||
@Test public void Timestamp_unix() {
|
||||
tst_Timestamp_unix("1970-01-01 00:00:00", 0);
|
||||
tst_Timestamp_unix("2012-01-01 00:00:00", 1325376000);
|
||||
} void tst_Timestamp_unix(String raw, long expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).Timestamp_unix());}
|
||||
@Test public void DaysInMonth() {
|
||||
tst_DaysInMonth("2012-01-01", 31);
|
||||
tst_DaysInMonth("2012-02-01", 29);
|
||||
tst_DaysInMonth("2012-04-01", 30);
|
||||
tst_DaysInMonth("2011-02-01", 28);
|
||||
} void tst_DaysInMonth(String raw, int expd) {Tfds.Eq(expd, DateAdp_.DaysInMonth(DateAdp_.parse_gplx(raw)));}
|
||||
@Test public void XtoUtc() {
|
||||
tst_XtoUtc("2012-01-01 00:00", "2012-01-01 05:00"); //4=Wed
|
||||
} void tst_XtoUtc(String raw, String expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).XtoUtc().XtoStr_fmt_yyyy_MM_dd_HH_mm());}
|
||||
|
||||
void tst_Parse_gplx(String raw, String expd) {
|
||||
DateAdp date = DateAdp_.parse_gplx(raw);
|
||||
String actl = date.XtoStr_gplx();
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
DateAdp_parser bldr = DateAdp_parser.new_();
|
||||
}
|
||||
120
100_core/src/gplx/DateAdp_parser.java
Normal file
120
100_core/src/gplx/DateAdp_parser.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class DateAdp_parser {
|
||||
public int[] Parse_iso8651_like(String raw_str) {Parse_iso8651_like(tmp_rv, raw_str); return tmp_rv;} int[] tmp_rv = new int[7];
|
||||
public void Parse_iso8651_like(int[] rv, String raw_str) {
|
||||
byte[] raw_bry = Bry_.new_u8(raw_str);
|
||||
Parse_iso8651_like(rv, raw_bry, 0, raw_bry.length);
|
||||
}
|
||||
public void Parse_iso8651_like(int[] rv, byte[] src, int bgn, int end) {
|
||||
/* 1981-04-05T14:30:30.000-05:00 ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
|
||||
1981.04.05 14.30.30.000-05.00 ISO 8601 loose
|
||||
99991231_235959.999 gplx
|
||||
yyyy-MM-ddTHH:mm:ss.fffzzzz Format String */
|
||||
int rv_len = rv.length;
|
||||
for (int i = 0; i < rv_len; i++)
|
||||
rv[i] = 0; // .Clear
|
||||
int pos = bgn, rv_idx = 0, int_len = 0, max_len = max_lens[rv_idx];
|
||||
while (true) {
|
||||
int int_val = -1;
|
||||
byte b = pos < end ? src[pos] : Byte_ascii.Null;
|
||||
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:
|
||||
int_val = b - Byte_ascii.Num_0; // convert ascii to val; EX: 49 -> 1
|
||||
int_len = int_bldr.Add(int_val);
|
||||
break;
|
||||
}
|
||||
if ( (int_val == -1 && int_len > 0) // char is not number && number exists (ignore consecutive delimiters: EX: "1981 01")
|
||||
|| int_len == max_len) { // max_len reached; necessary for gplxFormat
|
||||
rv[rv_idx++] = int_bldr.BldAndClear();
|
||||
if (rv_idx == 7) break; // past frac; break;
|
||||
int_len = 0;
|
||||
max_len = max_lens[rv_idx];
|
||||
}
|
||||
if (pos == end) break;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
int[] max_lens = new int[] {4/*y*/,2/*M*/,2/*d*/,2/*H*/,2/*m*/,2/*s*/,3/*S*/,0};
|
||||
IntBldr int_bldr = IntBldr.new_(4);
|
||||
public static DateAdp_parser new_() {return new DateAdp_parser();} DateAdp_parser() {}
|
||||
}
|
||||
class IntBldr {
|
||||
public int Add(char c) {
|
||||
if (idx > digitsLen - 1) throw Err_.new_missing_idx(idx, digitsLen);
|
||||
digits[idx++] = XbyChar(c);
|
||||
return idx;
|
||||
}
|
||||
public int Add(int i) {
|
||||
if (idx > digitsLen - 1) throw Err_.new_missing_idx(idx, digitsLen);
|
||||
digits[idx++] = i;
|
||||
return idx;
|
||||
}
|
||||
public int Parse(String raw) {
|
||||
ParseStr(raw);
|
||||
try {return Bld();}
|
||||
catch (Exception exc) {throw Err_.new_parse_exc(exc, int.class, raw);}
|
||||
}
|
||||
public boolean ParseTry(String raw) {
|
||||
ParseStr(raw);
|
||||
for (int i = 0; i < idx; i++)
|
||||
if (digits[i] < 0) return false;
|
||||
return true;
|
||||
}
|
||||
public int Bld() {
|
||||
int rv = 0, exponent = 1;
|
||||
for (int i = idx - 1; i > -1; i--) {
|
||||
int digit = digits[i];
|
||||
if (digit < 0) throw Err_.new_wo_type("invalid char", "char", (char)-digits[i], "ascii", -digits[i]);
|
||||
rv += digit * exponent;
|
||||
exponent *= 10;
|
||||
}
|
||||
return sign * rv;
|
||||
}
|
||||
public int BldAndClear() {
|
||||
int rv = Bld();
|
||||
this.Clear();
|
||||
return rv;
|
||||
}
|
||||
public void Clear() {idx = 0; sign = 1;}
|
||||
void ParseStr(String raw) {
|
||||
this.Clear();
|
||||
int rawLength = String_.Len(raw);
|
||||
for (int i = 0; i < rawLength; i++) {
|
||||
char c = String_.CharAt(raw, i);
|
||||
if (i == 0 && c == '-')
|
||||
sign = -1;
|
||||
else
|
||||
Add(c);
|
||||
}
|
||||
}
|
||||
int XbyChar(char c) {
|
||||
if (c == '0') return 0; else if (c == '1') return 1; else if (c == '2') return 2; else if (c == '3') return 3; else if (c == '4') return 4;
|
||||
else if (c == '5') return 5; else if (c == '6') return 6; else if (c == '7') return 7; else if (c == '8') return 8; else if (c == '9') return 9;
|
||||
else return -(int)c; // error handling: don't throw error; store ascii value in digit and throw if needed
|
||||
}
|
||||
int[] digits; int idx, digitsLen; int sign = 1;
|
||||
public static IntBldr new_(int digitsMax) {
|
||||
IntBldr rv = new IntBldr();
|
||||
rv.digits = new int[digitsMax];
|
||||
rv.digitsLen = digitsMax;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
34
100_core/src/gplx/DateAdp_parser_tst.java
Normal file
34
100_core/src/gplx/DateAdp_parser_tst.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class DateAdp_parser_tst {
|
||||
@Before public void init() {} DateAdp_parser_fxt fxt = new DateAdp_parser_fxt();
|
||||
@Test public void Parse_gplx() {
|
||||
fxt.Test_Parse_iso8651_like("2000-01-02T03:04:05.006-05:00" , 2000, 1, 2, 3, 4, 5, 6);
|
||||
fxt.Test_Parse_iso8651_like("2000-01-02" , 2000, 1, 2, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
class DateAdp_parser_fxt {
|
||||
DateAdp_parser parser = DateAdp_parser.new_(); int[] actl = new int[7];
|
||||
public void Test_Parse_iso8651_like(String s, int... expd) {
|
||||
byte[] bry = Bry_.new_a7(s);
|
||||
parser.Parse_iso8651_like(actl, bry, 0, bry.length);
|
||||
Tfds.Eq_ary(expd, actl, s);
|
||||
}
|
||||
}
|
||||
90
100_core/src/gplx/Decimal_adp.java
Normal file
90
100_core/src/gplx/Decimal_adp.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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;}
|
||||
}
|
||||
70
100_core/src/gplx/Decimal_adp_.java
Normal file
70
100_core/src/gplx/Decimal_adp_.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 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 {
|
||||
87
100_core/src/gplx/Decimal_adp__tst.java
Normal file
87
100_core/src/gplx/Decimal_adp__tst.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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");
|
||||
}
|
||||
@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");}
|
||||
}
|
||||
72
100_core/src/gplx/EnmMgr.java
Normal file
72
100_core/src/gplx/EnmMgr.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*;
|
||||
public class EnmMgr {
|
||||
public String BitRngSpr() {return bitRngSpr;} public EnmMgr BitRngSpr_(String val) {bitRngSpr = val; return this;} private String bitRngSpr = "+";
|
||||
public String Prefix() {return prefix;} public EnmMgr Prefix_(String val) {prefix = val; return this;} private String prefix;
|
||||
public int BitRngBgn() {return bitRngBgn;} public EnmMgr BitRngBgn_(int val) {bitRngBgn = val; return this;} int bitRngBgn = 1;
|
||||
public int BitRngEnd() {return bitRngEnd;} public EnmMgr BitRngEnd_(int val) {bitRngEnd = val; return this;} int bitRngEnd = Int_.Max_value;
|
||||
public void RegObj(int val, String raw, Object o) {
|
||||
rawRegy.Add(raw, val);
|
||||
valRegy.Add(val, raw);
|
||||
objRegy.Add(val, o);
|
||||
}
|
||||
public Object Get(int val) {return objRegy.Get_by(val);}
|
||||
public int GetVal(String raw) {
|
||||
String[] ary = String_.Split(raw, bitRngSpr);
|
||||
int rv = 0;
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
String term = String_.Trim(ary[i]); // ex: key.ctrl + key.a
|
||||
if (prefix != null) term = String_.Replace(term, prefix, "");
|
||||
int cur = -1;
|
||||
if (String_.Has_at_bgn(term, "#"))
|
||||
cur = Int_.parse(String_.Mid(term, 1));
|
||||
else
|
||||
cur = Int_.cast(rawRegy.Get_by(term));
|
||||
rv |= cur;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public String GetStr(int v) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int cur = v, curModifier = bitRngBgn;
|
||||
while (true) {
|
||||
if (cur == 0
|
||||
|| curModifier > bitRngEnd // loop until all Modifers have been shifted out
|
||||
) break;
|
||||
if ((cur & curModifier) == curModifier) { // cur has Modifier
|
||||
AppendRaw(sb, curModifier);
|
||||
cur ^= curModifier; // shift Modifier out
|
||||
}
|
||||
curModifier *= 2; // move to next Modifier; relies on Shift, Ctrl, Alt enum values
|
||||
}
|
||||
if (cur > 0 // cur is non-Modifier; NOTE: check needed for args that are just a Modifier;
|
||||
|| sb.Count() == 0) // cur is IptKey.None; cur == 0, but sb.length will also be 0
|
||||
AppendRaw(sb, cur);
|
||||
return sb.To_str();
|
||||
}
|
||||
void AppendRaw(String_bldr sb, int key) {
|
||||
String raw = (String)valRegy.Get_by(key);
|
||||
if (sb.Count() > 0) sb.Add(bitRngSpr);
|
||||
if (prefix != null) sb.Add(prefix);
|
||||
sb.Add(raw);
|
||||
}
|
||||
Hash_adp rawRegy = Hash_adp_.new_(), valRegy = Hash_adp_.new_(), objRegy = Hash_adp_.new_();
|
||||
public static EnmMgr new_() {return new EnmMgr();} EnmMgr() {}
|
||||
}
|
||||
22
100_core/src/gplx/Enm_.java
Normal file
22
100_core/src/gplx/Enm_.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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();}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.errs.*;
|
||||
public class Err extends RuntimeException {
|
||||
private final boolean is_gplx;
|
||||
private final String trace;
|
||||
|
||||
@@ -52,6 +52,7 @@ public class Err_ {
|
||||
}
|
||||
|
||||
public static String Message_lang(Throwable e) {return e.getMessage();}
|
||||
public static String To_str(Exception e) {return e.toString();} // e.getMessage() is sometimes null?
|
||||
public static String Trace_lang(Throwable e) {return Trace_lang_exec(e.getStackTrace());}
|
||||
private static String Trace_lang_exec(StackTraceElement[] ary) {
|
||||
String rv = "";
|
||||
|
||||
22
100_core/src/gplx/Guid_adp.java
Normal file
22
100_core/src/gplx/Guid_adp.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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();}
|
||||
}
|
||||
24
100_core/src/gplx/Guid_adp_.java
Normal file
24
100_core/src/gplx/Guid_adp_.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 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));}
|
||||
}
|
||||
28
100_core/src/gplx/Guid_adp__tst.java
Normal file
28
100_core/src/gplx/Guid_adp__tst.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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);
|
||||
}
|
||||
}
|
||||
30
100_core/src/gplx/Hash_adp.java
Normal file
30
100_core/src/gplx/Hash_adp.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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);
|
||||
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();
|
||||
}
|
||||
37
100_core/src/gplx/Hash_adp_.java
Normal file
37
100_core/src/gplx/Hash_adp_.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 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;}
|
||||
}
|
||||
206
100_core/src/gplx/Hash_adp_bry.java
Normal file
206
100_core/src/gplx/Hash_adp_bry.java
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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) {return super.Fetch_base(key_ref.Init((byte[])key));}
|
||||
@Override protected void Del_base(Object key) {super.Del_base(key_ref.Init((byte[])key));}
|
||||
@Override protected boolean Has_base(Object key) {return super.Has_base(key_ref.Init((byte[])key));}
|
||||
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, 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) {return super.Fetch_base(key_ref.Init(src));}
|
||||
public Object Get_by_mid(byte[] src, int bgn, int end) {return super.Fetch_base(key_ref.Init(src, bgn, end));}
|
||||
public Hash_adp_bry Add_byte_int(byte key, int val) {this.Add_base(Bry_.new_bytes(key), Int_obj_val.new_(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, Int_obj_val.new_(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), Int_obj_val.new_(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;
|
||||
}
|
||||
68
100_core/src/gplx/Hash_adp_bry_tst.java
Normal file
68
100_core/src/gplx/Hash_adp_bry_tst.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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;
|
||||
}
|
||||
}
|
||||
98
100_core/src/gplx/Io_url.java
Normal file
98
100_core/src/gplx/Io_url.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.ios.*; /*IoUrlInfo*/ import gplx.core.envs.*;
|
||||
public class Io_url implements CompareAble, ParseAble, GfoInvkAble { //_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 byte[] Http_file_bry() {
|
||||
// try {return Bry_.new_u8(String_.Concat(http_file_str, java.net.URLEncoder.encode(raw, "UTF-8")));}
|
||||
// catch (Exception e) {throw Err_.err_(e, "Http_file_bry");}
|
||||
// }
|
||||
public String To_http_file_str() {return Http_file_str + Http_file_str_encoder.Encode_str(raw);}
|
||||
public byte[] To_http_file_bry() {
|
||||
return 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 GfoInvkAble_.Rv_unhandled;
|
||||
} static final String Invk_to_http_file = "to_http_file", Invk_gen_sub_path_for_os = "gen_sub_path_for_os";
|
||||
}
|
||||
96
100_core/src/gplx/Io_url_.java
Normal file
96
100_core/src/gplx/Io_url_.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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}/", Env_.UserName()), IoUrlInfo_.Lnx); break;
|
||||
case Op_sys.Tid_osx: usr_dir = Io_url_.new_inf_(String_.Format("/Users/{0}/", Env_.UserName()), IoUrlInfo_.Lnx); break;
|
||||
case Op_sys.Tid_drd: usr_dir = Io_url_.new_inf_(String_.Format("/mnt/{0}/", Env_.UserName()), 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_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 http_any_(String src, boolean wnt) {
|
||||
return new_any_(parse_http_file(src, wnt));
|
||||
}
|
||||
private static String parse_http_file(String v, boolean wnt) {
|
||||
byte[] v_bry = Bry_.new_u8(v);
|
||||
int v_len = v_bry.length;
|
||||
if (Bry_.Has_at_bgn(v_bry, Io_url.Http_file_bry, 0, v_len)) {
|
||||
byte[] rv = new byte[v_len - Io_url.Http_file_len];
|
||||
for (int i = 0; i < rv.length; i++) {
|
||||
byte b = v_bry[i + Io_url.Http_file_len];
|
||||
if (wnt && b == Byte_ascii.Slash) b = Byte_ascii.Backslash;
|
||||
rv[i] = b;
|
||||
}
|
||||
return String_.new_u8(rv);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
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) == '\\')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
32
100_core/src/gplx/KeyVal.java
Normal file
32
100_core/src/gplx/KeyVal.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 int Key_tid() {return key_tid;} private int key_tid;
|
||||
public Object Key_as_obj() {return key;} private Object key;
|
||||
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;}
|
||||
@Override public String toString() {return To_str();}
|
||||
public String To_str() {return Key() + "=" + Object_.Xto_str_strict_or_null_mark(val);}
|
||||
}
|
||||
60
100_core/src/gplx/KeyValHash.java
Normal file
60
100_core/src/gplx/KeyValHash.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class KeyValHash {
|
||||
private Ordered_hash hash = Ordered_hash_.New();
|
||||
public int Count() {return hash.Count();}
|
||||
public KeyValHash 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 FetchValOr(String key, Object or) {KeyVal rv = FetchOrNull(key); return rv == null ? or : rv.Val();}
|
||||
public Object FetchValOrNull(String key) {return FetchValOr(key, null);}
|
||||
public Object FetchValOrFail(String key) {return KeyVal_.as_(hash.Get_by_or_fail(key)).Val();}
|
||||
public KeyValHash Add(KeyVal kv) {hash.Add(kv.Key(), kv); return this;}
|
||||
public KeyValHash Add(String key, Object val) {hash.Add(key, KeyVal_.new_(key, val)); return this;}
|
||||
public KeyValHash 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[] Xto_bry() {
|
||||
KeyVal[] rv = new KeyVal[this.Count()];
|
||||
for (int i = 0; i < rv.length; i++)
|
||||
rv[i] = this.Get_at(i);
|
||||
return rv;
|
||||
}
|
||||
public static KeyValHash new_() {return new KeyValHash();} protected KeyValHash() {}
|
||||
public static KeyValHash new_by_ary(KeyVal[] ary) {
|
||||
int ary_len = ary.length;
|
||||
KeyValHash rv = new KeyValHash();
|
||||
for (int i = 0; i < ary_len; i++)
|
||||
rv.Add(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
public KeyVal FetchOrNull(String key) {return KeyVal_.as_(hash.Get_by(key));}
|
||||
public static KeyValHash strAry_(String[] ary) {// needed for consoleLine
|
||||
int aryLen = Array_.Len(ary); if (aryLen % 2 != 0) throw Err_.new_wo_type("array length must be divisible by 2", "aryLen", aryLen, "ary", String_.Concat_lines_crlf(ary));
|
||||
KeyValHash rv = new KeyValHash();
|
||||
String key = null;
|
||||
for (int i = 0; i < aryLen; i++) {
|
||||
if (i % 2 == 0)
|
||||
key = ary[i];
|
||||
else
|
||||
rv.Add(key, ary[i]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final KeyValHash Empty = new KeyValHash();
|
||||
}
|
||||
36
100_core/src/gplx/KeyValHash_tst.java
Normal file
36
100_core/src/gplx/KeyValHash_tst.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class KeyValHash_tst {
|
||||
@Test public void AryVals() {
|
||||
tst_AryVals(ary_());
|
||||
tst_AryVals(ary_("key1", "1"), kv_("key1", "1"));
|
||||
tst_AryVals(ary_("key1", "1", "key2", "2"), kv_("key1", "1"), kv_("key2", "2"));
|
||||
}
|
||||
@Test public void Fail_lengthMustBeEven() {
|
||||
try {
|
||||
tst_AryVals(ary_("key1"), kv_("key1", "1"));
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
catch (Exception e) {Err_.Noop(e);}
|
||||
}
|
||||
void tst_AryVals(String[] ary, KeyVal... expd) {Tfds.Eq_ary_str(expd, KeyValHash.strAry_(ary).Xto_bry());}
|
||||
KeyVal kv_(String key, Object val) {return KeyVal_.new_(key, val);}
|
||||
String[] ary_(String... ary) {return ary;}
|
||||
}
|
||||
36
100_core/src/gplx/KeyValList.java
Normal file
36
100_core/src/gplx/KeyValList.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*;
|
||||
public class KeyValList {//20101217
|
||||
public int Count() {return list.Count();} List_adp list = List_adp_.new_();
|
||||
public void Clear() {list.Clear();}
|
||||
public KeyVal GetAt(int i) {return (KeyVal)list.Get_at(i);}
|
||||
public KeyValList Add(String key, Object val) {list.Add(KeyVal_.new_(key, val)); return this;}
|
||||
public KeyVal[] Xto_bry() {return (KeyVal[])list.To_ary(KeyVal.class);}
|
||||
public String To_str() {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < list.Count(); i++) {
|
||||
KeyVal kv = (KeyVal)list.Get_at(i);
|
||||
sb.Add_spr_unless_first(kv.Key(), " ", i);
|
||||
sb.Add("=").Add(kv.Val_to_str_or_empty());
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public static KeyValList args_(String key, Object val) {return new KeyValList().Add(key, val);}
|
||||
}
|
||||
103
100_core/src/gplx/KeyVal_.java
Normal file
103
100_core/src/gplx/KeyVal_.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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];
|
||||
sb.Add(itm.Key()).Add("=");
|
||||
Object itm_val = itm.Val();
|
||||
if (Type_adp_.Eq_typeSafe(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_nested(KeyVal... ary) {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
Ary_to_str_nested(bfr, 0, ary);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
private static void Ary_to_str_nested(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_adp_.ClassOf_obj(val);
|
||||
if (Type_adp_.Eq(val_type, KeyVal[].class)) { // val is KeyVal[]; recurse
|
||||
bfr.Add_byte_nl(); // add nl : "\n"
|
||||
Ary_to_str_nested(bfr, indent + 1, (KeyVal[])val);
|
||||
continue; // don't add \n below
|
||||
}
|
||||
else if (Type_adp_.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_adp_.Tid__str, key, key);}
|
||||
public static KeyVal new_(String key, Object val) {return new KeyVal(Type_adp_.Tid__str, key, val);}
|
||||
public static KeyVal int_(int key, Object val) {return new KeyVal(Type_adp_.Tid__int, key, val);}
|
||||
public static KeyVal obj_(Object key, Object val) {return new KeyVal(Type_adp_.Tid__obj, key, val);}
|
||||
}
|
||||
77
100_core/src/gplx/List_adp.java
Normal file
77
100_core/src/gplx/List_adp.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.lists.*; /*EnumerAble,ComparerAble*/
|
||||
public interface List_adp extends EnumerAble {
|
||||
int Count();
|
||||
Object Get_at(int i);
|
||||
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 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_.NotFound;}
|
||||
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() {}
|
||||
}
|
||||
73
100_core/src/gplx/List_adp_.java
Normal file
73
100_core/src/gplx/List_adp_.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.lists.*; /*EnumerAble,ComparerAble*/
|
||||
public class List_adp_ {
|
||||
public static final List_adp Noop = new List_adp_noop();
|
||||
public static List_adp as_(Object obj) {return obj instanceof List_adp ? (List_adp)obj : null;}
|
||||
public static List_adp new_() {return new List_adp_obj();}
|
||||
public static List_adp size_(int v) {return new List_adp_obj(v);}
|
||||
public static List_adp many_(Object... ary) {
|
||||
List_adp rv = new List_adp_obj();
|
||||
rv.Add_many(ary);
|
||||
return rv;
|
||||
}
|
||||
public static void Add_list(List_adp rv, List_adp add) {
|
||||
int len = add.Count();
|
||||
for (int i = 0; i < len; ++i)
|
||||
rv.Add(add.Get_at(i));
|
||||
}
|
||||
public static void DelAt_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 void DisposeAll(List_adp list) {
|
||||
for (int i = 0; i < list.Count(); i++)
|
||||
((RlsAble)list.Get_at(i)).Rls();
|
||||
}
|
||||
public static List_adp new_ary_(Object ary) {
|
||||
int ary_len = Array_.Len(ary);
|
||||
List_adp rv = size_(ary_len);
|
||||
for (int i = 0; i < ary_len; i++)
|
||||
rv.Add(Array_.Get_at(ary, i));
|
||||
return rv;
|
||||
}
|
||||
public static final int Capacity_initial = 8;
|
||||
public static final int NotFound = -1, Base1 = 1, LastIdxOffset = 1, CountToPos = 1;
|
||||
}
|
||||
173
100_core/src/gplx/List_adp_base.java
Normal file
173
100_core/src/gplx/List_adp_base.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.lists.*;
|
||||
public abstract class List_adp_base implements List_adp, GfoInvkAble {
|
||||
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 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_.NotFound) return List_adp_.NotFound;
|
||||
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_.NotFound;
|
||||
}
|
||||
@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[List_adp_.Capacity_initial];
|
||||
}
|
||||
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 GfoInvkAble_.Rv_unhandled;
|
||||
// return this;
|
||||
} private static final String Invk_len = "len", Invk_get_at = "get_at";
|
||||
}
|
||||
222
100_core/src/gplx/List_adp_tst.java
Normal file
222
100_core/src/gplx/List_adp_tst.java
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 = List_adp_.Capacity_initial;
|
||||
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 = List_adp_.Capacity_initial;
|
||||
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);
|
||||
}
|
||||
}
|
||||
72
100_core/src/gplx/Math_.java
Normal file
72
100_core/src/gplx/Math_.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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 double Ceil(double v) {return java.lang.Math.ceil(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;
|
||||
}
|
||||
}
|
||||
61
100_core/src/gplx/Math__tst.java
Normal file
61
100_core/src/gplx/Math__tst.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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));}
|
||||
}
|
||||
36
100_core/src/gplx/ObjAry.java
Normal file
36
100_core/src/gplx/ObjAry.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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;
|
||||
}
|
||||
}
|
||||
59
100_core/src/gplx/Object_.java
Normal file
59
100_core/src/gplx/Object_.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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_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_adp_.Eq(c, String_.Cls_ref_type)) return (String)v;
|
||||
else if (Type_adp_.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_adp_.ClassOf_obj(v);
|
||||
if (Type_adp_.Eq(c, String_.Cls_ref_type)) return (String)v;
|
||||
else if (Type_adp_.Eq(c, Bry_.Cls_ref_type)) return String_.new_u8((byte[])v);
|
||||
else if (Type_adp_.Eq(c, Bool_.Cls_ref_type)) return Bool_.cast(v) ? Bool_.True_str : Bool_.False_str; // always return "true" / "false"
|
||||
else if (Type_adp_.Eq(c, Double_.Cls_ref_type)) return Double_.To_str_loose(Double_.cast(v));
|
||||
else return v.toString();
|
||||
}
|
||||
public static final byte[] Bry__null = Bry_.new_a7("null");
|
||||
}
|
||||
36
100_core/src/gplx/Object__tst.java
Normal file
36
100_core/src/gplx/Object__tst.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
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));}
|
||||
}
|
||||
31
100_core/src/gplx/Ordered_hash.java
Normal file
31
100_core/src/gplx/Ordered_hash.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.lists.*; /*EnumerAble,ComparerAble*/
|
||||
public interface Ordered_hash extends Hash_adp {
|
||||
Object Get_at(int i);
|
||||
void Add_at(int i, Object o);
|
||||
int Idx_of(Object item);
|
||||
void Sort();
|
||||
void Sort_by(ComparerAble comparer);
|
||||
void Resize_bounds(int i);
|
||||
Object To_ary(Class<?> t);
|
||||
Object To_ary_and_clear(Class<?> t);
|
||||
void Move_to(int src, int trg);
|
||||
void Lock();
|
||||
}
|
||||
30
100_core/src/gplx/Ordered_hash_.java
Normal file
30
100_core/src/gplx/Ordered_hash_.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.primitives.*;
|
||||
public class Ordered_hash_ {
|
||||
public static Ordered_hash New() {return new Ordered_hash_base();}
|
||||
public static Ordered_hash New_bry() {return new Ordered_hash_bry();}
|
||||
}
|
||||
class Ordered_hash_bry extends Ordered_hash_base {
|
||||
private final Bry_obj_ref tmp_ref = Bry_obj_ref.New_empty();
|
||||
@Override protected void Add_base(Object key, Object val) {super.Add_base(Bry_obj_ref.New((byte[])key), val);}
|
||||
@Override protected void Del_base(Object key) {synchronized (tmp_ref) {super.Del_base(tmp_ref.Val_((byte[])key));}}
|
||||
@Override protected boolean Has_base(Object key) {synchronized (tmp_ref) {return super.Has_base(tmp_ref.Val_((byte[])key));}}
|
||||
@Override protected Object Fetch_base(Object key) {synchronized (tmp_ref) {return super.Fetch_base(tmp_ref.Val_((byte[])key));}}
|
||||
}
|
||||
94
100_core/src/gplx/Ordered_hash_base.java
Normal file
94
100_core/src/gplx/Ordered_hash_base.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.envs.*;
|
||||
import gplx.core.lists.*; /*EnumerAble,ComparerAble*/
|
||||
public class Ordered_hash_base extends Hash_adp_base implements Ordered_hash, GfoInvkAble {
|
||||
@Override protected void Add_base(Object key, Object val) {
|
||||
super.Add_base(key, val);
|
||||
ordered.Add(val);
|
||||
AssertCounts();
|
||||
}
|
||||
@Override public void Del(Object key) {
|
||||
if (!this.Has_base(key)) return;
|
||||
Object val = this.Fetch_base(key);
|
||||
this.Del_base(key);
|
||||
ordered.Del(val);
|
||||
AssertCounts();
|
||||
}
|
||||
protected Object Get_at_base(int index) {return ordered.Get_at(index);}
|
||||
protected int IndexOf_base(Object obj) {return ordered.Idx_of(obj);}
|
||||
@Override public void Clear() {
|
||||
if (locked) Lock_fail();
|
||||
super.Clear();
|
||||
ordered.Clear();
|
||||
}
|
||||
public Object To_ary(Class<?> type) {return ordered.To_ary(type);}
|
||||
public Object To_ary_and_clear(Class<?> t) {
|
||||
Object rv = To_ary(t);
|
||||
this.Clear();
|
||||
return rv;
|
||||
}
|
||||
@gplx.Virtual public void Sort() {if (locked) Lock_fail(); ordered.Sort();} // NOTE: uses item's .compareTo
|
||||
public void Sort_by(ComparerAble comparer) {if (locked) Lock_fail(); ordered.Sort_by(comparer);}
|
||||
@Override public java.util.Iterator iterator() {return ordered.iterator();}
|
||||
public void Add_at(int i, Object key, Object val) {
|
||||
if (locked) Lock_fail();
|
||||
super.Add_base(key, val);
|
||||
ordered.Add_at(i, val);
|
||||
AssertCounts();
|
||||
}
|
||||
void AssertCounts() {
|
||||
if (super.Count() != ordered.Count()) throw Err_.new_wo_type("counts do not match", "hash", super.Count(), "list", ordered.Count());
|
||||
}
|
||||
public void Resize_bounds(int i) {if (locked) Lock_fail(); ordered.Resize_bounds(i);}
|
||||
public void Lock() {locked = true;} private boolean locked = false;
|
||||
void Lock_fail() {throw Err_.new_wo_type("collection is locked");}
|
||||
static final String GRP_KEY = "gplx.core.lists.ordered_hash";
|
||||
public void Add_at(int i, Object o) {if (locked) Lock_fail(); ordered.Add_at(i, o);}
|
||||
public Object Get_at(int i) {return Get_at_base(i);}
|
||||
public int Idx_of(Object obj) {return this.IndexOf_base(obj);}
|
||||
public void Move_to(int src, int trg) {if (locked) Lock_fail(); ordered.Move_to(src, trg);}
|
||||
private String To_str_ui() {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int count = ordered.Count();
|
||||
int pad = String_.Len(Int_.To_str(count));
|
||||
for (int i = 0; i < count; i++) {
|
||||
sb .Add(Int_.To_str_pad_bgn_zero(i, pad))
|
||||
.Add(":").Add(ordered.Get_at(i).toString())
|
||||
.Add(Op_sys.Cur().Nl_str());
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_SetKeyOnly)) {
|
||||
String s = m.ReadStr("v");
|
||||
if (ctx.Deny()) return this;
|
||||
this.Add(s, s);
|
||||
}
|
||||
else if (ctx.Match(k, Invk_Print)) {
|
||||
if (ctx.Deny()) return this;
|
||||
return To_str_ui();
|
||||
}
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} static final String Invk_SetKeyOnly = "SetKeyOnly", Invk_Print = "Print";
|
||||
final List_adp ordered = List_adp_.new_();
|
||||
@Override public int Count() {return ordered.Count();}
|
||||
public Ordered_hash_base() {}
|
||||
}
|
||||
39
100_core/src/gplx/Ordered_hash_tst.java
Normal file
39
100_core/src/gplx/Ordered_hash_tst.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class Ordered_hash_tst {
|
||||
@Before public void setup() {
|
||||
hash = Ordered_hash_.New();
|
||||
}
|
||||
@Test public void Get_at() {
|
||||
hash.Add("key1", "val1");
|
||||
Tfds.Eq("val1", hash.Get_at(0));
|
||||
}
|
||||
@Test public void iterator() {
|
||||
hash.Add("key2", "val2");
|
||||
hash.Add("key1", "val1");
|
||||
|
||||
List_adp list = List_adp_.new_();
|
||||
for (Object val : hash)
|
||||
list.Add(val);
|
||||
Tfds.Eq("val2", list.Get_at(0));
|
||||
Tfds.Eq("val1", list.Get_at(1));
|
||||
}
|
||||
Ordered_hash hash;
|
||||
}
|
||||
24
100_core/src/gplx/RandomAdp.java
Normal file
24
100_core/src/gplx/RandomAdp.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.util.*;
|
||||
public class RandomAdp {
|
||||
private final Random under;
|
||||
public RandomAdp(Random v) {this.under = v;}
|
||||
public int Next(int max) {return under.nextInt(max);}
|
||||
}
|
||||
30
100_core/src/gplx/RandomAdp_.java
Normal file
30
100_core/src/gplx/RandomAdp_.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.util.*;
|
||||
public class RandomAdp_ implements GfoInvkAble {
|
||||
public static RandomAdp new_() {
|
||||
Random random = new Random(System.currentTimeMillis());
|
||||
return new RandomAdp(random);
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_Next)) return RandomAdp_.new_().Next(m.ReadInt("max"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
} static final String Invk_Next = "Next";
|
||||
public static final RandomAdp_ Gfs = new RandomAdp_();
|
||||
}
|
||||
548
100_core/src/gplx/String_.java
Normal file
548
100_core/src/gplx/String_.java
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import java.lang.*;
|
||||
import gplx.core.strings.*; import gplx.langs.gfs.*; import gplx.core.envs.*;
|
||||
public class String_ implements GfoInvkAble {
|
||||
public static final Class<?> Cls_ref_type = String.class;
|
||||
public static final String Cls_val_name = "str" + "ing";
|
||||
public static final int Find_none = -1, Pos_neg1 = -1;
|
||||
public static final String Null = null, Empty = "", Null_mark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n";
|
||||
public static String cast(Object v) {return (String)v;}
|
||||
public static String as_(Object obj) {return obj instanceof String ? (String)obj : null;}
|
||||
public static String new_a7(byte[] v) {return v == null ? null : new_a7(v, 0, v.length);}
|
||||
public static String new_a7(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "ASCII");
|
||||
}
|
||||
catch (Exception e) {throw Err_.new_exc(e, "core", "unsupported encoding");}
|
||||
}
|
||||
public static String new_u8(byte[] v) {return v == null ? null : new_u8(v, 0, v.length);}
|
||||
public static String new_u8(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "UTF-8");
|
||||
}
|
||||
catch (Exception e) {Err_.Noop(e); throw Err_.new_("core", "unsupported encoding", "bgn", bgn, "end", end);}
|
||||
}
|
||||
public static String new_u8__by_len(byte[] v, int bgn, int len) {
|
||||
int v_len = v.length;
|
||||
if (bgn + len > v_len) len = v_len - bgn;
|
||||
return new_u8(v, bgn, bgn + len);
|
||||
}
|
||||
public static String[] Ary_add(String[]... arys) {
|
||||
if (arys == null) return String_.Ary_empty;
|
||||
int arys_len = arys.length;
|
||||
int rv_len = 0;
|
||||
for (int i = 0; i < arys_len; i++) {
|
||||
String[] ary = arys[i];
|
||||
rv_len += ary.length;
|
||||
}
|
||||
int rv_idx = 0;
|
||||
String[] rv = new String[rv_len];
|
||||
for (int i = 0; i < arys_len; i++) {
|
||||
String[] ary = arys[i];
|
||||
int ary_len = ary.length;
|
||||
for (int j = 0; j < ary_len; j++)
|
||||
rv[rv_idx++] = ary[j];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static boolean Len_gt_0(String s) {return s != null && s.length() > 0;}
|
||||
public static boolean Len_eq_0(String s) {return s == null || s.length() == 0;}
|
||||
public static int Len(String s) {return s.length();}
|
||||
public static String Lower(String s) {return s.toLowerCase();}
|
||||
public static String Upper(String s) {return s.toUpperCase();}
|
||||
public static String CaseNormalize(boolean caseSensitive, String s) {return caseSensitive ? s : String_.Lower(s);}
|
||||
public static String Trim(String s) {return s.trim();}
|
||||
public static String Mid(String s, int bgn) {return s.substring(bgn);}
|
||||
public static String Replace(String s, String find, String replace) {return s.replace(find, replace);}
|
||||
public static char[] XtoCharAry(String s) {return s.toCharArray();}
|
||||
public static char CharAt(String s, int i) {return s.charAt(i);}
|
||||
public static int CodePointAt(String s, int i) {return s.codePointAt(i);}
|
||||
public static boolean Has(String s, String find) {return s.indexOf(find) != String_.Find_none;}
|
||||
public static boolean Has_at_bgn(String s, String v) {return s.startsWith(v);}
|
||||
public static boolean Has_at_end(String s, String v) {return s.endsWith(v);}
|
||||
public static int FindFwd(String s, String find) {return s.indexOf(find);}
|
||||
public static int FindFwd(String s, String find, int pos) {return s.indexOf(find, pos);}
|
||||
public static int FindBwd(String s, String find) {return s.lastIndexOf(find);}
|
||||
public static int FindBwd(String s, String find, int pos) {
|
||||
return s.lastIndexOf(find, pos);
|
||||
}
|
||||
public static int FindBetween(String s, String find, int bgn, int end) {
|
||||
int rv = FindFwd(s, find, bgn);
|
||||
return (rv > end) ? String_.Find_none : rv;
|
||||
}
|
||||
public static int FindAfter(String s, String find, int bgn) {
|
||||
int rv = FindFwd(s, find, bgn);
|
||||
return rv == String_.Find_none ? String_.Find_none : rv + Len(find);
|
||||
}
|
||||
public static int FindAfterRev(String s, String find, int pos) {
|
||||
int rv = FindBwd(s, find, pos);
|
||||
return rv == String_.Find_none ? String_.Find_none : rv + Len(find);
|
||||
}
|
||||
public static int Count(String s, String part) {
|
||||
int count = 0, pos = -1; // -1 b/c first pass must be 0 (see pos + 1 below)
|
||||
do {
|
||||
pos = FindFwd(s, part, pos + 1);
|
||||
if (pos == String_.Find_none) break;
|
||||
count++;
|
||||
} while (true);
|
||||
return count;
|
||||
}
|
||||
public static boolean Eq(String lhs, String rhs) {return lhs == null ? rhs == null : lhs.equals(rhs);}
|
||||
public static boolean EqAny(String lhs, String... rhsAry) {
|
||||
for (int i = 0; i < rhsAry.length; i++)
|
||||
if (Eq(lhs, rhsAry[i])) return true;
|
||||
return false;
|
||||
}
|
||||
public static boolean EqNot(String lhs, String rhs) {return !Object_.Eq(lhs, rhs);}
|
||||
public static boolean EqEmpty(String lhs) {return lhs.equals("");}
|
||||
public static String IfNullOrEmpty(String s, String or) {return s == null || s.length() == 0 ? or : s;}
|
||||
public static int Compare(String lhs, String rhs) {return lhs.compareTo(rhs);} // NOTE: Compare instead of compareTo b/c javafy lowercases compareTo
|
||||
public static int Compare_ignoreCase(String lhs, String rhs) {
|
||||
if (lhs == null && rhs != null) return CompareAble_.Less;
|
||||
else if (lhs != null && rhs == null) return CompareAble_.More;
|
||||
else if (lhs == null && rhs == null) return CompareAble_.Same;
|
||||
else return lhs.compareToIgnoreCase(rhs);
|
||||
//#-
|
||||
/*
|
||||
if (lhs == null && rhs != null) return CompareAble_.Less;
|
||||
else if (lhs != null && rhs == null) return CompareAble_.More;
|
||||
else if (lhs == null && rhs == null) return CompareAble_.Same;
|
||||
else return lhs.compareToIgnoreCase(rhs);
|
||||
*/
|
||||
}
|
||||
public static int Compare_strict(String lhs, String rhs) {
|
||||
int compare = String_.Compare(lhs, rhs);
|
||||
if (compare == CompareAble_.Same) return CompareAble_.Same;
|
||||
else if (compare < CompareAble_.Same) return CompareAble_.Less;
|
||||
else /* (compare > CompareAble_.Same) */ return CompareAble_.More;
|
||||
}
|
||||
public static int Compare_byteAry(String lhs, String rhs) {
|
||||
int lhsLen = lhs.length(), rhsLen = rhs.length();
|
||||
int aryLen = lhsLen < rhsLen ? lhsLen : rhsLen;
|
||||
int[] lhsAry = XtoIntAry(lhs, aryLen), rhsAry = XtoIntAry(rhs, aryLen);
|
||||
for (int i = 0; i < aryLen; i++) {
|
||||
int comp = Int_.Compare(lhsAry[i], rhsAry[i]);
|
||||
if (comp != CompareAble_.Same) return comp;
|
||||
}
|
||||
return Int_.Compare(lhsLen, rhsLen);
|
||||
}
|
||||
public static int[] XtoIntAry(String s, int len) {
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = (int)s.charAt(i);
|
||||
return rv;
|
||||
}
|
||||
public static String Coalesce(String s, String alt) {return Len_eq_0(s) ? alt : s;}
|
||||
public static boolean In(String s, String... ary) {
|
||||
for (String itm : ary)
|
||||
if (String_.Eq(s, itm)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String new_charAry_(char[] ary, int bgn, int len) {return new String(ary, bgn, len);}
|
||||
public static String Mid(String s, int bgn, int end) {
|
||||
try {return Mid_lang(s, bgn, end - bgn);}
|
||||
catch (Exception e) {
|
||||
int len = s == null ? 0 : Len(s);
|
||||
String msg = "";
|
||||
if (s == null) msg = "s is null";
|
||||
else if (bgn > end) msg = "@bgn > @end";
|
||||
else if (bgn < 0 || bgn >= len) msg = "@bgn is invalid";
|
||||
else if (end < 0 || end > len) msg = "@end is invalid";
|
||||
throw Err_.new_exc(e, "core", msg, "s", s, "bgn", bgn, "end", end, "len", len);
|
||||
}
|
||||
}
|
||||
public static String MidByLenSafe(String s, int bgn, int len) {
|
||||
if (bgn + len >= Len(s)) len = Len(s) - bgn;
|
||||
return Mid_lang(s, bgn, len);
|
||||
}
|
||||
public static String MidByLen(String s, int bgn, int len) {return Mid_lang(s, bgn, len);}
|
||||
public static String GetStrBefore(String s, String spr) {
|
||||
int sprPos = String_.FindFwd(s, spr); if (sprPos == String_.Find_none) throw Err_.new_wo_type("could not find spr", "s", s, "spr", spr);
|
||||
return Mid(s, 0, sprPos);
|
||||
}
|
||||
public static String GetStrAfter(String s, String spr) {
|
||||
int sprPos = String_.FindFwd(s, spr); if (sprPos == String_.Find_none) throw Err_.new_wo_type("could not find spr", "s", s, "spr", spr);
|
||||
return Mid(s, sprPos + 1);
|
||||
}
|
||||
public static String LimitToFirst(String s, int len) {
|
||||
if (len < 0) throw Err_.new_invalid_arg("< 0", "len", len);
|
||||
int sLen = Len(s); if (len > sLen) return s;
|
||||
return Mid_lang(s, 0, len);
|
||||
}
|
||||
public static String LimitToLast(String s, int len) {
|
||||
if (len < 0) throw Err_.new_invalid_arg("< 0", "len", len);
|
||||
int sLen = Len(s); if (len > sLen) return s;
|
||||
return Mid_lang(s, sLen - len, len);
|
||||
}
|
||||
public static String DelBgn(String s, int count) {
|
||||
if (count < 0) throw Err_.new_invalid_arg("< 0", "count", count);
|
||||
if (s == null) throw Err_.new_null();
|
||||
int len = Len(s); if (count > len) throw Err_.new_invalid_arg("> @len", "count", count, "len", len);
|
||||
return String_.Mid(s, count);
|
||||
}
|
||||
public static String DelBgnIf(String s, String find) {
|
||||
if (s == null) throw Err_.new_null();
|
||||
if (find == null) throw Err_.new_null();
|
||||
return Has_at_bgn(s, find) ? String_.Mid(s, Len(find)) : s;
|
||||
}
|
||||
public static String DelEnd(String s, int count) {
|
||||
if (count < 0) throw Err_.new_invalid_arg("< 0", "count", count);
|
||||
if (s == null) throw Err_.new_null();
|
||||
int len = Len(s); if (count > len) throw Err_.new_invalid_arg("> len", "count", count, "len", len);
|
||||
return Mid_lang(s, 0, len + -count);
|
||||
}
|
||||
public static String DelEndIf(String s, String find) {
|
||||
if (s == null) throw Err_.new_null();
|
||||
if (find == null) throw Err_.new_null();
|
||||
return Has_at_end(s, find) ? Mid_lang(s, 0, Len(s) - Len(find)) : s;
|
||||
}
|
||||
public static String LowerFirst(String s) {
|
||||
int len = Len(s); if (len == 0) return String_.Empty;
|
||||
String char0 = Lower(Mid_lang(s, 0, 1));
|
||||
return len == 1 ? char0 : char0 + Mid(s, 1);
|
||||
}
|
||||
public static String UpperFirst(String s) {
|
||||
int len = Len(s); if (len == 0) return String_.Empty;
|
||||
String char0 = Upper(Mid_lang(s, 0, 1));
|
||||
return len == 1 ? char0 : char0 + Mid(s, 1);
|
||||
}
|
||||
public static String PadBgn(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, true);}
|
||||
public static String PadEnd(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, false);}
|
||||
@gplx.Internal protected static String Pad(String s, int totalLen, String pad, boolean bgn) {
|
||||
int sLen = Len(s);
|
||||
int padLen = totalLen - sLen; if (padLen < 0) return s;
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
if (!bgn) sb.Add(s);
|
||||
for (int i = 0; i < padLen; i++)
|
||||
sb.Add(pad);
|
||||
if (bgn) sb.Add(s);
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String TrimEnd(String s) {if (s == null) return null;
|
||||
int len = String_.Len(s);
|
||||
if (len == 0) return s;
|
||||
int last = len;
|
||||
for (int i = len; i > 0; i--) {
|
||||
char c = s.charAt(i - 1);
|
||||
last = i;
|
||||
if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (last == len) ? s : Mid_lang(s, 0, last);
|
||||
}
|
||||
public static String Repeat(String s, int count) {
|
||||
if (count < 0) throw Err_.new_wo_type("count cannot be negative", "count", count, "s", s);
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = 0; i < count; i++)
|
||||
sb.Add(s);
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Insert(String s, int pos, String toInsert) {
|
||||
if (pos < 0 || pos >= String_.Len(s)) throw Err_.new_wo_type("String_.Insert failed; pos invalid", "pos", pos, "s", s, "toInsert", toInsert);
|
||||
return s.substring(0, pos) + toInsert + s.substring(pos);
|
||||
}
|
||||
public static String Format(String fmt, Object... args) {return Format_do(fmt, args);}
|
||||
public static String FormatOrEmptyStrIfNull(String fmt, Object arg) {return arg == null ? "" : Format(fmt, arg);}
|
||||
public static String Concat(char... ary) {return new String(ary);}
|
||||
public static String Concat(String s1, String s2, String s3) {return s1 + s2 + s3;}
|
||||
public static String Concat(String... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (String val : ary)
|
||||
sb.Add(val);
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_any(Object... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (Object val : ary)
|
||||
sb.Add_obj(val);
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_with_obj(String separator, Object... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int aryLen = Array_.Len(ary);
|
||||
for (int i = 0; i < aryLen; i++) {
|
||||
if (i != 0) sb.Add(separator);
|
||||
Object val = ary[i];
|
||||
sb.Add_obj(Object_.Xto_str_strict_or_empty(val));
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_with_str(String spr, String... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) sb.Add(spr);
|
||||
sb.Add_obj(ary[i]);
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_lines_crlf(String... values) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (String val : values)
|
||||
sb.Add(val).Add(String_.CrLf);
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_lines_crlf_skipLast(String... values) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (String val : values) {
|
||||
if (sb.Count() != 0) sb.Add(String_.CrLf);
|
||||
sb.Add(val);
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_lines_nl(String... values) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (String val : values)
|
||||
sb.Add(val).Add("\n");
|
||||
return sb.To_str();
|
||||
}
|
||||
public static String Concat_lines_nl_skip_last(String... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int ary_len = ary.length; int ary_end = ary_len - 1;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
sb.Add(ary[i]);
|
||||
if (i != ary_end) sb.Add("\n");
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
|
||||
public static String[] Ary(String... ary) {return ary;}
|
||||
public static String[] Ary_wo_null(String... ary) {
|
||||
List_adp list = List_adp_.new_();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
if (itm == null) continue;
|
||||
list.Add(itm);
|
||||
}
|
||||
return list.To_str_ary();
|
||||
}
|
||||
public static String AryXtoStr(String... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (String s : ary)
|
||||
sb.Add(s).Add(";");
|
||||
return sb.To_str();
|
||||
}
|
||||
public static final String[] Ary_empty = new String[0];
|
||||
public static String[] Split(String raw, char dlm) {return Split(raw, dlm, false);}
|
||||
public static String[] Split(String raw, char dlm, boolean addEmptyIfDlmIsLast) {
|
||||
List_adp list = List_adp_.new_(); String_bldr sb = String_bldr_.new_();
|
||||
int rawLen = String_.Len(raw); char c = '\0';
|
||||
for (int i = 0; i < rawLen; i++) {
|
||||
c = String_.CharAt(raw, i);
|
||||
if (c == dlm) {
|
||||
if (!addEmptyIfDlmIsLast && sb.Count() == 0 && i == rawLen - 1) {}
|
||||
else list.Add(sb.To_str_and_clear());
|
||||
}
|
||||
else
|
||||
sb.Add(c);
|
||||
}
|
||||
if (sb.Count() > 0)
|
||||
list.Add(sb.To_str_and_clear());
|
||||
return list.To_str_ary();
|
||||
}
|
||||
public static String[] Split(String s, String separator) {return Split_do(s, separator, false);}
|
||||
public static String[] SplitLines_crlf(String s) {return Split(s, Op_sys.Wnt.Nl_str());}
|
||||
public static String[] SplitLines_nl(String s) {return Split(s, Op_sys.Lnx.Nl_str());}
|
||||
public static String[] SplitLines_any(String s) {return Split_do(s, Op_sys.Lnx.Nl_str(), true);}
|
||||
public static String[] Split_lang(String s, char c) {return s.split(Character.toString(c));}
|
||||
|
||||
static String Format_do(String s, Object[] ary) {
|
||||
int aryLength = Array_.Len_obj(ary); if (aryLength == 0) return s; // nothing to format
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
char bracketBgn = '{', bracketEnd = '}';
|
||||
String aryVal = null; char c, next;
|
||||
int pos = 0; int textLength = Len(s); String numberStr = ""; boolean bracketsOn = false;
|
||||
while (true) {
|
||||
if (pos == textLength) break;
|
||||
c = CharAt(s, pos);
|
||||
if (bracketsOn) { // mode=bracketsOn
|
||||
if (c == bracketBgn) { // first bracketBgn is fake; add bracketBgn and whatever is in numberStr
|
||||
sb.Add(bracketBgn).Add(numberStr);
|
||||
numberStr = "";
|
||||
}
|
||||
else if (c == bracketEnd) {
|
||||
int aryIdx = Int_.parse_or(numberStr, Int_.Min_value);
|
||||
if (aryIdx != Int_.Min_value && Int_.Between(aryIdx, 0, aryLength - 1)) // check (a) aryIdx is num; (b) aryIdx is in bounds
|
||||
aryVal = Object_.Xto_str_strict_or_empty(ary[aryIdx]);
|
||||
else
|
||||
aryVal = String_.Concat_any(bracketBgn, numberStr, bracketEnd); // not valid, just add String
|
||||
sb.Add(aryVal);
|
||||
bracketsOn = false;
|
||||
numberStr = "";
|
||||
}
|
||||
else // char=anythingElse
|
||||
numberStr += c;
|
||||
}
|
||||
else { // mode=bracketsOff
|
||||
if (c == bracketBgn || c == bracketEnd) {
|
||||
boolean isEnd = pos == textLength - 1;
|
||||
if (isEnd)
|
||||
sb.Add(c);
|
||||
else {
|
||||
next = CharAt(s, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
sb.Add(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
bracketsOn = true;
|
||||
}
|
||||
}
|
||||
else // char=anythingElse
|
||||
sb.Add(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (Len(numberStr) > 0) // unclosed bracket; add bracketBgn and whatever is in numberStr; ex: "{0"
|
||||
sb.Add(bracketBgn).Add(numberStr);
|
||||
return sb.To_str();
|
||||
}
|
||||
static String[] Split_do(String s, String spr, boolean skipChar13) {
|
||||
if (String_.Eq(s, "") // "".Split('a') return array with one member: ""
|
||||
|| String_.Eq(spr, "")) // "a".Split('\0') returns array with one member: "a"
|
||||
return new String[] {s};
|
||||
List_adp list = List_adp_.new_(); String_bldr sb = String_bldr_.new_();
|
||||
int i = 0, sprPos = 0; boolean sprMatched = false; char spr0 = CharAt(spr, 0);
|
||||
int textLength = Len(s); int sprLength = Len(spr);
|
||||
while (true) {
|
||||
if (sprMatched
|
||||
|| i == textLength) { // last pass; add whatever's in sb to list
|
||||
list.Add(sb.To_str_and_clear());
|
||||
if (sprMatched && i == textLength) list.Add(""); // if s ends with spr and last pass, add emptyString as last
|
||||
sprMatched = false;
|
||||
}
|
||||
if (i == textLength) break;
|
||||
char c = CharAt(s, i);
|
||||
if (skipChar13 && c == (char)13) {i++; continue;}
|
||||
if (c == spr0) { // matches first char of spr
|
||||
sprPos = 1;
|
||||
while (true) {
|
||||
if (sprPos == sprLength) { // made it to end, must be match
|
||||
sprMatched = true;
|
||||
break;
|
||||
}
|
||||
if (i + sprPos == textLength) break; // ran out of s; handles partial match at end of String; ab+, +-
|
||||
if (CharAt(s, i + sprPos) != CharAt(spr, sprPos)) break; // no match
|
||||
sprPos++;
|
||||
}
|
||||
if (!sprMatched) // add partial match to sb
|
||||
sb.Add(Mid_lang(s, i, sprPos));
|
||||
i += sprPos;
|
||||
}
|
||||
else { // no spr match; just add char, increment pos
|
||||
sb.Add(c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return (String[])list.To_ary(String.class);
|
||||
}
|
||||
static String Mid_lang(String s, int bgn, int len) {return s.substring(bgn, bgn + len);}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_Replace)) {
|
||||
String s = m.ReadStr(GfsCore_.Arg_primitive), find = m.ReadStr("find"), replace = m.ReadStr("replace");
|
||||
if (ctx.Deny()) return this;
|
||||
return Replace(s, find, replace);
|
||||
}
|
||||
else if (ctx.Match(k, Invk_Len)) {
|
||||
String s = m.ReadStr(GfsCore_.Arg_primitive);
|
||||
if (ctx.Deny()) return this;
|
||||
return Len(s);
|
||||
}
|
||||
else if (ctx.Match(k, Invk_PadBgn)) {
|
||||
String s = m.ReadStr(GfsCore_.Arg_primitive); int totalLen = m.ReadInt("totalLen"); String pad = m.ReadStr("pad");
|
||||
if (ctx.Deny()) return this;
|
||||
return PadBgn(s, totalLen, pad);
|
||||
}
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
} public static final String Invk_Replace = "Replace", Invk_Len = "Len", Invk_PadBgn = "PadBgn";
|
||||
public static final String_ Gfs = new String_();
|
||||
public static String Extract_after_bwd(String src, String dlm) {
|
||||
int dlm_pos = String_.FindBwd(src, dlm); if (dlm_pos == String_.Find_none) return String_.Empty;
|
||||
int src_len = String_.Len(src); if (dlm_pos == src_len - 1) return String_.Empty;
|
||||
return String_.Mid(src, dlm_pos + 1, src_len);
|
||||
}
|
||||
public static String Replace_by_pos(String v, int del_bgn, int del_end, String repl) {
|
||||
return String_.Mid(v, 0, del_bgn) + repl + String_.Mid(v, del_end, String_.Len(v));
|
||||
}
|
||||
public static String read_(Object obj) {// NOTE: same as cast; for consistent readability only
|
||||
String rv = as_(obj);
|
||||
if (rv == null && obj != null) throw Err_.new_type_mismatch(String.class, obj); // NOTE: obj != null needed; EX: cast(null) --> null
|
||||
return rv;
|
||||
}
|
||||
public static String[] Ary(byte[]... ary) {
|
||||
if (ary == null) return String_.Ary_empty;
|
||||
int ary_len = ary.length;
|
||||
String[] rv = new String[ary_len];
|
||||
for (int i = 0; i < ary_len; i++)
|
||||
rv[i] = String_.new_u8(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
public static String [] Ary_filter(String[] src, String[] filter) {
|
||||
Hash_adp hash = Hash_adp_.new_();
|
||||
int len = filter.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String itm = filter[i];
|
||||
hash.Add_if_dupe_use_nth(itm, itm);
|
||||
}
|
||||
List_adp rv = List_adp_.new_();
|
||||
len = src.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String itm = src[i];
|
||||
if (hash.Has(itm)) rv.Add(itm);
|
||||
}
|
||||
return rv.To_str_ary();
|
||||
}
|
||||
public static String[] Ary_flatten(String[][] src_ary) {
|
||||
int trg_len = 0;
|
||||
int src_len = Array_.Len(src_ary);
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
String[] itm = src_ary[i];
|
||||
if (itm != null) trg_len += Array_.Len(itm);
|
||||
}
|
||||
String[] trg_ary = new String[trg_len];
|
||||
trg_len = 0;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
String[] itm = src_ary[i];
|
||||
if (itm == null) continue;
|
||||
int itm_len = Array_.Len(itm);
|
||||
for (int j = 0; j < itm_len; j++)
|
||||
trg_ary[trg_len++] = itm[j];
|
||||
}
|
||||
return trg_ary;
|
||||
}
|
||||
public static String To_str__as_kv_ary(String... ary) {
|
||||
int len = ary.length;
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < len; i+=2) {
|
||||
bfr.Add_str_u8(ary[i]).Add_byte_eq();
|
||||
String val = i + 1 < len ? ary[i + 1] : null;
|
||||
if (val != null) bfr.Add_str_u8(val);
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
}
|
||||
184
100_core/src/gplx/String__tst.java
Normal file
184
100_core/src/gplx/String__tst.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class String__tst {
|
||||
@Test public void Len() {
|
||||
tst_Len("", 0);
|
||||
tst_Len("abc", 3);
|
||||
} void tst_Len(String v, int expd) {Tfds.Eq(expd, String_.Len(v), "Len");}
|
||||
|
||||
@Test public void LimitToFirst() {
|
||||
tst_LimitToFirst("abc", 0, "");
|
||||
tst_LimitToFirst("abc", 1, "a");
|
||||
tst_LimitToFirst("abc", 2, "ab");
|
||||
tst_LimitToFirst("abc", 3, "abc");
|
||||
tst_LimitToFirst("abc", 4, "abc");
|
||||
err_LimitToFirst("abc", -1);
|
||||
}
|
||||
void tst_LimitToFirst(String s, int v, String expd) {Tfds.Eq(expd, String_.LimitToFirst(s, v));}
|
||||
void err_LimitToFirst(String s, int v) {try {String_.LimitToFirst(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void LimitToLast() {
|
||||
tst_LimitToLast("abc", 0, "");
|
||||
tst_LimitToLast("abc", 1, "c");
|
||||
tst_LimitToLast("abc", 2, "bc");
|
||||
tst_LimitToLast("abc", 3, "abc");
|
||||
tst_LimitToLast("abc", 4, "abc");
|
||||
err_LimitToLast("abc", -1);
|
||||
}
|
||||
void tst_LimitToLast(String s, int v, String expd) {Tfds.Eq(expd, String_.LimitToLast(s, v));}
|
||||
void err_LimitToLast(String s, int v) {try {String_.LimitToLast(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void DelBgn() {
|
||||
tst_DelBgn("abc", 0, "abc");
|
||||
tst_DelBgn("abc", 1, "bc");
|
||||
tst_DelBgn("abc", 2, "c");
|
||||
tst_DelBgn("abc", 3, "");
|
||||
err_DelBgn(null, 0);
|
||||
err_DelBgn("abc", 4);
|
||||
}
|
||||
void tst_DelBgn(String s, int v, String expd) {Tfds.Eq(expd, String_.DelBgn(s, v));}
|
||||
void err_DelBgn(String s, int v) {try {String_.DelBgn(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void DelBgnIf() {
|
||||
tst_DelBgnIf("abc", "", "abc");
|
||||
tst_DelBgnIf("abc", "a", "bc");
|
||||
tst_DelBgnIf("abc", "ab", "c");
|
||||
tst_DelBgnIf("abc", "abc", "");
|
||||
tst_DelBgnIf("abc", "abcd", "abc");
|
||||
tst_DelBgnIf("abc", "bcd", "abc");
|
||||
err_DelBgnIf(null, "abc");
|
||||
err_DelBgnIf("abc", null);
|
||||
}
|
||||
void tst_DelBgnIf(String s, String v, String expd) {Tfds.Eq(expd, String_.DelBgnIf(s, v));}
|
||||
void err_DelBgnIf(String s, String v) {try {String_.DelBgnIf(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void DelEnd() {
|
||||
tst_DelEnd("abc", 0, "abc");
|
||||
tst_DelEnd("abc", 1, "ab");
|
||||
tst_DelEnd("abc", 2, "a");
|
||||
tst_DelEnd("abc", 3, "");
|
||||
err_DelEnd(null, 0);
|
||||
err_DelEnd("abc", 4);
|
||||
}
|
||||
void tst_DelEnd(String s, int v, String expd) {Tfds.Eq(expd, String_.DelEnd(s, v));}
|
||||
void err_DelEnd(String s, int v) {try {String_.DelEnd(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void DelEndIf() {
|
||||
tst_DelEndIf("abc", "", "abc");
|
||||
tst_DelEndIf("abc", "c", "ab");
|
||||
tst_DelEndIf("abc", "bc", "a");
|
||||
tst_DelEndIf("abc", "abc", "");
|
||||
tst_DelEndIf("abc", "abcd", "abc");
|
||||
tst_DelEndIf("abc", "ab", "abc");
|
||||
err_DelEndIf(null, "");
|
||||
err_DelEndIf("", null);
|
||||
}
|
||||
void tst_DelEndIf(String s, String v, String expd) {Tfds.Eq(expd, String_.DelEndIf(s, v));}
|
||||
void err_DelEndIf(String s, String v) {try {String_.DelEndIf(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void MidByPos() {
|
||||
tst_MidByPos("abc", 0, 0, "");
|
||||
tst_MidByPos("abc", 0, 1, "a");
|
||||
tst_MidByPos("abc", 0, 2, "ab");
|
||||
tst_MidByPos("abc", 0, 3, "abc");
|
||||
tst_MidByPos("abc", 2, 3, "c");
|
||||
err_MidByPos("abc", 1, 5);
|
||||
// err_MidByPos("abc", 0, 4);
|
||||
}
|
||||
void tst_MidByPos(String s, int bgn, int end, String expd) {Tfds.Eq(expd, String_.Mid(s, bgn, end));}
|
||||
void err_MidByPos(String s, int bgn, int end) {try {String_.Mid(s, bgn, end);} catch (Exception e) {Tfds.Err_classMatch(e, Err.class); return;} Tfds.Fail_expdError();}
|
||||
@Test public void TrimEnd() {
|
||||
tst_TrimEnd("a", "a");
|
||||
tst_TrimEnd("a ", "a");
|
||||
tst_TrimEnd("a\t", "a");
|
||||
tst_TrimEnd("a\n", "a");
|
||||
tst_TrimEnd("a\r", "a");
|
||||
tst_TrimEnd("a\r\n \t", "a");
|
||||
tst_TrimEnd(" a", " a");
|
||||
tst_TrimEnd(null, null);
|
||||
}
|
||||
void tst_TrimEnd(String s, String expd) {Tfds.Eq(expd, String_.TrimEnd(s));}
|
||||
|
||||
@Test public void Count() {
|
||||
String text = "0 0 0";
|
||||
Tfds.Eq(3, String_.Count(text, "0"));
|
||||
}
|
||||
@Test public void Has() {
|
||||
String text = "find word";
|
||||
Tfds.Eq_true(String_.Has(text, "word"));
|
||||
Tfds.Eq_false(String_.Has(text, "nothing"));
|
||||
}
|
||||
@Test public void Repeat() {
|
||||
Tfds.Eq("333", String_.Repeat("3", 3));
|
||||
}
|
||||
@Test public void Format() {
|
||||
tst_Format("", ""); // empty
|
||||
tst_Format("no args", "no args"); // no args
|
||||
tst_Format("0", "{0}", 0); // one
|
||||
tst_Format("0 and 1", "{0} and {1}", 0, 1); // many
|
||||
tst_Format("{", "{{", 0); // escape bracketBgn
|
||||
tst_Format("}", "}}", 0); // escape bracketEnd
|
||||
tst_Format("{a0c}", "{a{0}c}", 0); // nested;
|
||||
tst_Format("{a{b}c}", "{a{b}c}", 0); // invalid invalid
|
||||
tst_Format("{1}", "{1}", 1); // invalid array index
|
||||
tst_Format("{a} {b}", "{a} {b}", 0); // invalid many
|
||||
tst_Format("{a}0{b}1", "{a}{0}{b}{1}", 0, 1); // invalid and valid
|
||||
tst_Format("{0", "{0", 0); // invalid dangling
|
||||
} void tst_Format(String expd, String fmt, Object... ary) {Tfds.Eq(expd, String_.Format(fmt, ary));}
|
||||
@Test public void Split() {
|
||||
tst_Split("ab", " ", "ab"); // no match -> return array with original input
|
||||
tst_Split("ab cd", " ", "ab", "cd"); // separator.length = 1
|
||||
tst_Split("ab+!cd", "+!", "ab", "cd"); // separator.length = 2
|
||||
tst_Split("ab+!cd+!ef", "+!", "ab", "cd", "ef"); // terms = 3
|
||||
tst_Split("ab+!cd+!", "+!", "ab", "cd", ""); // closing separator
|
||||
tst_Split("+!ab", "+!", "", "ab"); // opening separator
|
||||
tst_Split("ab+cd+!ef", "+!", "ab+cd", "ef"); // ignore partial matches
|
||||
tst_Split("ab+!cd+", "+!", "ab", "cd+"); // ignore partial matches; end of String
|
||||
|
||||
// boundary
|
||||
tst_Split("ab", "", "ab"); // separator.length = 0 -> return array with input as only member
|
||||
tst_Split("", " ", ""); // empty input -> return array with empty input
|
||||
|
||||
// acceptance
|
||||
tst_Split("this\r\nis\na\rtest\r\n.", "\r\n", "this", "is\na\rtest", ".");
|
||||
} void tst_Split(String text, String separator, String... expd) {Tfds.Eq_ary(expd, String_.Split(text, separator));}
|
||||
@Test public void Concat_with_obj() {
|
||||
tst_ConcatWith_any("a|b", "|", "a", "b"); // do not append final delimiter
|
||||
tst_ConcatWith_any("a||c", "|", "a", null, "c"); // null
|
||||
tst_ConcatWith_any("a|b", "|", Object_.Ary("a", "b")); // pass array as arg
|
||||
} void tst_ConcatWith_any(String expd, String delimiter, Object... array) {Tfds.Eq(expd, String_.Concat_with_obj(delimiter, array));}
|
||||
@Test public void Compare_byteAry() {
|
||||
tst_Compare_byteAry("a", "a", CompareAble_.Same);
|
||||
tst_Compare_byteAry("a", "b", CompareAble_.Less);
|
||||
tst_Compare_byteAry("b", "a", CompareAble_.More);
|
||||
tst_Compare_byteAry("ab", "ac", CompareAble_.Less);
|
||||
tst_Compare_byteAry("ac", "ab", CompareAble_.More);
|
||||
tst_Compare_byteAry("a", "ab", CompareAble_.Less);
|
||||
tst_Compare_byteAry("ab", "a", CompareAble_.More);
|
||||
tst_Compare_byteAry("101", "1-0-1", CompareAble_.More); // NOTE: regular String_.Compare returns Less in .NET, More in Java
|
||||
tst_Compare_byteAry("1-0-1", "101 (album)", CompareAble_.Less);
|
||||
} void tst_Compare_byteAry(String lhs, String rhs, int expd) {Tfds.Eq(expd, String_.Compare_byteAry(lhs, rhs));}
|
||||
@Test public void FindBwd() { // WORKAROUND.CS:String.LastIndexOf returns -1 for multi-chars;
|
||||
tst_FindRev("abc", "a", 0, 0);
|
||||
tst_FindRev("abc", "ab", 0, 0); // 2 chars
|
||||
tst_FindRev("abc", "abc", 0, 0); // 3 chars
|
||||
tst_FindRev("ab", "abc", 0, -1); // out of index error
|
||||
tst_FindRev("ababab", "ab", 2, 2); // make sure cs implementation doesn't pick up next
|
||||
} void tst_FindRev(String s, String find, int pos, int expd) {Tfds.Eq(expd, String_.FindBwd(s, find, pos));}
|
||||
@Test public void Extract_after_bwd() {
|
||||
Extract_after_bwd_tst("a/b", "/", "b");
|
||||
Extract_after_bwd_tst("a/", "/", "");
|
||||
Extract_after_bwd_tst("a", "/", "");
|
||||
} void Extract_after_bwd_tst(String src, String dlm, String expd) {Tfds.Eq(expd, String_.Extract_after_bwd(src, dlm));}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.consoles.*;
|
||||
import gplx.core.strings.*; import gplx.core.consoles.*; import gplx.core.tests.*;
|
||||
public class Tfds { // URL:doc/gplx.tfds/Tfds.txt
|
||||
public static boolean SkipDb = false;
|
||||
public static void Eq_bool (boolean expd , boolean actl) {Eq_exec_y(expd, actl, "", Object_.Ary_empty);}
|
||||
@@ -31,8 +31,6 @@ public class Tfds { // URL:doc/gplx.tfds/Tfds.txt
|
||||
public static void Eq_str (String expd, String actl, String fmt, Object... args) {Eq_exec_y(expd, actl, fmt, args);}
|
||||
|
||||
public static void Eq(Object expd, Object actl) {Eq_wkr(expd, actl, true, EmptyStr);}
|
||||
public static void Eq_able(EqAble expd, EqAble actl) {Eq_able_wkr(expd, actl, true, EmptyStr);}
|
||||
public static void Eq_able(EqAble expd, EqAble actl, String fmt, Object... args) {Eq_able_wkr(expd, actl, true, String_.Format(fmt, args));}
|
||||
public static void Eq_byte(byte expd, byte actl) {Eq_wkr(expd, actl, true, EmptyStr);}
|
||||
public static void Eq_long(long expd, long actl) {Eq_wkr(expd, actl, true, EmptyStr);}
|
||||
public static void Eq_float(float expd, float actl) {Eq_wkr(expd, actl, true, EmptyStr);}
|
||||
@@ -75,15 +73,6 @@ public class Tfds { // URL:doc/gplx.tfds/Tfds.txt
|
||||
String msg = msgBldr.Eq_xtoStr(lhs, rhs, String_.Format(fmt, args));
|
||||
throw Err_.new_wo_type(msg);
|
||||
}
|
||||
static void Eq_able_wkr(EqAble lhs, EqAble rhs, boolean expd, String customMsg) {
|
||||
boolean actl = false;
|
||||
if (lhs == null && rhs != null) actl = false;
|
||||
else if (lhs != null && rhs == null) actl = false;
|
||||
else actl = lhs.Eq(rhs);
|
||||
if (expd == actl) return;
|
||||
String msg = msgBldr.Eq_xtoStr(lhs, rhs, customMsg);
|
||||
throw Err_.new_wo_type(msg);
|
||||
}
|
||||
static void Eq_wkr(Object lhs, Object rhs, boolean expd, String customMsg) {
|
||||
boolean actl = Object_.Eq(lhs, rhs);
|
||||
if (expd == actl) return;
|
||||
@@ -168,6 +157,7 @@ public class Tfds { // URL:doc/gplx.tfds/Tfds.txt
|
||||
public static void WriteText(String text) {Console_adp__sys.Instance.Write_str(text);}
|
||||
public static void Write(byte[] s, int b, int e) {Write(Bry_.Mid(s, b, e));}
|
||||
public static void Write() {Write("tmp");}
|
||||
public static void Dbg(Object... ary) {Write(ary);}
|
||||
public static void Write(Object... ary) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int aryLen = Array_.Len(ary);
|
||||
|
||||
85
100_core/src/gplx/TimeSpanAdp.java
Normal file
85
100_core/src/gplx/TimeSpanAdp.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*;
|
||||
public class TimeSpanAdp implements CompareAble {
|
||||
public long Fracs() {return fracs;} long fracs; public int FracsAsInt() {return (int)fracs;}
|
||||
public Decimal_adp TotalSecs() {
|
||||
return Decimal_adp_.divide_(fracs, TimeSpanAdp_.Divisors[TimeSpanAdp_.Idx_Sec]);
|
||||
}
|
||||
public Decimal_adp Total_days() {
|
||||
return Decimal_adp_.divide_(fracs, TimeSpanAdp_.Divisors[TimeSpanAdp_.Idx_Hour] * 24);
|
||||
}
|
||||
public int[] Units() {return TimeSpanAdp_.Split_long(fracs, TimeSpanAdp_.Divisors);}
|
||||
public int Units_fracs() {
|
||||
int[] ary = TimeSpanAdp_.Split_long(fracs, TimeSpanAdp_.Divisors);
|
||||
return ary[TimeSpanAdp_.Idx_Frac];
|
||||
}
|
||||
public TimeSpanAdp Add(TimeSpanAdp val) {return new TimeSpanAdp(fracs + val.fracs);}
|
||||
public TimeSpanAdp Add_fracs(long val) {return new TimeSpanAdp(fracs + val);}
|
||||
public TimeSpanAdp Add_unit(int idx, int val) {
|
||||
int[] units = TimeSpanAdp_.Split_long(fracs, TimeSpanAdp_.Divisors);
|
||||
units[idx] += val;
|
||||
int sign = fracs >= 0 ? 1 : -1;
|
||||
long rv = sign * TimeSpanAdp_.Merge_long(units, TimeSpanAdp_.Divisors);
|
||||
return TimeSpanAdp_.fracs_(rv);
|
||||
}
|
||||
public TimeSpanAdp Subtract(TimeSpanAdp val) {return new TimeSpanAdp(fracs - val.fracs);}
|
||||
|
||||
public int compareTo(Object obj) {TimeSpanAdp comp = TimeSpanAdp_.cast(obj); return CompareAble_.Compare_obj(fracs, comp.fracs);}
|
||||
public boolean Eq(Object o) {
|
||||
TimeSpanAdp comp = TimeSpanAdp_.cast(o); if (comp == null) return false;
|
||||
return fracs == comp.fracs;
|
||||
}
|
||||
@Override public String toString() {return To_str(TimeSpanAdp_.Fmt_Default);}
|
||||
@Override public boolean equals(Object obj) {TimeSpanAdp comp = TimeSpanAdp_.cast(obj); return Object_.Eq(fracs, comp.fracs);}
|
||||
@Override public int hashCode() {return super.hashCode();}
|
||||
|
||||
public String To_str() {return TimeSpanAdp_.To_str(fracs, TimeSpanAdp_.Fmt_Default);}
|
||||
public String To_str(String format) {
|
||||
return TimeSpanAdp_.To_str(fracs, format);
|
||||
}
|
||||
public String XtoStrUiAbbrv() {
|
||||
if (fracs == 0) return "0" + UnitAbbrv(0);
|
||||
int[] units = Units();
|
||||
boolean started = false;
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
for (int i = units.length - 1; i > -1; i--) {
|
||||
int unit = units[i];
|
||||
if (!started) {
|
||||
if (unit == 0)
|
||||
continue;
|
||||
else
|
||||
started = true;
|
||||
}
|
||||
if (sb.Count() != 0) sb.Add(" ");
|
||||
sb.Add_obj(unit).Add(UnitAbbrv(i));
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
String UnitAbbrv(int i) {
|
||||
switch (i) {
|
||||
case 0: return "f";
|
||||
case 1: return "s";
|
||||
case 2: return "m";
|
||||
case 3: return "h";
|
||||
default: return "unknown:<" + Int_.To_str(i) + ">";
|
||||
}
|
||||
}
|
||||
@gplx.Internal protected TimeSpanAdp(long fracs) {this.fracs = fracs;}
|
||||
}
|
||||
162
100_core/src/gplx/TimeSpanAdp_.java
Normal file
162
100_core/src/gplx/TimeSpanAdp_.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.envs.*;
|
||||
public class TimeSpanAdp_ {
|
||||
public static final TimeSpanAdp Zero = new TimeSpanAdp(0);
|
||||
public static final TimeSpanAdp Null = new TimeSpanAdp(-1);
|
||||
public static TimeSpanAdp fracs_(long val) {return new TimeSpanAdp(val);}
|
||||
public static TimeSpanAdp seconds_(double seconds) {
|
||||
long fracs = (long)(seconds * Divisors[Idx_Sec]);
|
||||
return new TimeSpanAdp(fracs);
|
||||
}
|
||||
public static TimeSpanAdp decimal_(Decimal_adp seconds) {
|
||||
return new TimeSpanAdp(seconds.To_long_mult_1000());
|
||||
}
|
||||
public static TimeSpanAdp units_(int frc, int sec, int min, int hour) {
|
||||
int[] units = new int[] {frc, sec, min, hour};
|
||||
long fracs = Merge_long(units, TimeSpanAdp_.Divisors);
|
||||
return TimeSpanAdp_.fracs_(fracs);
|
||||
}
|
||||
public static TimeSpanAdp from_(long bgn) {return TimeSpanAdp_.fracs_(Env_.TickCount() - bgn);}
|
||||
public static final long parse_null = Long_.Min_value;
|
||||
public static TimeSpanAdp parse(String raw) {
|
||||
byte[] bry = Bry_.new_u8(raw);
|
||||
long fracs = parse_to_fracs(bry, 0, bry.length, false);
|
||||
return fracs == parse_null ? null : TimeSpanAdp_.fracs_(fracs);
|
||||
}
|
||||
public static long parse_to_fracs(byte[] raw, int bgn, int end, boolean fail_if_ws) {
|
||||
int sign = 1, val_f = 0, val_s = 0, val_m = 0, val_h = 0, colon_pos = 0, unit_val = 0, unit_multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // start from end; fracs should be lowest unit
|
||||
byte b = raw[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:
|
||||
int unit_digit = Byte_ascii.To_a7_int(b);
|
||||
unit_val = (unit_multiple == 1) ? unit_digit : unit_val + (unit_digit * unit_multiple);
|
||||
switch (colon_pos) {
|
||||
case 0: val_s = unit_val; break;
|
||||
case 1: val_m = unit_val; break;
|
||||
case 2: val_h = unit_val; break;
|
||||
default: return parse_null; // only hour:minute:second supported for ':' separator; ':' count should be <= 2
|
||||
}
|
||||
unit_multiple *= 10;
|
||||
break;
|
||||
case Byte_ascii.Dot:
|
||||
double factor = (double)1000 / (double)unit_multiple; // factor is necessary to handle non-standard decimals; ex: .1 -> 100; .00199 -> .001
|
||||
val_f = (int)((double)val_s * factor); // move val_s unit_val to val_f; logic is indirect, b/c of differing inputs: "123" means 123 seconds; ".123" means 123 fractionals
|
||||
val_s = 0;
|
||||
unit_multiple = 1;
|
||||
break;
|
||||
case Byte_ascii.Colon:
|
||||
colon_pos++;
|
||||
unit_multiple = 1;
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
if (i == 0 && unit_val > 0) // only if first char && unit_val > 0
|
||||
sign = -1;
|
||||
break;
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
|
||||
if (fail_if_ws) return parse_null;
|
||||
break;
|
||||
default:
|
||||
return parse_null; // invalid char; return null;
|
||||
}
|
||||
}
|
||||
return sign * (val_f + (val_s * Divisors[1]) + (val_m * Divisors[2]) + (val_h * Divisors[3]));
|
||||
}
|
||||
public static String To_str(long frc, String fmt) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int[] units = Split_long(frc, Divisors);
|
||||
|
||||
if (String_.Eq(fmt, TimeSpanAdp_.Fmt_Short)) {
|
||||
for (int i = Idx_Hour; i > -1; i--) {
|
||||
int val = units[i];
|
||||
if (val == 0 && i == Idx_Hour) continue; // skip hour if 0; ex: 01:02, instead of 00:01:02
|
||||
if (i == Idx_Frac) continue; // skip frac b/c fmt is short
|
||||
if (sb.Count() > 0) // sb already has unit; add delimiter
|
||||
sb.Add(Sprs[i]);
|
||||
if (val < 10) // zeroPad
|
||||
sb.Add("0");
|
||||
sb.Add(Int_.To_str(val));
|
||||
}
|
||||
return sb.To_str_and_clear();
|
||||
}
|
||||
boolean fmt_fracs = !String_.Eq(fmt, TimeSpanAdp_.Fmt_NoFractionals);
|
||||
boolean fmt_padZeros = String_.Eq(fmt, TimeSpanAdp_.Fmt_PadZeros);
|
||||
if (frc == 0) return fmt_padZeros ? "00:00:00.000" : "0";
|
||||
|
||||
int[] padZerosAry = ZeroPadding;
|
||||
boolean first = true;
|
||||
String dlm = "";
|
||||
int zeros = 0;
|
||||
if (frc < 0) sb.Add("-"); // negative sign
|
||||
for (int i = Idx_Hour; i > -1; i--) { // NOTE: "> Idx_Frac" b/c frc will be handled below
|
||||
int val = units[i];
|
||||
if (i == Idx_Frac // only write fracs...
|
||||
&& !(val == 0 && fmt_padZeros) // ... if val == 0 && fmt is PadZeros
|
||||
&& !(val != 0 && fmt_fracs) // ... or val != 0 && fmt is PadZeros or Default
|
||||
) continue;
|
||||
if (first && val == 0 && !fmt_padZeros) continue; // if first and val == 0, don't full pad (avoid "00:")
|
||||
zeros = first && !fmt_padZeros ? 1 : padZerosAry[i]; // if first, don't zero pad (avoid "01")
|
||||
dlm = first ? "" : Sprs[i]; // if first, don't use dlm (avoid ":01")
|
||||
sb.Add(dlm);
|
||||
sb.Add(Int_.To_str_pad_bgn_zero(val, zeros));
|
||||
first = false;
|
||||
}
|
||||
return sb.To_str();
|
||||
}
|
||||
@gplx.Internal protected static int[] Split_long(long fracs, int[] divisors) {
|
||||
int divLength = Array_.Len(divisors);
|
||||
int[] rv = new int[divLength];
|
||||
long cur = Math_.Abs(fracs);
|
||||
for (int i = divLength - 1; i > -1; i--) {
|
||||
int divisor = divisors[i];
|
||||
long factor = cur / divisor;
|
||||
rv[i] = (int)factor;
|
||||
cur -= (factor * divisor);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@gplx.Internal protected static long Merge_long(int[] vals, int[] divisors) {
|
||||
long rv = 0; int valLength = Array_.Len(vals);
|
||||
for (int i = 0; i < valLength; i++) {
|
||||
rv += vals[i] * divisors[i];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final String Fmt_PadZeros = "00:00:00.000"; // u,h00:m00:s00.f000
|
||||
public static final String Fmt_Short = "short"; // u,h##:m#0:s00;
|
||||
public static final String Fmt_Default = "0.000"; // v,#.000
|
||||
public static final String Fmt_NoFractionals = "0"; // v,#
|
||||
@gplx.Internal protected static final int[] Divisors = {
|
||||
1, //1 fracs
|
||||
1000, //1,000 fracs in a second
|
||||
60000, //60,000 fracs in a minute (60 seconds * 1,000)
|
||||
3600000, //3,600,000 fracs in an hour (60 minutes * 60,000)
|
||||
};
|
||||
public static final String MajorDelimiter = ":";
|
||||
@gplx.Internal protected static final int Idx_Frac = 0;
|
||||
@gplx.Internal protected static final int Idx_Sec = 1;
|
||||
@gplx.Internal protected static final int Idx_Min = 2;
|
||||
@gplx.Internal protected static final int Idx_Hour = 3;
|
||||
static int[] ZeroPadding = {3, 2, 2, 2,};
|
||||
static String[] Sprs = {".", MajorDelimiter, MajorDelimiter, "",};
|
||||
public static TimeSpanAdp cast(Object arg) {try {return (TimeSpanAdp)arg;} catch(Exception exc) {throw Err_.new_type_mismatch_w_exc(exc, TimeSpanAdp.class, arg);}}
|
||||
public static final double Ratio_f_to_s = 1000;
|
||||
}
|
||||
54
100_core/src/gplx/TimeSpanAdp__parse_tst.java
Normal file
54
100_core/src/gplx/TimeSpanAdp__parse_tst.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class TimeSpanAdp__parse_tst {
|
||||
@Test public void Zero() {
|
||||
tst_Parse("0", 0);
|
||||
}
|
||||
@Test public void Milliseconds() {
|
||||
tst_Parse("0.987", 987);
|
||||
tst_Parse("0.00199", 1); // do not parse as 199
|
||||
tst_Parse("0.1", 100); // do not parse as 1
|
||||
}
|
||||
@Test public void Seconds() {
|
||||
tst_Parse("1.987", 1987);
|
||||
}
|
||||
@Test public void Minutes() {
|
||||
tst_Parse("1:02.987", 62987);
|
||||
}
|
||||
@Test public void MinuteSecondOnly() {
|
||||
tst_Parse("1:02", 62000);
|
||||
}
|
||||
@Test public void Hour() {
|
||||
tst_Parse("1:02:03.987", 3723987);
|
||||
}
|
||||
@Test public void Negative() {
|
||||
tst_Parse("-1:02:03.987", -3723987);
|
||||
}
|
||||
@Test public void Loopholes() {
|
||||
tst_Parse("001:02", 62000); // multiple leading zeroes
|
||||
tst_Parse("1.2.3.4", 1200); // ignore all decimals except first
|
||||
tst_Parse("60:60.9999", 3660999); // value does not need to be bounded to limits (except fracs, which is always < 1000)
|
||||
tst_Parse(" 01 : 02 : 03 . 987", 3723987); // whitespace
|
||||
}
|
||||
void tst_Parse(String text, long expd) {
|
||||
TimeSpanAdp val = TimeSpanAdp_.parse(text);
|
||||
Tfds.Eq(expd, val.Fracs());
|
||||
}
|
||||
}
|
||||
87
100_core/src/gplx/TimeSpanAdp_basic_tst.java
Normal file
87
100_core/src/gplx/TimeSpanAdp_basic_tst.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class TimeSpanAdp_basic_tst {
|
||||
@Test public void seconds_() {
|
||||
TimeSpanAdp expd = TimeSpanAdp_.fracs_(123987);
|
||||
TimeSpanAdp actl = TimeSpanAdp_.seconds_(123.987);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
@Test public void TotalSecs() {
|
||||
TimeSpanAdp val = TimeSpanAdp_.fracs_(1987);
|
||||
Tfds.Eq_decimal(Decimal_adp_.parts_(1, 987), val.TotalSecs());
|
||||
}
|
||||
@Test public void Units() {
|
||||
tst_Units("01:02:03.987", 1, 2, 3, 987);
|
||||
tst_Units("01:00:03", 1, 0, 3, 0);
|
||||
tst_Units("01:00:00.987", 1, 0, 0, 987);
|
||||
tst_Units("02:00.987", 0, 2, 0, 987);
|
||||
}
|
||||
@Test public void Add() {
|
||||
TimeSpanAdp val = TimeSpanAdp_.fracs_(3);
|
||||
TimeSpanAdp arg = TimeSpanAdp_.fracs_(2);
|
||||
TimeSpanAdp expd = TimeSpanAdp_.fracs_(5);
|
||||
TimeSpanAdp actl = val.Add(arg);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
@Test public void Subtract() {
|
||||
TimeSpanAdp val = TimeSpanAdp_.fracs_(3);
|
||||
TimeSpanAdp arg = TimeSpanAdp_.fracs_(2);
|
||||
TimeSpanAdp expd = TimeSpanAdp_.fracs_(1);
|
||||
TimeSpanAdp actl = val.Subtract(arg);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
@Test public void Add_unit_identity() {
|
||||
tst_AddUnit("00:00:01.000", 0, 0, "00:00:01.000");
|
||||
}
|
||||
@Test public void Add_unit_basic() {
|
||||
tst_AddUnit("01:59:58.987", 0, 1013, "02:00:00.000");
|
||||
tst_AddUnit("01:59:58.987", 1, 2, "02:00:00.987");
|
||||
tst_AddUnit("01:59:58.987", 2, 1, "02:00:58.987");
|
||||
tst_AddUnit("01:59:58.987", 3, 1, "02:59:58.987");
|
||||
}
|
||||
@Test public void Add_unit_negative() {
|
||||
tst_AddUnit("01:00:00.00", 0, -1, "00:59:59.999");
|
||||
tst_AddUnit("01:00:00.00", 1, -1, "00:59:59.000");
|
||||
tst_AddUnit("01:00:00.00", 2, -1, "00:59:00.000");
|
||||
tst_AddUnit("01:00:00.00", 3, -1, "00:00:00.000");
|
||||
}
|
||||
@Test public void XtoStrUiAbbrv() {
|
||||
tst_XtoStrUiAbbrv("01:02:03.004", "1h 2m 3s 4f");
|
||||
tst_XtoStrUiAbbrv("00:00:03.004", "3s 4f");
|
||||
tst_XtoStrUiAbbrv("00:00:03.000", "3s 0f");
|
||||
tst_XtoStrUiAbbrv("11:22:33.444", "11h 22m 33s 444f");
|
||||
tst_XtoStrUiAbbrv("00:00:00.000", "0f");
|
||||
} void tst_XtoStrUiAbbrv(String raw, String expd) {Tfds.Eq(expd, TimeSpanAdp_.parse(raw).XtoStrUiAbbrv());}
|
||||
void tst_AddUnit(String valRaw, int unitIdx, int delta, String expdRaw) {
|
||||
TimeSpanAdp val = TimeSpanAdp_.parse(valRaw);
|
||||
TimeSpanAdp actl = val.Add_unit(unitIdx, delta);
|
||||
Tfds.Eq(TimeSpanAdp_.parse(expdRaw), actl);
|
||||
}
|
||||
void tst_Units(String text, int... expd) {
|
||||
TimeSpanAdp val = TimeSpanAdp_.parse(text);
|
||||
int hour = 0, min = 0, sec = 0, frac = 0;
|
||||
int[] ary = val.Units();
|
||||
hour = ary[TimeSpanAdp_.Idx_Hour]; min = ary[TimeSpanAdp_.Idx_Min]; sec = ary[TimeSpanAdp_.Idx_Sec]; frac = ary[TimeSpanAdp_.Idx_Frac];
|
||||
Tfds.Eq(expd[0], hour);
|
||||
Tfds.Eq(expd[1], min);
|
||||
Tfds.Eq(expd[2], sec);
|
||||
Tfds.Eq(expd[3], frac);
|
||||
}
|
||||
}
|
||||
59
100_core/src/gplx/TimeSpanAdp_xtoStr_tst.java
Normal file
59
100_core/src/gplx/TimeSpanAdp_xtoStr_tst.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*;
|
||||
public class TimeSpanAdp_xtoStr_tst {
|
||||
@Test public void Zero() {
|
||||
tst_Default(0, "0");
|
||||
}
|
||||
@Test public void MinuteSeconds() {
|
||||
tst_Default(77000, "1:17");
|
||||
}
|
||||
@Test public void ZeroSuppression() {
|
||||
tst_Default(660000, "11:00"); //fractional 0 and leading 0s are suppressed; i.e.: not 00:11:00.000
|
||||
}
|
||||
@Test public void HourTest() {
|
||||
tst_Default(3723987, "1:02:03.987");
|
||||
}
|
||||
@Test public void NegSeconds() {
|
||||
tst_Default(-2000, "-2");
|
||||
}
|
||||
@Test public void NegMins() {
|
||||
tst_Default(-60000, "-1:00");
|
||||
}
|
||||
@Test public void NegHours() {
|
||||
tst_Default(-3723981, "-1:02:03.981");
|
||||
}
|
||||
@Test public void ZeroPadding() {
|
||||
tst_ZeroPadding("0", "00:00:00.000");
|
||||
tst_ZeroPadding("1:02:03.123", "01:02:03.123");
|
||||
tst_ZeroPadding("1", "00:00:01.000");
|
||||
tst_ZeroPadding(".987", "00:00:00.987");
|
||||
tst_ZeroPadding("2:01.456", "00:02:01.456");
|
||||
}
|
||||
void tst_Default(long fractionals, String expd) {
|
||||
TimeSpanAdp ts = TimeSpanAdp_.fracs_(fractionals);
|
||||
String actl = ts.To_str(TimeSpanAdp_.Fmt_Default);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
void tst_ZeroPadding(String val, String expd) {
|
||||
TimeSpanAdp timeSpan = TimeSpanAdp_.parse(val);
|
||||
String actl = timeSpan.To_str(TimeSpanAdp_.Fmt_PadZeros);
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
}
|
||||
27
100_core/src/gplx/Url_encoder_interface.java
Normal file
27
100_core/src/gplx/Url_encoder_interface.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public interface Url_encoder_interface {
|
||||
String Encode_str(String v);
|
||||
byte[] Encode_bry(String v);
|
||||
}
|
||||
class Url_encoder_interface_same implements Url_encoder_interface {
|
||||
public String Encode_str(String v) {return v;}
|
||||
public byte[] Encode_bry(String v) {return Bry_.new_u8(v);}
|
||||
public static final Url_encoder_interface_same Instance = new Url_encoder_interface_same(); Url_encoder_interface_same() {}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.stores.*;
|
||||
public class Yn {
|
||||
public static final String Y = "y", N = "n";
|
||||
public static boolean parse_by_char_or(String v, boolean or) {
|
||||
|
||||
44
100_core/src/gplx/core/brys/Bry_bfr_mkr.java
Normal file
44
100_core/src/gplx/core/brys/Bry_bfr_mkr.java
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.brys; import gplx.*; import gplx.core.*;
|
||||
public class Bry_bfr_mkr {
|
||||
private final Bry_bfr_mkr_mgr mkr_b128 = new Bry_bfr_mkr_mgr(Tid_b128, 128);
|
||||
public Bry_bfr Get_b128() {return mkr_b128.Get();}
|
||||
public Bry_bfr Get_b512() {return mkr_b512.Get();} private final Bry_bfr_mkr_mgr mkr_b512 = new Bry_bfr_mkr_mgr(Tid_b512, 512);
|
||||
public Bry_bfr Get_k004() {return mkr_k004.Get();} private final Bry_bfr_mkr_mgr mkr_k004 = new Bry_bfr_mkr_mgr(Tid_k004, 4 * Io_mgr.Len_kb);
|
||||
public Bry_bfr Get_m001() {return mkr_m001.Get();} private final Bry_bfr_mkr_mgr mkr_m001 = new Bry_bfr_mkr_mgr(Tid_m001, 1 * Io_mgr.Len_mb);
|
||||
public void Rls(Bry_bfr v) {v.Mkr_rls();}
|
||||
public void Clear() {
|
||||
for (byte i = Tid_b128; i <= Tid_m001; i++)
|
||||
mkr(i).Clear();
|
||||
}
|
||||
public void Clear_fail_check() {
|
||||
for (byte i = Tid_b128; i <= Tid_m001; i++)
|
||||
mkr(i).Clear_fail_check();
|
||||
}
|
||||
private Bry_bfr_mkr_mgr mkr(byte tid) {
|
||||
switch (tid) {
|
||||
case Tid_b128: return mkr_b128;
|
||||
case Tid_b512: return mkr_b512;
|
||||
case Tid_k004: return mkr_k004;
|
||||
case Tid_m001: return mkr_m001;
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
public static final byte Tid_b128 = 0, Tid_b512 = 1, Tid_k004 = 2, Tid_m001 = 3;
|
||||
}
|
||||
100
100_core/src/gplx/core/brys/Bry_bfr_mkr_mgr.java
Normal file
100
100_core/src/gplx/core/brys/Bry_bfr_mkr_mgr.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.brys; import gplx.*; import gplx.core.*;
|
||||
public class Bry_bfr_mkr_mgr {
|
||||
private final Object thread_lock = new Object();
|
||||
private Bry_bfr[] used = Bry_bfr_.Ary_empty; private int used_len = 0, used_max = 0;
|
||||
private int[] free; private int free_len; private int reset;
|
||||
public Bry_bfr_mkr_mgr(byte mgr_id, int reset) {// NOTE: random IndexOutOfBounds errors in Get around free[--free_len] with free_len being -1; put member variable initialization within thread_lock to try to avoid; DATE:2014-09-21
|
||||
this.mgr_id = mgr_id;
|
||||
this.reset = reset;
|
||||
this.free = Int_.Ary_empty;
|
||||
this.free_len = 0;
|
||||
}
|
||||
public byte Mgr_id() {return mgr_id;} private byte mgr_id;
|
||||
public Bry_bfr Get() {
|
||||
synchronized (thread_lock) {
|
||||
Bry_bfr rv = null; int rv_idx = -1;
|
||||
if (free_len > 0) {
|
||||
try {rv_idx = free[--free_len];} catch (Exception e) {throw Err_.new_exc(e, "core", "failed to get free", "idx", free_len, "free_len", free.length);}
|
||||
try {rv = used[rv_idx];} catch (Exception e) {throw Err_.new_exc(e, "core", "failed to get used", "idx", rv_idx, "used_len", used.length);}
|
||||
}
|
||||
else {
|
||||
if (used_len == used_max) Expand();
|
||||
rv_idx = used_len++;
|
||||
rv = used[rv_idx];
|
||||
if (rv == null) {
|
||||
rv = Bry_bfr.reset_(reset);
|
||||
used[rv_idx] = rv;
|
||||
}
|
||||
}
|
||||
rv.Mkr_init(this, rv_idx);
|
||||
return rv.Clear(); // NOTE: ALWAYS call Clear when doing Get. caller may forget to call Clear, and reused bfr may have leftover bytes. unit tests will not catch, and difficult to spot in app
|
||||
}
|
||||
}
|
||||
public void Rls(int idx) {
|
||||
synchronized (thread_lock) {
|
||||
if (idx == -1) throw Err_.new_wo_type("rls called on bfr that was not created by factory");
|
||||
int new_used_len = used_len - 1;
|
||||
if (idx == new_used_len)
|
||||
used_len = new_used_len;
|
||||
else
|
||||
free[free_len++] = idx;
|
||||
}
|
||||
}
|
||||
public void Clear_fail_check() {
|
||||
synchronized (thread_lock) {
|
||||
for (int i = 0; i < used_max; i++) {
|
||||
Bry_bfr itm = used[i];
|
||||
if (itm != null) {
|
||||
if (!itm.Mkr_idx_is_null()) throw Err_.new_wo_type("failed to clear bfr", "idx", Int_.To_str(i));
|
||||
itm.Clear();
|
||||
}
|
||||
used[i] = null;
|
||||
}
|
||||
used = Bry_bfr_.Ary_empty;
|
||||
free = Int_.Ary_empty;
|
||||
free_len = used_len = used_max = 0;
|
||||
}
|
||||
}
|
||||
public void Clear() {
|
||||
synchronized (thread_lock) {
|
||||
for (int i = 0; i < used_max; i++) {
|
||||
Bry_bfr itm = used[i];
|
||||
if (itm != null) itm.Clear();
|
||||
used[i] = null;
|
||||
}
|
||||
used = Bry_bfr_.Ary_empty;
|
||||
free = Int_.Ary_empty;
|
||||
free_len = 0;
|
||||
used_len = used_max = 0;
|
||||
}
|
||||
}
|
||||
@gplx.Internal protected Bry_bfr[] Used() {return used;}
|
||||
@gplx.Internal protected int Used_len() {return used_len;}
|
||||
private void Expand() {
|
||||
int new_max = used_max == 0 ? 2 : used_max * 2;
|
||||
Bry_bfr[] new_ary = new Bry_bfr[new_max];
|
||||
Array_.Copy_to(used, 0, new_ary, 0, used_max);
|
||||
used = new_ary;
|
||||
used_max = new_max;
|
||||
int[] new_free = new int[used_max];
|
||||
Array_.Copy_to(free, 0, new_free, 0, free_len);
|
||||
free = new_free;
|
||||
}
|
||||
}
|
||||
57
100_core/src/gplx/core/brys/Bry_bfr_mkr_tst.java
Normal file
57
100_core/src/gplx/core/brys/Bry_bfr_mkr_tst.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.brys; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*;
|
||||
public class Bry_bfr_mkr_tst {
|
||||
private final Bry_bfr_mkr_fxt fxt = new Bry_bfr_mkr_fxt();
|
||||
@Before public void setup() {fxt.Clear();}
|
||||
@Test public void Get_1() {fxt.Clear().Get().Test__used(0);}
|
||||
@Test public void Get_2() {fxt.Clear().Get().Get().Test__used(0, 1);}
|
||||
@Test public void Get_3() {fxt.Clear().Get().Get().Get().Test__used(0, 1, 2);}
|
||||
@Test public void Rls() {fxt.Clear().Get().Rls(0).Test__used();}
|
||||
@Test public void Rls_skip_1() {
|
||||
fxt.Clear().Get().Get().Rls(0).Test__used(-1, 1);
|
||||
fxt.Get().Test__used(0, 1);
|
||||
}
|
||||
@Test public void Rls_skip_2_1() {
|
||||
fxt.Clear().Get().Get().Get().Rls(1).Rls(0).Test__used(-1, -1, 2);
|
||||
fxt.Get().Test__used(0, -1, 2);
|
||||
fxt.Get().Test__used(0, 1, 2);
|
||||
fxt.Get().Test__used(0, 1, 2, 3);
|
||||
}
|
||||
@Test public void Get_rls_get() { // PURPOSE: defect in which last rls failed b/c was not doing ++ if rv existed
|
||||
fxt.Clear().Get().Rls(0).Get().Get().Rls(1).Rls(0).Test__used();
|
||||
}
|
||||
}
|
||||
class Bry_bfr_mkr_fxt {
|
||||
private final Bry_bfr_mkr_mgr mkr = new Bry_bfr_mkr_mgr(Byte_.Zero, 32);
|
||||
public Bry_bfr_mkr_fxt Clear() {mkr.Clear(); return this;}
|
||||
public Bry_bfr_mkr_fxt Get() {mkr.Get(); return this;}
|
||||
public Bry_bfr_mkr_fxt Rls(int i) {mkr.Used()[i].Mkr_rls(); return this;}
|
||||
public Bry_bfr_mkr_fxt Test__used(int... expd) {
|
||||
int actl_len = mkr.Used_len();
|
||||
int[] actl = new int[actl_len];
|
||||
for (int i = 0; i < actl_len; i++) {
|
||||
Bry_bfr bfr = mkr.Used()[i];
|
||||
int actl_val = bfr == null ? -2 : bfr.Mkr_idx();
|
||||
actl[i] = actl_val;
|
||||
}
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
169
100_core/src/gplx/core/brys/Bry_rdr_old.java
Normal file
169
100_core/src/gplx/core/brys/Bry_rdr_old.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.brys; import gplx.*; import gplx.core.*;
|
||||
public class Bry_rdr_old {
|
||||
private byte[] scope = Bry_.Empty;
|
||||
public byte[] Src() {return src;} protected byte[] src;
|
||||
public int Src_len() {return src_len;} protected int src_len;
|
||||
public void Init(byte[] src) {this.Init(Bry_.Empty, src, 0);}
|
||||
public void Init(byte[] src, int pos) {this.Init(Bry_.Empty, src, pos);}
|
||||
public void Init(byte[] scope, byte[] src, int pos) {
|
||||
this.src = src; this.src_len = src.length; this.pos = pos;
|
||||
this.scope = scope;
|
||||
}
|
||||
public int Pos() {return pos;} public Bry_rdr_old Pos_(int v) {this.pos = v; return this;} protected int pos;
|
||||
public void Pos_add(int v) {pos += v;}
|
||||
public boolean Pos_is_eos() {return pos == src_len;}
|
||||
public boolean Pos_is_reading() {return pos < src_len;}
|
||||
public void Pos_add_one() {++pos;}
|
||||
public int Or_int() {return or_int;} public void Or_int_(int v) {or_int = v;} private int or_int = Int_.Min_value;
|
||||
public byte[] Or_bry() {return or_bry;} public void Or_bry_(byte[] v) {or_bry = v;} private byte[] or_bry;
|
||||
public int Find_fwd(byte find) {return Bry_find_.Find_fwd(src, find, pos);}
|
||||
public int Find_fwd_ws() {return Bry_find_.Find_fwd_until_ws(src, pos, src_len);}
|
||||
public int Find_fwd__pos_at_lhs(byte[] find_bry) {return Find_fwd__pos_at(find_bry, Bool_.N);}
|
||||
public int Find_fwd__pos_at_rhs(byte[] find_bry) {return Find_fwd__pos_at(find_bry, Bool_.Y);}
|
||||
public int Find_fwd__pos_at(byte[] find_bry, boolean pos_at_rhs) {
|
||||
int find_pos = Bry_find_.Find_fwd(src, find_bry, pos, src_len);
|
||||
if (pos_at_rhs) find_pos += find_bry.length;
|
||||
if (find_pos != Bry_find_.Not_found) pos = find_pos;
|
||||
return find_pos;
|
||||
}
|
||||
public byte Read_byte() {return src[pos];}
|
||||
public int Read_int_to_semic() {return Read_int_to(Byte_ascii.Semic);}
|
||||
public int Read_int_to_comma() {return Read_int_to(Byte_ascii.Comma);}
|
||||
public int Read_int_to_pipe() {return Read_int_to(Byte_ascii.Pipe);}
|
||||
public int Read_int_to_nl() {return Read_int_to(Byte_ascii.Nl);}
|
||||
public int Read_int_to_quote() {return Read_int_to(Byte_ascii.Quote);}
|
||||
public int Read_int_to_non_num(){return Read_int_to(Byte_ascii.Null);}
|
||||
public int Read_int_to(byte to_char) {
|
||||
int bgn = pos;
|
||||
int rv = 0;
|
||||
int negative = 1;
|
||||
while (pos < src_len) {
|
||||
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:
|
||||
rv = (rv * 10) + (b - Byte_ascii.Num_0);
|
||||
break;
|
||||
case Byte_ascii.Dash:
|
||||
if (negative == -1) // 2nd negative
|
||||
return or_int; // return or_int
|
||||
else // 1st negative
|
||||
negative = -1; // flag negative
|
||||
break;
|
||||
default: {
|
||||
boolean match = b == to_char;
|
||||
if (to_char == Byte_ascii.Null) {// hack for Read_int_to_non_num
|
||||
--pos;
|
||||
match = true;
|
||||
}
|
||||
return match ? rv * negative : or_int;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bgn == pos ? or_int : rv * negative;
|
||||
}
|
||||
public byte[] Read_bry_to_nl() {return Read_bry_to(Byte_ascii.Nl);}
|
||||
public byte[] Read_bry_to_semic() {return Read_bry_to(Byte_ascii.Semic);}
|
||||
public byte[] Read_bry_to_pipe() {return Read_bry_to(Byte_ascii.Pipe);}
|
||||
public byte[] Read_bry_to_quote() {return Read_bry_to(Byte_ascii.Quote);}
|
||||
public byte[] Read_bry_to_apos() {return Read_bry_to(Byte_ascii.Apos);}
|
||||
public byte[] Read_bry_to(byte to_char) {
|
||||
int bgn = pos;
|
||||
while (pos < src_len) {
|
||||
byte b = src[pos];
|
||||
if (b == to_char)
|
||||
return Bry_.Mid(src, bgn, pos++);
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
return bgn == pos ? or_bry : Bry_.Mid(src, bgn, src_len);
|
||||
}
|
||||
public boolean Read_yn_to_pipe() {return Read_byte_to_pipe() == Byte_ascii.Ltr_y;}
|
||||
public byte Read_byte_to_pipe() {
|
||||
byte rv = src[pos];
|
||||
pos += 2; // 1 for byte; 1 for pipe;
|
||||
return rv;
|
||||
}
|
||||
public double Read_double_to_pipe() {return Read_double_to(Byte_ascii.Pipe);}
|
||||
public double Read_double_to(byte to_char) {
|
||||
byte[] double_bry = Read_bry_to(to_char);
|
||||
return Double_.parse(String_.new_a7(double_bry)); // double will never have utf8
|
||||
}
|
||||
@gplx.Virtual public Bry_rdr_old Skip_ws() {
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: case Byte_ascii.Space:
|
||||
++pos;
|
||||
break;
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Bry_rdr_old Skip_alpha_num_under() {
|
||||
while (pos < src_len) {
|
||||
switch (src[pos]) {
|
||||
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:
|
||||
case Byte_ascii.Underline:
|
||||
++pos;
|
||||
break;
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Chk_bry_or_fail(byte[] bry) {
|
||||
int bry_len = bry.length;
|
||||
boolean match = Bry_.Match(src, pos, pos + bry_len, bry);
|
||||
if (match) pos += bry_len;
|
||||
else throw Err_.new_wo_type("bry.rdr:chk failed", "bry", bry, "pos", pos);
|
||||
}
|
||||
public void Chk_byte_or_fail(byte b) {
|
||||
boolean match = pos < src_len ? src[pos] == b : false;
|
||||
if (match) ++pos;
|
||||
else throw Err_.new_wo_type("bry.rdr:chk failed", "byte", b, "pos", pos);
|
||||
}
|
||||
public byte[] Mid_by_len_safe(int len) {
|
||||
int end = pos + len; if (end > src_len) end = src_len;
|
||||
return Bry_.Mid(src, pos, end);
|
||||
}
|
||||
public boolean Chk_bry_wo_move(byte[] bry, int pos) {
|
||||
int bry_len = bry.length;
|
||||
return Bry_.Match(src, pos, pos + bry_len, bry);
|
||||
}
|
||||
public int Warn(String err, int bgn, int rv) {
|
||||
int end = rv + 256; if (end > src_len) end = src_len;
|
||||
Gfo_usr_dlg_.Instance.Warn_many("", "", "read failed: scope=~{0} err=~{1} mid=~{2}", scope, err, String_.new_u8(src, bgn, end));
|
||||
return rv + 1; // rv is always hook_bgn; add +1 to set at next character, else infinite loop
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.brys.args; import gplx.*; import gplx.core.*; import gplx.core.brys.*;
|
||||
public class Bfr_arg__bry extends gplx.core.brys.Bfr_arg_base {
|
||||
private final byte[] bry;
|
||||
private byte[] bry;
|
||||
public Bfr_arg__bry(byte[] v) {this.bry = v;}
|
||||
public void Set(byte[] v) {this.bry = v;}
|
||||
@Override public void Bfr_arg__add(Bry_bfr bfr) {bfr.Add(bry);}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.consoles; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.envs.*;
|
||||
public class Console_adp__sys implements Console_adp {
|
||||
private String tmp_txt;
|
||||
public Console_adp__sys() {
|
||||
|
||||
@@ -15,20 +15,20 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.threads.*;
|
||||
public class Env_ {
|
||||
public static void Init(String[] args, String appNameAndExt, Class<?> type) {
|
||||
mode_testing = false;
|
||||
mode_debug = String_.In("GPLX_DEBUG_MODE_ENABLED", args);
|
||||
appArgs = args;
|
||||
appUrl = JarAdp_.Url_type(type).OwnerDir().GenSubFil(appNameAndExt);
|
||||
appUrl = Jar_adp_.Url_type(type).OwnerDir().GenSubFil(appNameAndExt);
|
||||
}
|
||||
public static void Init_swt(String[] args, Class<?> type) { // DATE:2014-06-23
|
||||
mode_testing = false;
|
||||
mode_debug = String_.In("GPLX_DEBUG_MODE_ENABLED", args);
|
||||
appArgs = args;
|
||||
appUrl = JarAdp_.Url_type(type);
|
||||
appUrl = Jar_adp_.Url_type(type);
|
||||
}
|
||||
public static void Init_drd() {
|
||||
mode_testing = mode_debug = false;
|
||||
@@ -15,8 +15,8 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
public class JarAdp_ {
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
public class Jar_adp_ {
|
||||
public static DateAdp ModifiedTime_type(Class<?> type) {if (type == null) throw Err_.new_null();
|
||||
Io_url url = Url_type(type);
|
||||
return Io_mgr.Instance.QueryFil(url).ModifiedTime();
|
||||
@@ -15,7 +15,7 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
public class Op_sys {
|
||||
Op_sys(byte tid, byte sub_tid, String os_name, byte bitness, String nl_str, byte fsys_dir_spr_byte, boolean fsys_case_match) {
|
||||
this.tid = tid; this.sub_tid = sub_tid; this.os_name = os_name; this.bitness = bitness; this.nl_str = nl_str; this.fsys_dir_spr_byte = fsys_dir_spr_byte; this.fsys_dir_spr_str = Char_.To_str((char)fsys_dir_spr_byte); this.fsys_case_match = fsys_case_match;
|
||||
@@ -15,7 +15,7 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
public class Op_sys_ {
|
||||
public static boolean Wnt_invalid_char(byte b) {
|
||||
switch (b) {
|
||||
@@ -15,7 +15,26 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
import gplx.Bool_;
|
||||
import gplx.Bry_;
|
||||
import gplx.Bry_bfr;
|
||||
import gplx.Err_;
|
||||
import gplx.GfoInvkAble;
|
||||
import gplx.GfoInvkAbleCmd;
|
||||
import gplx.GfoInvkAble_;
|
||||
import gplx.GfoMsg;
|
||||
import gplx.Gfo_usr_dlg;
|
||||
import gplx.Gfo_usr_dlg_;
|
||||
import gplx.GfsCtx;
|
||||
import gplx.Io_url;
|
||||
import gplx.Io_url_;
|
||||
import gplx.List_adp;
|
||||
import gplx.List_adp_;
|
||||
import gplx.RlsAble;
|
||||
import gplx.String_;
|
||||
import gplx.Tfds;
|
||||
import gplx.Virtual;
|
||||
import gplx.core.threads.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@@ -24,40 +43,40 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import javax.management.RuntimeErrorException;
|
||||
import gplx.core.brys.fmtrs.*;
|
||||
import gplx.core.strings.*; import gplx.langs.gfs.*;
|
||||
public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
public boolean Enabled() {return enabled;} public ProcessAdp Enabled_(boolean v) {enabled = v; return this;} private boolean enabled = true;
|
||||
public byte Exe_exists() {return exe_exists;} public ProcessAdp Exe_exists_(byte v) {exe_exists = v; return this;} private byte exe_exists = Bool_.__byte;
|
||||
public Io_url Exe_url() {return exe_url;} public ProcessAdp Exe_url_(Io_url val) {exe_url = val; exe_exists = Bool_.__byte; return this;} Io_url exe_url;
|
||||
public String Args_str() {return args_str;} public ProcessAdp Args_str_(String val) {args_str = val; return this;} private String args_str = "";
|
||||
import gplx.core.brys.fmtrs.*; import gplx.core.strings.*;
|
||||
import gplx.langs.gfs.*;
|
||||
public class Process_adp implements GfoInvkAble, RlsAble {
|
||||
public boolean Enabled() {return enabled;} public Process_adp Enabled_(boolean v) {enabled = v; return this;} private boolean enabled = true;
|
||||
public byte Exe_exists() {return exe_exists;} public Process_adp Exe_exists_(byte v) {exe_exists = v; return this;} private byte exe_exists = Bool_.__byte;
|
||||
public Io_url Exe_url() {return exe_url;} public Process_adp Exe_url_(Io_url val) {exe_url = val; exe_exists = Bool_.__byte; return this;} Io_url exe_url;
|
||||
public String Args_str() {return args_str;} public Process_adp Args_str_(String val) {args_str = val; return this;} private String args_str = "";
|
||||
public Bry_fmtr Args_fmtr() {return args_fmtr;} Bry_fmtr args_fmtr = Bry_fmtr.new_("");
|
||||
public byte Run_mode() {return run_mode;} public ProcessAdp Run_mode_(byte v) {run_mode = v; return this;} private byte run_mode = Run_mode_sync_block;
|
||||
public byte Run_mode() {return run_mode;} public Process_adp Run_mode_(byte v) {run_mode = v; return this;} private byte run_mode = Run_mode_sync_block;
|
||||
public static final byte Run_mode_async = 0, Run_mode_sync_block = 1, Run_mode_sync_timeout = 2;
|
||||
public int Exit_code() {return exit_code;} int exit_code;
|
||||
public boolean Exit_code_pass() {return exit_code == Exit_pass;}
|
||||
public String Rslt_out() {return rslt_out;} private String rslt_out;
|
||||
public Io_url Working_dir() {return working_dir;} public ProcessAdp Working_dir_(Io_url v) {working_dir = v; return this;} Io_url working_dir;
|
||||
public ProcessAdp Cmd_args(String cmd, String args) {this.Exe_url_(Io_url_.new_fil_(cmd)); this.args_fmtr.Fmt_(args); return this;}
|
||||
public ProcessAdp WhenBgn_add(GfoInvkAbleCmd cmd) {whenBgnList.Add(cmd); return this;}
|
||||
public ProcessAdp WhenBgn_del(GfoInvkAbleCmd cmd) {whenBgnList.Del(cmd); return this;}
|
||||
public int Thread_timeout() {return thread_timeout;} public ProcessAdp Thread_timeout_seconds_(int v) {thread_timeout = v * 1000; return this;} int thread_timeout = 0;
|
||||
public int Thread_interval() {return thread_interval;} public ProcessAdp Thread_interval_(int v) {thread_interval = v; return this;} int thread_interval = 20;
|
||||
public String Thread_kill_name() {return thread_kill_name;} public ProcessAdp Thread_kill_name_(String v) {thread_kill_name = v; return this;} private String thread_kill_name = "";
|
||||
public Io_url Tmp_dir() {return tmp_dir;} @gplx.Virtual public ProcessAdp Tmp_dir_(Io_url v) {tmp_dir = v; return this;} Io_url tmp_dir;
|
||||
private ProcessAdp WhenBgn_run() {return Invk_cmds(whenBgnList);} List_adp whenBgnList = List_adp_.new_();
|
||||
public ProcessAdp WhenEnd_add(GfoInvkAbleCmd cmd) {whenEndList.Add(cmd); return this;}
|
||||
public ProcessAdp WhenEnd_del(GfoInvkAbleCmd cmd) {whenEndList.Del(cmd); return this;}
|
||||
public Gfo_usr_dlg Prog_dlg() {return prog_dlg;} public ProcessAdp Prog_dlg_(Gfo_usr_dlg v) {prog_dlg = v; return this;} Gfo_usr_dlg prog_dlg;
|
||||
public String Prog_fmt() {return prog_fmt;} public ProcessAdp Prog_fmt_(String v) {prog_fmt = v; return this;} private String prog_fmt = ""; // NOTE: set to "", else cmds that do not set prog_fmt will fail on fmtr.Fmt(null)
|
||||
public Io_url Working_dir() {return working_dir;} public Process_adp Working_dir_(Io_url v) {working_dir = v; return this;} Io_url working_dir;
|
||||
public Process_adp Cmd_args(String cmd, String args) {this.Exe_url_(Io_url_.new_fil_(cmd)); this.args_fmtr.Fmt_(args); return this;}
|
||||
public Process_adp WhenBgn_add(GfoInvkAbleCmd cmd) {whenBgnList.Add(cmd); return this;}
|
||||
public Process_adp WhenBgn_del(GfoInvkAbleCmd cmd) {whenBgnList.Del(cmd); return this;}
|
||||
public int Thread_timeout() {return thread_timeout;} public Process_adp Thread_timeout_seconds_(int v) {thread_timeout = v * 1000; return this;} int thread_timeout = 0;
|
||||
public int Thread_interval() {return thread_interval;} public Process_adp Thread_interval_(int v) {thread_interval = v; return this;} int thread_interval = 20;
|
||||
public String Thread_kill_name() {return thread_kill_name;} public Process_adp Thread_kill_name_(String v) {thread_kill_name = v; return this;} private String thread_kill_name = "";
|
||||
public Io_url Tmp_dir() {return tmp_dir;} @gplx.Virtual public Process_adp Tmp_dir_(Io_url v) {tmp_dir = v; return this;} Io_url tmp_dir;
|
||||
private Process_adp WhenBgn_run() {return Invk_cmds(whenBgnList);} List_adp whenBgnList = List_adp_.new_();
|
||||
public Process_adp WhenEnd_add(GfoInvkAbleCmd cmd) {whenEndList.Add(cmd); return this;}
|
||||
public Process_adp WhenEnd_del(GfoInvkAbleCmd cmd) {whenEndList.Del(cmd); return this;}
|
||||
public Gfo_usr_dlg Prog_dlg() {return prog_dlg;} public Process_adp Prog_dlg_(Gfo_usr_dlg v) {prog_dlg = v; return this;} Gfo_usr_dlg prog_dlg;
|
||||
public String Prog_fmt() {return prog_fmt;} public Process_adp Prog_fmt_(String v) {prog_fmt = v; return this;} private String prog_fmt = ""; // NOTE: set to "", else cmds that do not set prog_fmt will fail on fmtr.Fmt(null)
|
||||
private GfoInvkAble owner;
|
||||
private ProcessAdp WhenEnd_run() {return Invk_cmds(whenEndList);} List_adp whenEndList = List_adp_.new_();
|
||||
private ProcessAdp Invk_cmds(List_adp list) {
|
||||
private Process_adp WhenEnd_run() {return Invk_cmds(whenEndList);} List_adp whenEndList = List_adp_.new_();
|
||||
private Process_adp Invk_cmds(List_adp list) {
|
||||
for (Object o : list)
|
||||
((GfoInvkAbleCmd)o).Invk();
|
||||
return this;
|
||||
}
|
||||
public ProcessAdp Run(Object... args) {
|
||||
public Process_adp Run(Object... args) {
|
||||
if (String_.Len_eq_0(exe_url.Raw())) return this; // noop if exe_url is "";
|
||||
if (!args_fmtr.Fmt_null()) {
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
@@ -94,7 +113,7 @@ public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
}
|
||||
static final String Invk_cmd = "cmd", Invk_cmd_ = "cmd_", Invk_args = "args", Invk_args_ = "args_", Invk_cmd_args_ = "cmd_args_", Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_mode_ = "mode_", Invk_timeout_ = "timeout_", Invk_tmp_dir_ = "tmp_dir_", Invk_owner = "owner";
|
||||
Bry_fmtr_eval_mgr cmd_url_eval;
|
||||
public static ProcessAdp ini_(GfoInvkAble owner, Gfo_usr_dlg usr_dlg, ProcessAdp process, Bry_fmtr_eval_mgr cmd_url_eval, byte run_mode, int timeout, String cmd_url_fmt, String args_fmt, String... args_keys) {
|
||||
public static Process_adp ini_(GfoInvkAble owner, Gfo_usr_dlg usr_dlg, Process_adp process, Bry_fmtr_eval_mgr cmd_url_eval, byte run_mode, int timeout, String cmd_url_fmt, String args_fmt, String... args_keys) {
|
||||
process.Run_mode_(run_mode).Thread_timeout_seconds_(timeout);
|
||||
process.cmd_url_eval = cmd_url_eval;
|
||||
Io_url cmd_url = Bry_fmtr_eval_mgr_.Eval_url(cmd_url_eval, Bry_.new_u8(cmd_url_fmt));
|
||||
@@ -114,27 +133,27 @@ public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
private Bry_fmtr notify_fmtr = Bry_fmtr.new_("", "process_exe_name", "process_exe_args", "process_seconds"); Bry_bfr notify_bfr = Bry_bfr.reset_(255);
|
||||
public Process UnderProcess() {return process;} Process process;
|
||||
public void Rls() {if (process != null) process.destroy();}
|
||||
public ProcessAdp Run_wait_sync() {
|
||||
public Process_adp Run_wait_sync() {
|
||||
if (Env_.Mode_testing()) return Test_runs_add();
|
||||
Process_bgn();
|
||||
Process_start();
|
||||
Process_run_and_end();
|
||||
return this;
|
||||
}
|
||||
public ProcessAdp Run_start() {
|
||||
public Process_adp Run_start() {
|
||||
if (Env_.Mode_testing()) return Test_runs_add();
|
||||
Process_bgn();
|
||||
Process_start();
|
||||
return this;
|
||||
}
|
||||
public ProcessAdp Run_async() {
|
||||
public Process_adp Run_async() {
|
||||
if (Env_.Mode_testing()) return Test_runs_add();
|
||||
Process_bgn();
|
||||
Thread_ProcessAdp_async thread = new Thread_ProcessAdp_async(this);
|
||||
thread.start();
|
||||
return this;
|
||||
}
|
||||
public ProcessAdp Run_wait() {
|
||||
public Process_adp Run_wait() {
|
||||
if (Env_.Mode_testing()) return Test_runs_add();
|
||||
int notify_interval = 100; int notify_checkpoint = notify_interval;
|
||||
int elapsed = 0;
|
||||
@@ -203,7 +222,7 @@ public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
kill_args = "-9 ";
|
||||
}
|
||||
kill_args += thread_kill_name;
|
||||
ProcessAdp kill_process = new ProcessAdp().Exe_url_(Io_url_.new_fil_(kill_exe)).Args_str_(kill_args).Thread_kill_name_("");
|
||||
Process_adp kill_process = new Process_adp().Exe_url_(Io_url_.new_fil_(kill_exe)).Args_str_(kill_args).Thread_kill_name_("");
|
||||
boolean pass = kill_process.Run_wait().Exit_code_pass();
|
||||
return "killed|" + kill_exe + "|" + kill_args + "|" + pass + "|" + exe_url.Raw() + "|" + args_str;
|
||||
}
|
||||
@@ -252,15 +271,15 @@ public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
process.destroy();
|
||||
}
|
||||
public static void run_wait_(Io_url url) {
|
||||
ProcessAdp process = new ProcessAdp().Exe_url_(url);
|
||||
Process_adp process = new Process_adp().Exe_url_(url);
|
||||
process.Run_start();
|
||||
process.Process_run_and_end();
|
||||
return;
|
||||
}
|
||||
public static final List_adp Test_runs = List_adp_.new_();
|
||||
private ProcessAdp Test_runs_add() {Test_runs.Add(exe_url.Raw() + " " + args_str); exit_code = Exit_pass; return this;}
|
||||
private Process_adp Test_runs_add() {Test_runs.Add(exe_url.Raw() + " " + args_str); exit_code = Exit_pass; return this;}
|
||||
public static int run_wait_arg_(Io_url url, String arg) {
|
||||
ProcessAdp process = new ProcessAdp();
|
||||
Process_adp process = new Process_adp();
|
||||
process.Exe_url_(url).Args_str_(arg).Run_wait();
|
||||
return process.Exit_code();
|
||||
}
|
||||
@@ -288,7 +307,7 @@ public class ProcessAdp implements GfoInvkAble, RlsAble {
|
||||
}
|
||||
}
|
||||
class Thread_ProcessAdp_async extends Thread {
|
||||
public Thread_ProcessAdp_async(ProcessAdp process_adp) {this.process_adp = process_adp;} ProcessAdp process_adp;
|
||||
public Thread_ProcessAdp_async(Process_adp process_adp) {this.process_adp = process_adp;} Process_adp process_adp;
|
||||
public boolean Done() {return done;} boolean done = false;
|
||||
public void Cancel() {process_adp.UnderProcess().destroy();}
|
||||
public void run() {
|
||||
@@ -296,7 +315,7 @@ class Thread_ProcessAdp_async extends Thread {
|
||||
}
|
||||
}
|
||||
class Thread_ProcessAdp_sync extends Thread {
|
||||
public Thread_ProcessAdp_sync(ProcessAdp process_adp) {this.process_adp = process_adp;} private final ProcessAdp process_adp;
|
||||
public Thread_ProcessAdp_sync(Process_adp process_adp) {this.process_adp = process_adp;} private final Process_adp process_adp;
|
||||
public boolean Done() {return done;} private boolean done = false;
|
||||
public void Cancel() {
|
||||
process_adp.UnderProcess().destroy();
|
||||
@@ -15,18 +15,18 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.envs; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*;
|
||||
public class ProcessAdp_tst {
|
||||
private ProcessAdp_fxt fxt = new ProcessAdp_fxt();
|
||||
public class Process_adp_tst {
|
||||
private Process_adp_fxt fxt = new Process_adp_fxt();
|
||||
@Test public void Escape_ampersands_if_process_is_cmd() {
|
||||
fxt.Test_Escape_ampersands_if_process_is_cmd(Bool_.Y, "cmd" , "/c \"http://a.org?b=c&d=e\"", "/c \"http://a.org?b=c^&d=e\"");
|
||||
fxt.Test_Escape_ampersands_if_process_is_cmd(Bool_.Y, "cmd1", "/c \"http://a.org?b=c&d=e\"", "/c \"http://a.org?b=c&d=e\"");
|
||||
fxt.Test_Escape_ampersands_if_process_is_cmd(Bool_.N, "cmd" , "/c \"http://a.org?b=c&d=e\"", "/c \"http://a.org?b=c&d=e\"");
|
||||
}
|
||||
}
|
||||
class ProcessAdp_fxt {
|
||||
class Process_adp_fxt {
|
||||
public void Test_Escape_ampersands_if_process_is_cmd(boolean os_is_wnt, String exe_url, String exe_args, String expd) {
|
||||
Tfds.Eq(expd, ProcessAdp.Escape_ampersands_if_process_is_cmd(os_is_wnt, exe_url, exe_args));
|
||||
Tfds.Eq(expd, Process_adp.Escape_ampersands_if_process_is_cmd(os_is_wnt, exe_url, exe_args));
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx;
|
||||
package gplx.core.errs; import gplx.*; import gplx.core.*;
|
||||
public class Err_msg {
|
||||
private final String msg; private Object[] args;
|
||||
public Err_msg(String type, String msg, Object[] args) {
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.type_xtns.*;
|
||||
public class GfoFld {
|
||||
public String Key() {return key;} private String key;
|
||||
public ClassXtn Type() {return type;} ClassXtn type;
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.type_xtns.*;
|
||||
public interface GfoFldList {
|
||||
int Count();
|
||||
boolean Has(String key);
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.strings.*;
|
||||
import gplx.core.strings.*; import gplx.core.type_xtns.*;
|
||||
public class GfoFldList_ {
|
||||
public static final GfoFldList Null = new GfoFldList_null();
|
||||
public static GfoFldList new_() {return new GfoFldList_base();}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.strings.*;
|
||||
import gplx.core.strings.*; import gplx.core.stores.*;
|
||||
public class GfoNde implements GfoInvkAble {
|
||||
public GfoFldList Flds() {return flds;} GfoFldList flds;
|
||||
public Hash_adp EnvVars() {return envVars;} Hash_adp envVars = Hash_adp_.new_();
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.type_xtns.*;
|
||||
public class GfoNdeFxt {
|
||||
public GfoNde root_(GfoNde... subs) {return GfoNde_.root_(subs);}
|
||||
public GfoNde tbl_(String name, GfoNde... rows) {return GfoNde_.tbl_(name, GfoFldList_.Null, rows);}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.lists.*; /*ComparerAble*/
|
||||
import gplx.core.lists.*; /*ComparerAble*/
|
||||
public interface GfoNdeList {
|
||||
int Count();
|
||||
GfoNde FetchAt_asGfoNde(int index);
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.lists.*; /*ComparerAble*/
|
||||
import gplx.core.lists.*; /*ComparerAble*/
|
||||
public class GfoNdeList_ {
|
||||
public static final GfoNdeList Null = new GfoNdeList_null();
|
||||
public static GfoNdeList new_() {return new GfoNdeList_base();}
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_ndes; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.type_xtns.*; import gplx.core.stores.*;
|
||||
public class GfoNde_ {
|
||||
public static final GfoNde[] Ary_empty = new GfoNde[0];
|
||||
public static GfoNde[] ary_(GfoNde... ary) {return ary;}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.gfo_regys; import gplx.*; import gplx.core.*;
|
||||
import gplx.langs.gfs.*;
|
||||
import gplx.langs.gfs.*; import gplx.core.type_xtns.*;
|
||||
public class GfoRegy implements GfoInvkAble {
|
||||
public int Count() {return hash.Count();}
|
||||
public Hash_adp Parsers() {return parsers;} Hash_adp parsers = Hash_adp_.new_();
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.Date;
|
||||
|
||||
import javax.print.FlavorException;
|
||||
import javax.tools.JavaCompiler;
|
||||
import gplx.core.criterias.*;
|
||||
import gplx.core.criterias.*; import gplx.core.envs.*;
|
||||
public class IoEngine_system extends IoEngine_base {
|
||||
@Override public String Key() {return IoEngine_.SysKey;}
|
||||
@Override public void DeleteDirDeep(IoEngine_xrg_deleteDir args) {utl.DeleteDirDeep(this, args.Url(), args);}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.texts.*;
|
||||
import gplx.core.texts.*; import gplx.core.envs.*;
|
||||
public class IoEngine_xrg_loadFilStr {
|
||||
public Io_url Url() {return url;} public IoEngine_xrg_loadFilStr Url_(Io_url val) {url = val; return this;} Io_url url;
|
||||
public boolean MissingIgnored() {return missingIgnored;} public IoEngine_xrg_loadFilStr MissingIgnored_() {return MissingIgnored_(true);} public IoEngine_xrg_loadFilStr MissingIgnored_(boolean v) {missingIgnored = v; return this;} private boolean missingIgnored = false;
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.type_xtns.*;
|
||||
public class IoItmClassXtn extends ClassXtn_base implements ClassXtn {
|
||||
public String Key() {return Key_const;} public static final String Key_const = "ioItemType";
|
||||
@Override public Class<?> UnderClass() {return int.class;}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.lists.*; /*Ordered_hash_base*/
|
||||
import gplx.core.lists.*; /*Ordered_hash_base*/
|
||||
public class IoItmList extends Ordered_hash_base {
|
||||
public boolean Has(Io_url url) {return Has_base(MakeKey(url));}
|
||||
public void Add(IoItm_base itm) {
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.envs.*;
|
||||
public interface IoUrlInfo {
|
||||
String Key();
|
||||
byte DirSpr_byte();
|
||||
|
||||
@@ -16,6 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.envs.*;
|
||||
import gplx.langs.gfs.*;
|
||||
public class IoUrlInfoRegy implements GfoInvkAble {
|
||||
public void Reg(IoUrlInfo info) {hash.Add_if_dupe_use_nth(info.Key(), info);}
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.stores.*; /*GfoNdeRdr_*/
|
||||
import gplx.core.envs.*; import gplx.core.stores.*; /*GfoNdeRdr_*/
|
||||
import gplx.core.gfo_regys.*;
|
||||
public class IoZipWkr {
|
||||
public Io_url ExeUrl() {return (Io_url)GfoRegy.Instance.FetchValOrFail(Regy_ExeUrl);}
|
||||
@@ -29,7 +29,7 @@ public class IoZipWkr {
|
||||
@gplx.Internal protected String Expand_genCmdString(Io_url srcUrl, Io_url trgUrl) {
|
||||
return String_.Format(this.ExeArgFmt(), srcUrl.Xto_api(), trgUrl.Xto_api());
|
||||
}
|
||||
ProcessAdp process = new ProcessAdp();
|
||||
Process_adp process = new Process_adp();
|
||||
public static IoZipWkr regy_() {return new IoZipWkr();}
|
||||
static final String Regy_ExeUrl = "gplx.core.ios.IoZipWkr.ExeUrl", Regy_ExeArgFmt = "gplx.core.ios.IoZipWkr.ExeArgFmt";
|
||||
public static IoZipWkr new_(Io_url exeUrl, String expandArgs) {
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.brys.args.*; import gplx.core.brys.fmtrs.*;
|
||||
import gplx.core.brys.args.*; import gplx.core.brys.fmtrs.*; import gplx.core.envs.*;
|
||||
public class Io_download_fmt {
|
||||
private final Io_size_fmtr_arg size_fmtr_arg = new Io_size_fmtr_arg(), rate_fmtr_arg = new Io_size_fmtr_arg().Suffix_(Bry_.new_a7("ps"));
|
||||
private final Bfr_arg__time prog_left_fmtr_arg = new Bfr_arg__time(); private final Bfr_arg__decimal_int prog_pct_fmtr_arg = new Bfr_arg__decimal_int().Places_(2);
|
||||
|
||||
@@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*;
|
||||
import org.junit.*; import gplx.core.envs.*;
|
||||
public class Io_download_fmt_tst {
|
||||
Io_download_fmt_fxt fxt = new Io_download_fmt_fxt();
|
||||
@Before public void init() {fxt.Clear();}
|
||||
|
||||
20
100_core/src/gplx/core/lists/ComparerAble.java
Normal file
20
100_core/src/gplx/core/lists/ComparerAble.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public interface ComparerAble extends java.util.Comparator {} //_20110320
|
||||
// public int compare(Object lhsObj, Object rhsObj) {}
|
||||
21
100_core/src/gplx/core/lists/ComparerAble_.java
Normal file
21
100_core/src/gplx/core/lists/ComparerAble_.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public class ComparerAble_ {
|
||||
public static int Compare(ComparerAble comparer, Object lhs, Object rhs) {return comparer.compare(lhs, rhs);}
|
||||
}
|
||||
19
100_core/src/gplx/core/lists/EnumerAble.java
Normal file
19
100_core/src/gplx/core/lists/EnumerAble.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public interface EnumerAble extends java.lang.Iterable {}//_20110320
|
||||
57
100_core/src/gplx/core/lists/Hash_adp_base.java
Normal file
57
100_core/src/gplx/core/lists/Hash_adp_base.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public abstract class Hash_adp_base implements Hash_adp {
|
||||
public boolean Has(Object key) {return Has_base(key);}
|
||||
public Object Get_by(Object key) {return Fetch_base(key);}
|
||||
public Object Get_by_or_fail(Object key) {return Get_by_or_fail_base(key);}
|
||||
// public Object Get_by_or_new(Object key, NewAble proto) {
|
||||
// Object rv = Fetch_base(key);
|
||||
// if (rv == null) {
|
||||
// rv = proto.NewByKey(key);
|
||||
// Add_base(key, rv);
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
public void Add(Object key, Object val) {Add_base(key, val);}
|
||||
public void Add_as_key_and_val(Object val) {Add_base(val, val);}
|
||||
public void Add_if_dupe_use_nth(Object key, Object val) {
|
||||
Object existing = Fetch_base(key); if (existing != null) Del(key); // overwrite if exists
|
||||
Add(key, val);
|
||||
}
|
||||
public boolean Add_if_dupe_use_1st(Object key, Object val) {
|
||||
if (Has(key)) return false;
|
||||
Add(key, val);
|
||||
return true;
|
||||
}
|
||||
@gplx.Virtual public void Del(Object key) {Del_base(key);}
|
||||
protected Object Get_by_or_fail_base(Object key) {
|
||||
if (key == null) throw Err_.new_wo_type("key cannot be null");
|
||||
if (!Has_base(key)) throw Err_.new_wo_type("key not found", "key", key);
|
||||
return Fetch_base(key);
|
||||
}
|
||||
|
||||
private final java.util.Hashtable hash = new java.util.Hashtable();
|
||||
@gplx.Virtual public int Count() {return hash.size();}
|
||||
@gplx.Virtual public void Clear() {hash.clear();}
|
||||
@gplx.Virtual protected void Add_base(Object key, Object val) {hash.put(key, val);}
|
||||
@gplx.Virtual protected void Del_base(Object key) {hash.remove(key);}
|
||||
@gplx.Virtual protected boolean Has_base(Object key) {return hash.containsKey(key);}
|
||||
@gplx.Virtual protected Object Fetch_base(Object key) {return hash.get(key);}
|
||||
@gplx.Virtual public java.util.Iterator iterator() {return hash.values().iterator();}
|
||||
}
|
||||
40
100_core/src/gplx/core/lists/Hash_adp_list.java
Normal file
40
100_core/src/gplx/core/lists/Hash_adp_list.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public class Hash_adp_list extends Hash_adp_base {
|
||||
@gplx.New public List_adp Get_by(Object key) {return List_adp_.as_(Fetch_base(key));}
|
||||
public List_adp Get_by_or_new(Object key) {
|
||||
List_adp rv = Get_by(key);
|
||||
if (rv == null) {
|
||||
rv = List_adp_.new_();
|
||||
Add_base(key, rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void AddInList(Object key, Object val) {
|
||||
List_adp list = Get_by_or_new(key);
|
||||
list.Add(val);
|
||||
}
|
||||
public void DelInList(Object key, Object val) {
|
||||
List_adp list = Get_by(key);
|
||||
if (list == null) return;
|
||||
list.Del(val);
|
||||
if (list.Count() == 0) Del(key);
|
||||
}
|
||||
public static Hash_adp_list new_() {return new Hash_adp_list();} Hash_adp_list() {}
|
||||
}
|
||||
24
100_core/src/gplx/core/lists/Iterator_null.java
Normal file
24
100_core/src/gplx/core/lists/Iterator_null.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.core.lists; import gplx.*; import gplx.core.*;
|
||||
public class Iterator_null implements java.util.Iterator {
|
||||
public boolean hasNext() {return false;}
|
||||
public Object next() {return null;}
|
||||
public void remove() {}
|
||||
public static final Iterator_null Instance = new Iterator_null();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user