mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
Refactor: Refactor baselib; merge Array_ and Bool_
This commit is contained in:
@@ -1,10 +1,24 @@
|
||||
package gplx.objects;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects;
|
||||
public class GfoKeyVal<K, V> {
|
||||
public GfoKeyVal(K key, V val) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
public K Key() {return key;} private final K key;
|
||||
public V Val() {return val;} public void ValSet(V v) {this.val = v;} private V val;
|
||||
public GfoKeyVal(K key, V val) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
public K Key() {return key;} private final K key;
|
||||
public V Val() {return val;} public void ValSet(V v) {this.val = v;} private V val;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,22 +13,22 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects; import gplx.*;
|
||||
import gplx.objects.brys.*;
|
||||
import gplx.objects.strings.*;
|
||||
import gplx.objects.types.*;
|
||||
public class Object_ {
|
||||
public static String To_str_or_null_mark(Object v) {return v == null ? "<<NULL>>": To_str(v);}
|
||||
public static String To_str_or(Object v, String or) {return v == null ? or : To_str(v);}
|
||||
public static String To_str(Object v) {
|
||||
Class<?> c = v.getClass();
|
||||
if (Type_.Eq(c, String_.Cls_ref_type)) return (String)v;
|
||||
else if (Type_.Eq(c, Bry_.Cls_ref_type)) return String_.New_bry_utf8((byte[])v);
|
||||
else return v.toString();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
package gplx.objects;
|
||||
import gplx.objects.arrays.BryUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
import gplx.objects.types.TypeUtl;
|
||||
public class ObjectUtl {
|
||||
public static String ToStrOrNullMark(Object v) {return v == null ? "<<NULL>>": ToStr(v);}
|
||||
public static String ToStrOr(Object v, String or) {return v == null ? or : ToStr(v);}
|
||||
public static String ToStr(Object v) {
|
||||
Class<?> c = v.getClass();
|
||||
if (TypeUtl.Eq(c, StringUtl.ClsRefType)) return (String)v;
|
||||
else if (TypeUtl.Eq(c, BryUtl.ClsRefType)) return StringUtl.NewByBryUtf8((byte[])v);
|
||||
else return v.toString();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
82
baselib/src/gplx/objects/arrays/ArrayUtl.java
Normal file
82
baselib/src/gplx/objects/arrays/ArrayUtl.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.arrays;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.lists.ComparerAble;
|
||||
import gplx.objects.lists.ComparerAbleSorter;
|
||||
import java.lang.reflect.Array;
|
||||
public class ArrayUtl {
|
||||
public static int Len(Object ary) {return Array.getLength(ary);}
|
||||
public static int LenObjAry(Object[] ary) {return ary == null ? 0 : ary.length;}
|
||||
public static Object GetAt(Object ary, int i) {return Array.get(ary, i);}
|
||||
public static void SetAt(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 srcLen) {
|
||||
try {System.arraycopy(src, 0, trg, 0, srcLen);}
|
||||
catch (Exception e) {throw ErrUtl.NewFmt(e, "ArrayUtl.Expand failed; srcLen={0}", srcLen);}
|
||||
return trg;
|
||||
}
|
||||
public static void Copy(Object src, Object trg) {System.arraycopy(src, 0, trg, 0, Len(src));}
|
||||
public static void CopyTo(Object src, Object trg, int trgPos) {System.arraycopy(src, 0, trg, trgPos, Len(src));}
|
||||
public static void CopyTo(Object src, int srcBgn, Object trg, int trgBgn, int srcLen) {System.arraycopy(src, srcBgn, trg, trgBgn, srcLen);}
|
||||
public static Object Clone(Object src) {return Clone(src, 0, Len(src));}
|
||||
public static Object Clone(Object src, int srcBgn) {return Clone(src, srcBgn, Array.getLength(src));}
|
||||
private static Object Clone(Object src, int srcBgn, int srcEnd) {
|
||||
int trgLen = srcEnd - srcBgn;
|
||||
Object trg = Create(ComponentType(src), trgLen);
|
||||
CopyTo(src, srcBgn, trg, 0, trgLen);
|
||||
return trg;
|
||||
}
|
||||
public static Object Resize(Object src, int trgLen) {
|
||||
Object trg = Create(ComponentType(src), trgLen);
|
||||
int srcLen = Array.getLength(src);
|
||||
int copyLen = srcLen > trgLen ? trgLen : srcLen; // trgLen can either expand or shrink
|
||||
CopyTo(src, 0, trg, 0, copyLen);
|
||||
return trg;
|
||||
}
|
||||
public static Object Append(Object src, Object add) {
|
||||
int srcLen = Len(src);
|
||||
int trgLen = srcLen + Len(add);
|
||||
Object trg = Create(ComponentType(src), trgLen);
|
||||
Copy(src, trg);
|
||||
for (int i = srcLen; i < trgLen; i++)
|
||||
SetAt(trg, i, GetAt(add, i - srcLen));
|
||||
return trg;
|
||||
}
|
||||
public static Object AppendOne(Object src, int srcLen, Object newObj) {
|
||||
Object rv = Resize(src, srcLen + 1);
|
||||
SetAt(rv, srcLen, newObj);
|
||||
return rv;
|
||||
}
|
||||
public static Object[] Insert(Object[] cur, Object[] add, int addPos) {
|
||||
int curLen = cur.length, addLen = add.length;
|
||||
Object[] rv = (Object[])Create(ComponentType(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 void Sort(Object[] obj) {new ComparerAbleSorter().Sort(obj, obj.length);}
|
||||
public static void Sort(Object[] obj, ComparerAble comparer) {new ComparerAbleSorter().Sort(obj, obj.length, true, comparer);}
|
||||
public static Object Cast(Object o) {return o;} // NOTE: leftover from .NET; casts System.Object to System.Array
|
||||
private static Class<?> ComponentType(Object ary) {
|
||||
if (ary == null) throw ErrUtl.NewMsg("Array is null");
|
||||
return ary.getClass().getComponentType();
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.arrays; import gplx.*; import gplx.objects.*;
|
||||
import java.lang.reflect.Array;
|
||||
import gplx.objects.errs.*;
|
||||
public class Array_ {
|
||||
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_fmt(e, "Array_.Expand failed; src_len={0}", 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_msg("Array is null");
|
||||
return ary.getClass().getComponentType();
|
||||
}
|
||||
public static Object Resize_add(Object src, Object add) {
|
||||
int srcLen = Len(src);
|
||||
int trgLen = srcLen + Len(add);
|
||||
Object trg = Create(Component_type(src), trgLen);
|
||||
Copy(src, trg);
|
||||
for (int i = srcLen; i < trgLen; i++)
|
||||
Set_at(trg, i, Get_at(add, i - srcLen));
|
||||
return trg;
|
||||
}
|
||||
public static Object Clone(Object src) {
|
||||
Object trg = Create(Component_type(src), Len(src));
|
||||
Copy(src, trg);
|
||||
return trg;
|
||||
}
|
||||
}
|
||||
115
baselib/src/gplx/objects/arrays/BryUtl.java
Normal file
115
baselib/src/gplx/objects/arrays/BryUtl.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.arrays;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
public class BryUtl {
|
||||
public static final Class<?> ClsRefType = byte[].class;
|
||||
public static final byte[] Empty = new byte[0];
|
||||
|
||||
public static boolean Eq(byte[] lhs, byte[] rhs) {return Eq(lhs, 0, lhs == null ? 0 : lhs.length, rhs);}
|
||||
public static boolean Eq(byte[] lhs, int lhsBgn, int lhsEnd, byte[] rhs) {
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
if (lhsBgn < 0) return false;
|
||||
int rhsLen = rhs.length;
|
||||
if (rhsLen != lhsEnd - lhsBgn) return false;
|
||||
int lhsLen = lhs.length;
|
||||
for (int i = 0; i < rhsLen; i++) {
|
||||
int lhsPos = i + lhsBgn;
|
||||
if (lhsPos == lhsLen) return false;
|
||||
if (rhs[i] != lhs[lhsPos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static byte[][] Ary(byte[]... ary) {return ary;}
|
||||
public static byte[][] Ary(String... ary) {
|
||||
int aryLen = ary.length;
|
||||
byte[][] rv = new byte[aryLen][];
|
||||
for (int i = 0; i < aryLen; i++) {
|
||||
String itm = ary[i];
|
||||
rv[i] = itm == null ? null : BryUtl.NewUtf08(itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static byte[] NewA7(String str) {
|
||||
if (str == null) return null;
|
||||
int str_len = str.length();
|
||||
if (str_len == 0) return 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[] NewUtf08(String src) {
|
||||
try {
|
||||
int srcLen = src.length();
|
||||
if (srcLen == 0) return BryUtl.Empty;
|
||||
int bryLen = NewUtf08Count(src, srcLen);
|
||||
byte[] bry = new byte[bryLen];
|
||||
NewUtf08Write(src, srcLen, bry, 0);
|
||||
return bry;
|
||||
}
|
||||
catch (Exception e) {throw ErrUtl.NewFmt(e, "invalid UTF-8 sequence; src={0}", src);}
|
||||
}
|
||||
private static int NewUtf08Count(String src, int srcLen) {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < srcLen; ++i) {
|
||||
char c = src.charAt(i);
|
||||
int cLen = 0;
|
||||
if ( c < 128) cLen = 1; // 1 << 7
|
||||
else if ( c < 2048) cLen = 2; // 1 << 11
|
||||
else if ( (c > 55295) // 0xD800
|
||||
&& (c < 56320)) cLen = 4; // 0xDFFF
|
||||
else cLen = 3; // 1 << 16
|
||||
if (cLen == 4) ++i; // surrogate is 2 wide, not 1
|
||||
rv += cLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void NewUtf08Write(String src, int srcLen, byte[] bry, int bryPos) {
|
||||
for (int i = 0; i < srcLen; ++i) {
|
||||
char c = src.charAt(i);
|
||||
if ( c < 128) {
|
||||
bry[bryPos++] = (byte)c;
|
||||
}
|
||||
else if ( c < 2048) {
|
||||
bry[bryPos++] = (byte)(0xC0 | (c >> 6));
|
||||
bry[bryPos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if ( (c > 55295) // 0xD800
|
||||
&& (c < 56320)) { // 0xDFFF
|
||||
if (i >= srcLen) throw ErrUtl.NewMsg("incomplete surrogate pair at end of String");
|
||||
char nxtChar = src.charAt(i + 1);
|
||||
int v = 0x10000 + (c - 0xD800) * 0x400 + (nxtChar - 0xDC00);
|
||||
bry[bryPos++] = (byte)(0xF0 | (v >> 18));
|
||||
bry[bryPos++] = (byte)(0x80 | (v >> 12) & 0x3F);
|
||||
bry[bryPos++] = (byte)(0x80 | (v >> 6) & 0x3F);
|
||||
bry[bryPos++] = (byte)(0x80 | (v & 0x3F));
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
bry[bryPos++] = (byte)(0xE0 | (c >> 12));
|
||||
bry[bryPos++] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
bry[bryPos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.brys; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Bry_ {
|
||||
public static final Class<?> Cls_ref_type = byte[].class;
|
||||
public static final byte[] Empty = new byte[0];
|
||||
|
||||
public static boolean Eq(byte[] lhs, byte[] rhs) {return Eq(lhs, 0, lhs == null ? 0 : lhs.length, rhs);}
|
||||
public static boolean Eq(byte[] lhs, int lhs_bgn, int lhs_end, byte[] rhs) {
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
if (lhs_bgn < 0) return false;
|
||||
int rhs_len = rhs.length;
|
||||
if (rhs_len != lhs_end - lhs_bgn) return false;
|
||||
int lhs_len = lhs.length;
|
||||
for (int i = 0; i < rhs_len; i++) {
|
||||
int lhs_pos = i + lhs_bgn;
|
||||
if (lhs_pos == lhs_len) return false;
|
||||
if (rhs[i] != lhs[lhs_pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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_utf08(itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static byte[] New_utf08(String src) {
|
||||
try {
|
||||
int src_len = src.length();
|
||||
if (src_len == 0) return Bry_.Empty;
|
||||
int bry_len = New_utf08__count(src, src_len);
|
||||
byte[] bry = new byte[bry_len];
|
||||
New_utf08__write(src, src_len, bry, 0);
|
||||
return bry;
|
||||
}
|
||||
catch (Exception e) {throw Err_.New_fmt(e, "invalid UTF-8 sequence; src={0}", src);}
|
||||
}
|
||||
public static int New_utf08__count(String src, int src_len) {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < src_len; ++i) {
|
||||
char c = src.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_utf08__write(String src, int src_len, byte[] bry, int bry_pos) {
|
||||
for (int i = 0; i < src_len; ++i) {
|
||||
char c = src.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 >= src_len) throw Err_.New_msg("incomplete surrogate pair at end of String");
|
||||
char nxt_char = src.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,7 +13,8 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.errs; import gplx.*; import gplx.objects.*;
|
||||
package gplx.objects.errs;
|
||||
import gplx.*; import gplx.objects.*;
|
||||
public class Err extends RuntimeException {
|
||||
private final String msg;
|
||||
public Err(String msg) {this.msg = msg;}
|
||||
|
||||
43
baselib/src/gplx/objects/errs/ErrUtl.java
Normal file
43
baselib/src/gplx/objects/errs/ErrUtl.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.errs;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
public class ErrUtl {
|
||||
public static void Noop(Exception e) {}
|
||||
public static Err NewMsg(String msg) {return new Err(msg);}
|
||||
public static Err NewFmt(String fmt, Object... args) {return new Err(StringUtl.Format(fmt, args));}
|
||||
public static Err NewFmt(Exception e, String fmt, Object... args) {return new Err(StringUtl.Format(fmt, args) + " exc=" + ErrUtl.MessageLang(e));}
|
||||
public static Err NewNull(String name) {return new Err("object was null; name=" + name);}
|
||||
public static Err NewUnhandledDefault(Object o) {return new Err("val is not in switch; val=" + ObjectUtl.ToStr(o));}
|
||||
public static Err NewUnimplemented() {return new Err("method is not implemented");}
|
||||
public static Err NewParse(Class<?> cls, String raw) {return new Err("parse failed; cls=" + cls.getCanonicalName() + "; raw=" + raw);}
|
||||
|
||||
public static String MessageLang(Exception e) {
|
||||
return Error.class.isAssignableFrom(e.getClass())
|
||||
? e.toString() // java.lang.Error returns null for "getMessage()"; return "toString()" instead
|
||||
: e.getMessage();
|
||||
}
|
||||
public static String TraceLang(Throwable e) {
|
||||
StackTraceElement[] ary = e.getStackTrace();
|
||||
String rv = "";
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
if (i != 0) rv += "\n";
|
||||
rv += ary[i].toString();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.errs; import gplx.objects.Object_;
|
||||
import gplx.objects.strings.String_;
|
||||
public class Err_ {
|
||||
public static void Noop(Exception e) {}
|
||||
public static Err New_fmt(String fmt, Object... args) {return new Err(String_.Format(fmt, args));}
|
||||
public static Err New_msg(String msg) {return new Err(msg);}
|
||||
public static Err New_fmt(Exception e, String fmt, Object... args) {
|
||||
return new Err(String_.Format(fmt, args) + " exc=" + Err_.Message_lang(e));
|
||||
}
|
||||
|
||||
public static Err New_null(String name) {return new Err("Object was null; name=" + name);}
|
||||
public static Err New_unhandled_default(Object o) {
|
||||
return new Err("val is not in switch; val=" + Object_.To_str(o));
|
||||
}
|
||||
public static Err New_unimplemented() {return new Err("Method is not implemented");}
|
||||
|
||||
public static String Message_lang(Exception e) {
|
||||
return Error.class.isAssignableFrom(e.getClass())
|
||||
? e.toString() // java.lang.Error returns null for "getMessage()"; return "toString()" instead
|
||||
: e.getMessage();
|
||||
}
|
||||
|
||||
public static String Trace_lang(Throwable e) {
|
||||
StackTraceElement[] ary = e.getStackTrace();
|
||||
String rv = "";
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
if (i != 0) rv += "\n";
|
||||
rv += ary[i].toString();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,36 @@
|
||||
package gplx.objects.events;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.events;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GfoEvent<A> {
|
||||
private final List<GfoHandler<A>> handlers = new ArrayList<>();
|
||||
private final String name;
|
||||
private final GfoEventOwner owner;
|
||||
public GfoEvent(String name, GfoEventOwner owner) {
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
}
|
||||
public void Add(GfoHandler<A> handler) {
|
||||
owner.EventsEnabledSet(true);
|
||||
handlers.add(handler);
|
||||
}
|
||||
public void Run(A args) {
|
||||
for (GfoHandler<A> handler : handlers) {
|
||||
handler.Run(owner, args);
|
||||
}
|
||||
}
|
||||
private final List<GfoHandler<A>> handlers = new ArrayList<>();
|
||||
private final String name;
|
||||
private final GfoEventOwner owner;
|
||||
public GfoEvent(String name, GfoEventOwner owner) {
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
}
|
||||
public void Add(GfoHandler<A> handler) {
|
||||
owner.EventsEnabledSet(true);
|
||||
handlers.add(handler);
|
||||
}
|
||||
public void Run(A args) {
|
||||
for (GfoHandler<A> handler : handlers) {
|
||||
handler.Run(owner, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
package gplx.objects.events;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.events;
|
||||
public interface GfoEventOwner {
|
||||
boolean EventsEnabled(); void EventsEnabledSet(boolean v);
|
||||
boolean EventsEnabled(); void EventsEnabledSet(boolean v);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
package gplx.objects.events;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.events;
|
||||
public interface GfoHandler<A> {
|
||||
void Run(GfoEventOwner sender, A args);
|
||||
void Run(GfoEventOwner sender, A args);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
public class Char_ {
|
||||
public static final String Cls_val_name = "char";
|
||||
public static final Class<?> Cls_ref_type = Character.class;
|
||||
}
|
||||
package gplx.objects.lists;
|
||||
public interface CompareAble extends Comparable {} // URL:/doc/gplx/CompareAble_.txt
|
||||
// public int compareTo(Object obj) {Type comp = (Type)obj; return prop.compareTo(comp.prop);}
|
||||
41
baselib/src/gplx/objects/lists/CompareAbleUtl.java
Normal file
41
baselib/src/gplx/objects/lists/CompareAbleUtl.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public class CompareAbleUtl {
|
||||
public static Comparable as_(Object obj) {return obj instanceof Comparable ? (Comparable)obj : null;}
|
||||
public static int Compare_obj(Object lhs, Object rhs) {return Compare_comp(as_(lhs), as_(rhs));}
|
||||
public static int Compare_comp(Comparable lhs, Comparable rhs) {
|
||||
if (lhs == null && rhs == null) return CompareAbleUtl.Same;
|
||||
else if (lhs == null) return CompareAbleUtl.More;
|
||||
else if (rhs == null) return CompareAbleUtl.Less;
|
||||
else return Compare(lhs, rhs);
|
||||
}
|
||||
public static int Compare(Comparable lhs, Comparable rhs) {return lhs.compareTo(rhs);}
|
||||
|
||||
public static boolean Is(int expd, Comparable lhs, Comparable rhs) {
|
||||
int actl = Compare_comp(lhs, rhs);
|
||||
if (actl == Same && expd % 2 == Same) // actl=Same and expd=(Same||MoreOrSame||LessOrSame)
|
||||
return true;
|
||||
else
|
||||
return (actl * expd) > 0; // actl=More||Less; expd will match if on same side of 0 (ex: expd=Less; actl=Less; -1 * -1 = 1)
|
||||
}
|
||||
public static final int
|
||||
More = 1,
|
||||
Less = -1,
|
||||
Same = 0,
|
||||
More_or_same = 2,
|
||||
Less_or_same = -2;
|
||||
}
|
||||
@@ -13,8 +13,8 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
public class Float_ {
|
||||
public static final String Cls_val_name = "float";
|
||||
public static final Class<?> Cls_ref_type = Float.class;
|
||||
package gplx.objects.lists;
|
||||
import java.util.Comparator;
|
||||
public interface ComparerAble extends Comparator {
|
||||
}
|
||||
// public int compare(Object lhsObj, Object rhsObj) {}
|
||||
61
baselib/src/gplx/objects/lists/ComparerAbleSorter.java
Normal file
61
baselib/src/gplx/objects/lists/ComparerAbleSorter.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public class ComparerAbleSorter {
|
||||
private ComparerAble comparer = null;
|
||||
public void Sort(Object[] orig, int origLen) {Sort(orig, origLen, true, null);}
|
||||
public void Sort(Object[] orig, int origLen, boolean asc, ComparerAble comparer) {
|
||||
this.comparer = comparer;
|
||||
Object[] temp = new Object[origLen];
|
||||
MergeSort(asc, orig, temp, 0, origLen - 1);
|
||||
this.comparer = null;
|
||||
}
|
||||
private void MergeSort(boolean asc, Object[] orig, Object[] temp, int lhs, int rhs) {
|
||||
if (lhs < rhs) {
|
||||
int mid = (lhs + rhs) / 2;
|
||||
MergeSort(asc, orig, temp, lhs, mid);
|
||||
MergeSort(asc, orig, temp, mid + 1, rhs);
|
||||
Combine(asc, orig, temp, lhs, mid + 1, rhs);
|
||||
}
|
||||
}
|
||||
private void Combine(boolean asc, Object[] orig, Object[] temp, int lhsPos, int rhsPos, int rhsEnd) {
|
||||
int lhsEnd = rhsPos - 1;
|
||||
int tmpPos = lhsPos;
|
||||
int aryLen = rhsEnd - lhsPos + 1;
|
||||
|
||||
while (lhsPos <= lhsEnd && rhsPos <= rhsEnd) {
|
||||
int compareVal = 0;
|
||||
if (comparer != null)
|
||||
compareVal = ComparerAbleUtl.Compare(comparer, orig[lhsPos], orig[rhsPos]);
|
||||
else {
|
||||
Comparable lhsComp = (Comparable)orig[lhsPos];
|
||||
compareVal = lhsComp == null ? CompareAbleUtl.Less : lhsComp.compareTo(orig[rhsPos]);
|
||||
}
|
||||
if (!asc) compareVal *= -1;
|
||||
if (compareVal <= CompareAbleUtl.Same) // NOTE: (a) must be < 0; JAVA's String.compareTo returns -number based on position; (b) must be <= else sorting sorted list will change order; EX: sorting (a,1;a,2) on fld0 will switch to (a,2;a,1)
|
||||
temp[tmpPos++] = orig[lhsPos++];
|
||||
else
|
||||
temp[tmpPos++] = orig[rhsPos++];
|
||||
}
|
||||
|
||||
while (lhsPos <= lhsEnd) // Copy rest of first half
|
||||
temp[tmpPos++] = orig[lhsPos++];
|
||||
while (rhsPos <= rhsEnd) // Copy rest of right half
|
||||
temp[tmpPos++] = orig[rhsPos++];
|
||||
for (int i = 0; i < aryLen; i++, rhsEnd--)
|
||||
orig[rhsEnd] = temp[rhsEnd];
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,7 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
public class Short_ {
|
||||
public static final String Cls_val_name = "short";
|
||||
public static final Class<?> Cls_ref_type = Short.class;
|
||||
package gplx.objects.lists;
|
||||
public class ComparerAbleUtl {
|
||||
public static int Compare(ComparerAble comparer, Object lhs, Object rhs) {return comparer.compare(lhs, rhs);}
|
||||
}
|
||||
@@ -1,4 +1,18 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public interface GfoComparator<T> extends java.util.Comparator<T> {
|
||||
}
|
||||
|
||||
@@ -1,46 +1,59 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
import gplx.objects.errs.Err_;
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GfoHashBase<K, V> implements Iterable<Map.Entry<K, V>> {
|
||||
protected final Map<K, V> map = new HashMap<>();
|
||||
protected final Map<K, V> map = new HashMap<>();
|
||||
|
||||
public int Len() {return map.size();}
|
||||
public void Clear() {map.clear();}
|
||||
public void Add(GfoHashKeyFunc<K> keyFunc, V v) {Add(keyFunc.ToHashKey(), v);}
|
||||
public void Add(K k, V v) {
|
||||
if (k == null) {
|
||||
throw Err_.New_fmt("key cannot be null; val={0}", v);
|
||||
}
|
||||
if (map.containsKey(k)) {
|
||||
throw Err_.New_fmt("key already exists: key={0} val={1}", k, v);
|
||||
}
|
||||
map.put(k, v);
|
||||
}
|
||||
public void Del(K k) {map.remove(k);}
|
||||
public void Set(K k, V v) {map.put(k, v);}
|
||||
public boolean Has(K k) {return map.containsKey(k);}
|
||||
public V GetByOrNull(K k) {return map.get(k);}
|
||||
public V GetByOr(K k, V or) {
|
||||
V v = map.get(k);
|
||||
if (v == null) {
|
||||
v = or;
|
||||
}
|
||||
return v;
|
||||
public int Len() {return map.size();}
|
||||
public void Clear() {map.clear();}
|
||||
public void Add(GfoHashKeyFunc<K> keyFunc, V v) {Add(keyFunc.ToHashKey(), v);}
|
||||
public void Add(K k, V v) {
|
||||
if (k == null) {
|
||||
throw ErrUtl.NewFmt("key cannot be null; val={0}", v);
|
||||
}
|
||||
if (map.containsKey(k)) {
|
||||
throw ErrUtl.NewFmt("key already exists: key={0} val={1}", k, v);
|
||||
}
|
||||
map.put(k, v);
|
||||
}
|
||||
public V GetByOrFail(GfoHashKeyFunc<K> func) {return GetByOrFail(func.ToHashKey());}
|
||||
public V GetByOrFail(K k) {
|
||||
V v = map.get(k);
|
||||
if (v == null) {
|
||||
throw Err_.New_fmt("val not found; key={0}", k);
|
||||
}
|
||||
return v;
|
||||
public void Del(K k) {map.remove(k);}
|
||||
public void Set(K k, V v) {map.put(k, v);}
|
||||
public boolean Has(K k) {return map.containsKey(k);}
|
||||
public V GetByOrNull(K k) {return map.get(k);}
|
||||
public V GetByOr(K k, V or) {
|
||||
V v = map.get(k);
|
||||
if (v == null) {
|
||||
v = or;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
public V GetByOrFail(GfoHashKeyFunc<K> func) {return GetByOrFail(func.ToHashKey());}
|
||||
public V GetByOrFail(K k) {
|
||||
V v = map.get(k);
|
||||
if (v == null) {
|
||||
throw ErrUtl.NewFmt("val not found; key={0}", k);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override public Iterator<Map.Entry<K, V>> iterator() {return map.entrySet().iterator();}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public interface GfoHashKeyFunc<K> {
|
||||
K ToHashKey();
|
||||
K ToHashKey();
|
||||
}
|
||||
|
||||
@@ -1,127 +1,140 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
import gplx.objects.GfoKeyVal;
|
||||
import gplx.objects.errs.Err_;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GfoIndexedList<K, V> implements Iterable<V> {
|
||||
private final GfoListBase<V> list = new GfoListBase<>();
|
||||
private final GfoHashBase<K, GfoIndexedListEntry<K, V>> hash = new GfoHashBase<>();
|
||||
public boolean Has(K key) {
|
||||
return hash.Has(key);
|
||||
}
|
||||
public int Len() {return hash.Len();}
|
||||
public V GetAt(int key) {
|
||||
return list.GetAt(key);
|
||||
}
|
||||
public V GetByOrFail(GfoHashKeyFunc<K> func) {return GetByOrFail(func.ToHashKey());}
|
||||
public V GetByOrFail(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
if (val == null) {
|
||||
throw Err_.New_fmt("Unknown key: {0}", key);
|
||||
}
|
||||
return val.Val();
|
||||
}
|
||||
public V GetByOr(K key, V or) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? or : val.Val();
|
||||
}
|
||||
public Optional<V> GetBy(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? Optional.empty() : Optional.of(val.Val());
|
||||
}
|
||||
public V GetByOrNull(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? null : val.Val();
|
||||
}
|
||||
public void Sort(GfoComparator<V> comparator) {
|
||||
private final GfoListBase<V> list = new GfoListBase<>();
|
||||
private final GfoHashBase<K, GfoIndexedListEntry<K, V>> hash = new GfoHashBase<>();
|
||||
public boolean Has(K key) {
|
||||
return hash.Has(key);
|
||||
}
|
||||
public int Len() {return hash.Len();}
|
||||
public V GetAt(int key) {
|
||||
return list.GetAt(key);
|
||||
}
|
||||
public V GetByOrFail(GfoHashKeyFunc<K> func) {return GetByOrFail(func.ToHashKey());}
|
||||
public V GetByOrFail(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
if (val == null) {
|
||||
throw ErrUtl.NewFmt("Unknown key: {0}", key);
|
||||
}
|
||||
return val.Val();
|
||||
}
|
||||
public V GetByOr(K key, V or) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? or : val.Val();
|
||||
}
|
||||
public Optional<V> GetBy(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? Optional.empty() : Optional.of(val.Val());
|
||||
}
|
||||
public V GetByOrNull(K key) {
|
||||
GfoIndexedListEntry<K, V> val = hash.GetByOrNull(key);
|
||||
return val == null ? null : val.Val();
|
||||
}
|
||||
public void Sort(GfoComparator<V> comparator) {
|
||||
list.Sort(comparator);
|
||||
}
|
||||
public void AddAt(int i, K key, V val) {
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() >= i) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() + 1);
|
||||
}
|
||||
}
|
||||
hash.Add(key, new GfoIndexedListEntry<>(key, val, i));
|
||||
list.AddAt(i, val);
|
||||
}
|
||||
public void DelAt(int i, K key) {
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() > i) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() - 1);
|
||||
}
|
||||
}
|
||||
hash.Del(key);
|
||||
list.DelAt(i);
|
||||
}
|
||||
public void Add(GfoHashKeyFunc<K> func, V val) {Add(func.ToHashKey(), val);}
|
||||
public void Add(K key, V val) {
|
||||
hash.Add(key, new GfoIndexedListEntry<>(key, val, list.Len()));
|
||||
list.Add(val);
|
||||
}
|
||||
public void Set(K key, V val) {
|
||||
GfoIndexedListEntry<K, V> entry = hash.GetByOrNull(key);
|
||||
if (entry == null) {
|
||||
this.Add(key, val);
|
||||
}
|
||||
else {
|
||||
entry.ValSet(val);
|
||||
list.Set(entry.ListIdx(), val);
|
||||
}
|
||||
}
|
||||
public void DelBy(K key) {
|
||||
GfoIndexedListEntry<K, V> entry = hash.GetByOrNull(key);
|
||||
if (entry == null) {
|
||||
return; // if key is unknown, do nothing; matches behavior of java.util.Hashtable
|
||||
}
|
||||
hash.Del(key);
|
||||
int listIdx = entry.ListIdx();
|
||||
list.DelAt(listIdx);
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() > listIdx) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Clear() {
|
||||
list.Clear();
|
||||
hash.Clear();
|
||||
}
|
||||
public V[] ToAry(Class<?> clz) {return list.ToAry(clz);}
|
||||
public GfoKeyVal<K, V>[] ToKvAry() {
|
||||
int len = this.Len();
|
||||
GfoKeyVal<K, V>[] ary = new GfoKeyVal[len];
|
||||
int idx = 0;
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
ary[idx++] = new GfoKeyVal<>(mapEntryItem.Key(), mapEntryItem.Val());
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
}
|
||||
public void AddAt(int i, K key, V val) {
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() >= i) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() + 1);
|
||||
}
|
||||
}
|
||||
hash.Add(key, new GfoIndexedListEntry<>(key, val, i));
|
||||
list.AddAt(i, val);
|
||||
}
|
||||
public void DelAt(int i, K key) {
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() > i) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() - 1);
|
||||
}
|
||||
}
|
||||
hash.Del(key);
|
||||
list.DelAt(i);
|
||||
}
|
||||
public void Add(GfoHashKeyFunc<K> func, V val) {Add(func.ToHashKey(), val);}
|
||||
public void Add(K key, V val) {
|
||||
hash.Add(key, new GfoIndexedListEntry<>(key, val, list.Len()));
|
||||
list.Add(val);
|
||||
}
|
||||
public void Set(K key, V val) {
|
||||
GfoIndexedListEntry<K, V> entry = hash.GetByOrNull(key);
|
||||
if (entry == null) {
|
||||
this.Add(key, val);
|
||||
}
|
||||
else {
|
||||
entry.ValSet(val);
|
||||
list.Set(entry.ListIdx(), val);
|
||||
}
|
||||
}
|
||||
public void DelBy(K key) {
|
||||
GfoIndexedListEntry<K, V> entry = hash.GetByOrNull(key);
|
||||
if (entry == null) {
|
||||
return; // if key is unknown, do nothing; matches behavior of java.util.Hashtable
|
||||
}
|
||||
hash.Del(key);
|
||||
int listIdx = entry.ListIdx();
|
||||
list.DelAt(listIdx);
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
if (mapEntryItem.ListIdx() > listIdx) {
|
||||
mapEntryItem.ListIdxSet(mapEntryItem.ListIdx() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Clear() {
|
||||
list.Clear();
|
||||
hash.Clear();
|
||||
}
|
||||
public V[] ToAry(Class<?> clz) {return list.ToAry(clz);}
|
||||
public GfoKeyVal<K, V>[] ToKvAry() {
|
||||
int len = this.Len();
|
||||
GfoKeyVal<K, V>[] ary = new GfoKeyVal[len];
|
||||
int idx = 0;
|
||||
for (Map.Entry<K, GfoIndexedListEntry<K, V>> mapEntry : hash) {
|
||||
GfoIndexedListEntry<K, V> mapEntryItem = mapEntry.getValue();
|
||||
ary[idx++] = new GfoKeyVal<>(mapEntryItem.Key(), mapEntryItem.Val());
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
|
||||
@Override public Iterator<V> iterator() {return list.iterator();}
|
||||
@Override public void forEach(Consumer<? super V> action) {list.forEach(action);}
|
||||
@Override public Spliterator<V> spliterator() {return list.spliterator();}
|
||||
}
|
||||
class GfoIndexedListEntry<K, V> {
|
||||
private final K key;
|
||||
private V val;
|
||||
private int listIdx;
|
||||
public GfoIndexedListEntry(K key, V val, int listIdx) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
this.listIdx = listIdx;
|
||||
}
|
||||
public K Key() {return key;}
|
||||
public V Val() {return val;} public void ValSet(V v) {this.val = v;}
|
||||
public int ListIdx() {return listIdx;} public void ListIdxSet(int v) {listIdx = v;}
|
||||
private final K key;
|
||||
private V val;
|
||||
private int listIdx;
|
||||
public GfoIndexedListEntry(K key, V val, int listIdx) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
this.listIdx = listIdx;
|
||||
}
|
||||
public K Key() {return key;}
|
||||
public V Val() {return val;} public void ValSet(V v) {this.val = v;}
|
||||
public int ListIdx() {return listIdx;} public void ListIdxSet(int v) {listIdx = v;}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
import gplx.objects.errs.Err_;
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.events.GfoEvent;
|
||||
import gplx.objects.events.GfoEventOwner;
|
||||
|
||||
@@ -8,116 +22,115 @@ import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
protected final List<E> list = new ArrayList<>();
|
||||
private boolean eventsEnabled;
|
||||
protected final List<E> list = new ArrayList<>();
|
||||
private boolean eventsEnabled;
|
||||
|
||||
public GfoListBase() {
|
||||
public GfoListBase() {
|
||||
this.itemsChanged = new GfoEvent<>("Add", this);
|
||||
}
|
||||
}
|
||||
|
||||
public int Len() {return list.size();}
|
||||
public E GetAt(int i) {return list.get(i);}
|
||||
public E GetAtBgn() {return list.get(0);}
|
||||
public E GetAtEnd() {return list.get(list.size() - 1);}
|
||||
public int Len() {return list.size();}
|
||||
public E GetAt(int i) {return list.get(i);}
|
||||
public E GetAtBgn() {return list.get(0);}
|
||||
public E GetAtEnd() {return list.get(list.size() - 1);}
|
||||
|
||||
@Override
|
||||
public boolean EventsEnabled() {
|
||||
return eventsEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void EventsEnabledSet(boolean v) {
|
||||
eventsEnabled = v;
|
||||
}
|
||||
public GfoEvent<ItemsChangedArg<E>> ItemsChanged() {return itemsChanged;} private final GfoEvent<ItemsChangedArg<E>> itemsChanged;
|
||||
public GfoListBase<E> Add(E itm) {
|
||||
list.add(itm);
|
||||
if (eventsEnabled) {
|
||||
public GfoListBase<E> Add(E itm) {
|
||||
list.add(itm);
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Add, GfoListBase.NewFromArray(itm)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoListBase<E> AddMany(E... ary) {
|
||||
for (E itm : ary) {
|
||||
this.Add(itm);
|
||||
}
|
||||
return this;
|
||||
public GfoListBase<E> AddMany(E... ary) {
|
||||
for (E itm : ary) {
|
||||
this.Add(itm);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoListBase<E> AddMany(GfoListBase<E> list) {
|
||||
for (E itm : list) {
|
||||
this.Add(itm);
|
||||
}
|
||||
return this;
|
||||
public GfoListBase<E> AddMany(GfoListBase<E> list) {
|
||||
for (E itm : list) {
|
||||
this.Add(itm);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void AddAt(int i, E itm) {
|
||||
list.add(i, itm);
|
||||
if (eventsEnabled) {
|
||||
public void AddAt(int i, E itm) {
|
||||
list.add(i, itm);
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Add, GfoListBase.NewFromArray(itm)));
|
||||
}
|
||||
}
|
||||
public void Set(int i, E itm) {
|
||||
list.set(i, itm);
|
||||
if (eventsEnabled) {
|
||||
}
|
||||
public void Set(int i, E itm) {
|
||||
list.set(i, itm);
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Set, GfoListBase.NewFromArray(itm)));
|
||||
}
|
||||
}
|
||||
public void DelAt(int i) {
|
||||
list.remove(i);
|
||||
}
|
||||
public void DelBetween(int i) {DelBetween(i, list.size() - 1);}
|
||||
public void DelBetween(int bgn, int end) {
|
||||
// put items in array for event
|
||||
int len = end - bgn;
|
||||
GfoListBase<E> old = new GfoListBase<>();
|
||||
for (int i = 0; i < len; i++) {
|
||||
old.Add(list.get(i + bgn));
|
||||
}
|
||||
}
|
||||
public void DelAt(int i) {
|
||||
list.remove(i);
|
||||
}
|
||||
public void DelBetween(int i) {DelBetween(i, list.size() - 1);}
|
||||
public void DelBetween(int bgn, int end) {
|
||||
// put items in array for event
|
||||
int len = end - bgn;
|
||||
GfoListBase<E> old = new GfoListBase<>();
|
||||
for (int i = 0; i < len; i++) {
|
||||
old.Add(list.get(i + bgn));
|
||||
}
|
||||
|
||||
// actually delete
|
||||
for (int i = bgn; i < end; i++) {
|
||||
// actually delete
|
||||
for (int i = bgn; i < end; i++) {
|
||||
list.remove(bgn);
|
||||
}
|
||||
if (eventsEnabled) {
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Del, old));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DelAtEnd() {
|
||||
int idx = list.size() - 1;
|
||||
E itm = list.get(idx);
|
||||
list.remove(idx);
|
||||
if (eventsEnabled) {
|
||||
public void DelAtEnd() {
|
||||
int idx = list.size() - 1;
|
||||
E itm = list.get(idx);
|
||||
list.remove(idx);
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Del, GfoListBase.NewFromArray(itm)));
|
||||
}
|
||||
}
|
||||
public void Clear() {
|
||||
GfoListBase<E> old = new GfoListBase<>();
|
||||
for (E itm : list)
|
||||
old.Add(itm);
|
||||
list.clear();
|
||||
if (eventsEnabled) {
|
||||
public void Clear() {
|
||||
GfoListBase<E> old = new GfoListBase<>();
|
||||
for (E itm : list)
|
||||
old.Add(itm);
|
||||
list.clear();
|
||||
if (eventsEnabled) {
|
||||
itemsChanged.Run(new ItemsChangedArg<>(ItemsChangedType.Clear, old));
|
||||
}
|
||||
}
|
||||
public void Sort(GfoComparator<E> comparator) {
|
||||
}
|
||||
public void Sort(GfoComparator<E> comparator) {
|
||||
list.sort(comparator);
|
||||
}
|
||||
public E[] ToAry(Class<?> clz) {
|
||||
int len = list.size();
|
||||
E[] rv = (E[])Array.newInstance(clz, len);
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = list.get(i);
|
||||
return rv;
|
||||
}
|
||||
public String[] ToStringAry() {
|
||||
int len = list.size();
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = list.get(i).toString();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
public E[] ToAry(Class<?> clz) {
|
||||
int len = list.size();
|
||||
E[] rv = (E[])Array.newInstance(clz, len);
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = list.get(i);
|
||||
return rv;
|
||||
}
|
||||
public String[] ToStringAry() {
|
||||
int len = list.size();
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = list.get(i).toString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
@@ -143,7 +156,7 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
}
|
||||
@Override
|
||||
public void remove() {
|
||||
throw Err_.New_unimplemented();
|
||||
throw ErrUtl.NewUnimplemented();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +1,50 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
import gplx.objects.errs.Err_;
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GfoSetBase<I> implements Iterable<I> {
|
||||
protected final Set<I> hash = new HashSet<>();
|
||||
protected final Set<I> hash = new HashSet<>();
|
||||
|
||||
public int Len() {return hash.size();}
|
||||
public void Clear() {hash.clear();}
|
||||
public GfoSetBase<I> AddMany(I... ary) {
|
||||
for (I itm : ary) {
|
||||
public int Len() {return hash.size();}
|
||||
public void Clear() {hash.clear();}
|
||||
public GfoSetBase<I> AddMany(I... ary) {
|
||||
for (I itm : ary) {
|
||||
Add(itm);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Add(GfoHashKeyFunc<I> keyFunc) {Add(keyFunc.ToHashKey());}
|
||||
public GfoSetBase<I> Add(I itm) {
|
||||
if (itm == null) {
|
||||
throw Err_.New_fmt("key cannot be null; val={0}", itm);
|
||||
}
|
||||
if (hash.contains(itm)) {
|
||||
throw Err_.New_fmt("key already exists: key={0} val={1}", itm);
|
||||
}
|
||||
hash.add(itm);
|
||||
}
|
||||
public void Add(GfoHashKeyFunc<I> keyFunc) {Add(keyFunc.ToHashKey());}
|
||||
public GfoSetBase<I> Add(I itm) {
|
||||
if (itm == null) {
|
||||
throw ErrUtl.NewFmt("key cannot be null; val={0}", itm);
|
||||
}
|
||||
if (hash.contains(itm)) {
|
||||
throw ErrUtl.NewFmt("key already exists: key={0} val={1}", itm);
|
||||
}
|
||||
hash.add(itm);
|
||||
return this;
|
||||
}
|
||||
public void Del(I itm) {hash.remove(itm);}
|
||||
public boolean Has(I itm) {return hash.contains(itm);}
|
||||
}
|
||||
public void Del(I itm) {hash.remove(itm);}
|
||||
public boolean Has(I itm) {return hash.contains(itm);}
|
||||
|
||||
@Override public Iterator<I> iterator() {return hash.iterator();}
|
||||
@Override public void forEach(Consumer<? super I> action) {hash.forEach(action);}
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public class ItemsChangedArg<T> {
|
||||
public ItemsChangedArg(ItemsChangedType type, GfoListBase<T> itms) {
|
||||
this.type = type;
|
||||
this.itms = itms;
|
||||
}
|
||||
public ItemsChangedType Type() {return type;} private final ItemsChangedType type;
|
||||
public GfoListBase<T> Itms() {return itms;} private final GfoListBase<T> itms;
|
||||
public T Itm() {return itms.GetAt(0);}
|
||||
public ItemsChangedArg(ItemsChangedType type, GfoListBase<T> itms) {
|
||||
this.type = type;
|
||||
this.itms = itms;
|
||||
}
|
||||
public ItemsChangedType Type() {return type;} private final ItemsChangedType type;
|
||||
public GfoListBase<T> Itms() {return itms;} private final GfoListBase<T> itms;
|
||||
public T Itm() {return itms.GetAt(0);}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
package gplx.objects.lists;
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
public enum ItemsChangedType {
|
||||
Add,
|
||||
Del,
|
||||
Set,
|
||||
Clear,
|
||||
Add,
|
||||
Del,
|
||||
Set,
|
||||
Clear,
|
||||
}
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ListUtil {
|
||||
public static byte[] ToArray(List<Byte> list) {
|
||||
int len = list.size();
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = list.get(i);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] ToArray(List<Byte> list) {
|
||||
int len = list.size();
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = list.get(i);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
62
baselib/src/gplx/objects/primitives/BoolUtl.java
Normal file
62
baselib/src/gplx/objects/primitives/BoolUtl.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.arrays.BryUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.lists.CompareAbleUtl;
|
||||
import gplx.objects.strings.AsciiByte;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
public class BoolUtl {
|
||||
public static final String ClsValName = "bool";
|
||||
public static final Class<?> ClsRefType = Boolean.class;
|
||||
|
||||
public static final boolean N = false , Y = true;
|
||||
public static final byte NByte = 0 , YByte = 1 , NullByte = 127;
|
||||
public static final int NInt = 0 , YInt = 1 , NullInt = -1;
|
||||
public static final String TrueStr = "true", FalseStr = "false";
|
||||
public static final byte[] NBry = new byte[] {AsciiByte.Ltr_n}, YBry = new byte[] {AsciiByte.Ltr_y};
|
||||
public static final byte[] TrueBry = BryUtl.NewA7(TrueStr) , FalseBry = BryUtl.NewA7(FalseStr);
|
||||
public static boolean ByInt(int v) {return v == YInt;}
|
||||
public static int ToInt(boolean v) {return v ? YInt : NInt;}
|
||||
public static byte ToByte(boolean v) {return v ? YByte : NByte;}
|
||||
public static String ToStrLower(boolean v) {return v ? TrueStr : FalseStr;}
|
||||
public static boolean Cast(Object o) {
|
||||
try {
|
||||
return (Boolean)o;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw ErrUtl.NewFmt(e, "failed to cast to boolean; obj={0}", ObjectUtl.ToStr(o));
|
||||
}
|
||||
}
|
||||
public static boolean Parse(String raw) {
|
||||
if ( StringUtl.Eq(raw, TrueStr)
|
||||
|| StringUtl.Eq(raw, "True") // needed for Store_Wtr(){boolVal.toString();}
|
||||
)
|
||||
return true;
|
||||
else if ( StringUtl.Eq(raw, FalseStr)
|
||||
|| StringUtl.Eq(raw, "False")
|
||||
)
|
||||
return false;
|
||||
else
|
||||
throw ErrUtl.NewParse(boolean.class, raw);
|
||||
}
|
||||
public static int Compare(boolean lhs, boolean rhs) {
|
||||
if ( lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if (!lhs && rhs) return CompareAbleUtl.Less;
|
||||
else /*lhs && !rhs*/ return CompareAbleUtl.More;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Bool_ {
|
||||
public static final String Cls_val_name = "bool";
|
||||
public static final Class<?> Cls_ref_type = Boolean.class;
|
||||
|
||||
public static final boolean N = false , Y = true;
|
||||
public static final byte N_byte = 0 , Y_byte = 1 , __byte = 127;
|
||||
public static final int N_int = 0 , Y_int = 1 , __int = -1;
|
||||
public static final String True_str = "true", False_str = "false";
|
||||
|
||||
|
||||
public static boolean Cast(Object o) {
|
||||
try {
|
||||
return (Boolean)o;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw Err_.New_fmt(e, "failed to cast to boolean; obj={0}", Object_.To_str(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,17 +13,18 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Byte_ {
|
||||
public static final String Cls_val_name = "byte";
|
||||
public static final Class<?> Cls_ref_type = Byte.class;
|
||||
package gplx.objects.primitives;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
public class ByteUtl {
|
||||
public static final String ClsValName = "byte";
|
||||
public static final Class<?> ClsRefType = Byte.class;
|
||||
public static byte Cast(Object o) {
|
||||
try {
|
||||
return (Byte)o;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw Err_.New_fmt(e, "failed to cast to byte; obj={0}", Object_.To_str(o));
|
||||
throw ErrUtl.NewFmt(e, "failed to cast to byte; obj={0}", ObjectUtl.ToStr(o));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,13 +13,12 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
public class Char_code_ {
|
||||
public static final char
|
||||
New_line = '\n'
|
||||
, Space = ' '
|
||||
, Colon = ':'
|
||||
, Num_0 = '0'
|
||||
, Pipe = '|'
|
||||
;
|
||||
}
|
||||
package gplx.objects.primitives;
|
||||
public class CharCode {
|
||||
public static final char
|
||||
NewLine = '\n',
|
||||
Space = ' ',
|
||||
Colon = ':',
|
||||
Num0 = '0',
|
||||
Pipe = '|';
|
||||
}
|
||||
20
baselib/src/gplx/objects/primitives/CharUtl.java
Normal file
20
baselib/src/gplx/objects/primitives/CharUtl.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
public class CharUtl {
|
||||
public static final String ClsValName = "char";
|
||||
public static final Class<?> ClsRefType = Character.class;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -14,10 +14,9 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
|
||||
public class Double_ {
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
public class DoubleUtl {
|
||||
public static final String ClsValName = "double";
|
||||
public static final Class<?> ClsRefType = Double.class;
|
||||
|
||||
public static String ToStrByPrintF(double val) {
|
||||
// call sprintf-like format; EX:"sprintf((s), "%.14g", (n));"
|
||||
20
baselib/src/gplx/objects/primitives/FloatUtl.java
Normal file
20
baselib/src/gplx/objects/primitives/FloatUtl.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
public class FloatUtl {
|
||||
public static final String ClsValName = "float";
|
||||
public static final Class<?> ClsRefType = Float.class;
|
||||
}
|
||||
110
baselib/src/gplx/objects/primitives/IntUtl.java
Normal file
110
baselib/src/gplx/objects/primitives/IntUtl.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
public class IntUtl {
|
||||
public static final String ClsValName = "int";
|
||||
public static final Class<?> ClsRefType = Integer.class;
|
||||
|
||||
public static final int
|
||||
MinValue = Integer.MIN_VALUE,
|
||||
MaxValue = Integer.MAX_VALUE,
|
||||
MaxValue31 = 2147483647,
|
||||
Neg1 = -1,
|
||||
Null = IntUtl.MinValue,
|
||||
Base1 = 1, // for base-1 lists / arrays; EX: PHP; [a, b, c]; [1] => a
|
||||
Offset1 = 1; // common symbol for + 1 after current pos; EX: StringUtl.Mid(lhs + Offset1, rhs)
|
||||
|
||||
public static int Cast(Object o) {
|
||||
try {
|
||||
return (Integer)o;
|
||||
}
|
||||
catch(Exception e) {
|
||||
throw ErrUtl.NewFmt(e, "failed to cast to int; obj={0}", ObjectUtl.ToStr(o));
|
||||
}
|
||||
}
|
||||
public static String ToStr(int v) {return new Integer(v).toString();}
|
||||
public static int ParseOr(String raw, int or) {
|
||||
// process args
|
||||
if (raw == null) return or;
|
||||
int rawLen = StringUtl.Len(raw);
|
||||
if (rawLen == 0) return or;
|
||||
|
||||
// loop backwards from nth to 0th char
|
||||
int rv = 0, powerOf10 = 1;
|
||||
for (int idx = rawLen - 1; idx >= 0; idx--) {
|
||||
char cur = StringUtl.CharAt(raw, idx);
|
||||
int digit = -1;
|
||||
switch (cur) {
|
||||
// numbers -> assign digit
|
||||
case '0': digit = 0; break; case '1': digit = 1; break; case '2': digit = 2; break; case '3': digit = 3; break; case '4': digit = 4; break;
|
||||
case '5': digit = 5; break; case '6': digit = 6; break; case '7': digit = 7; break; case '8': digit = 8; break; case '9': digit = 9; break;
|
||||
|
||||
// negative sign
|
||||
case '-':
|
||||
if (idx != 0) { // invalid if not 1st
|
||||
return or;
|
||||
}
|
||||
else { // is first; multiply by -1
|
||||
rv *= -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// anything else
|
||||
default:
|
||||
return or;
|
||||
}
|
||||
rv += (digit * powerOf10);
|
||||
powerOf10 *= 10;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static boolean Between(int v, int lhs, int rhs) {
|
||||
int lhsComp = v == lhs ? 0 : (v < lhs ? -1 : 1);
|
||||
int rhsComp = v == rhs ? 0 : (v < rhs ? -1 : 1);
|
||||
return (lhsComp * rhsComp) != 1; // 1 when v is (a) greater than both or (b) less than both
|
||||
}
|
||||
|
||||
private static int[] Log10Vals = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, IntUtl.MaxValue};
|
||||
public static int Log10(int v) {
|
||||
if (v == 0) return 0;
|
||||
int sign = 1;
|
||||
if (v < 0) {
|
||||
if (v == IntUtl.MinValue) return -9; // NOTE: IntUtl.MinValue * -1 = IntUtl.MinValue
|
||||
v *= -1;
|
||||
sign = -1;
|
||||
}
|
||||
int log10sLen = Log10Vals.length;
|
||||
int rv = log10sLen - 2; // rv will only happen when v == IntUtl.MaxValue
|
||||
int bgn = 0;
|
||||
if (v > 1000) { // optimization to reduce number of ops to < 5
|
||||
bgn = 3;
|
||||
if (v > 1000000) bgn = 6;
|
||||
}
|
||||
for (int i = bgn; i < log10sLen; i++) {
|
||||
if (v < Log10Vals[i]) {rv = i - 1; break;}
|
||||
}
|
||||
return rv * sign;
|
||||
}
|
||||
|
||||
public static int CountDigits(int v) {
|
||||
int log10 = Log10(v);
|
||||
return v > -1 ? log10 + 1 : log10 * -1 + 2;
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
import gplx.objects.strings.*;
|
||||
public class Int_ {
|
||||
public static final String Cls_val_name = "int";
|
||||
public static final Class<?> Cls_ref_type = Integer.class;
|
||||
|
||||
public static final int
|
||||
Min_value = Integer.MIN_VALUE
|
||||
, Max_value = Integer.MAX_VALUE
|
||||
, Max_value__31 = 2147483647
|
||||
, Neg1 = -1
|
||||
, Null = Int_.Min_value
|
||||
, Base1 = 1 // for super 1 lists / arrays; EX: PHP; [a, b, c]; [1] => a
|
||||
, Offset_1 = 1 // common symbol for + 1 after current pos; EX: String_.Mid(lhs + Offset_1, rhs)
|
||||
;
|
||||
|
||||
public static int Cast(Object o) {
|
||||
try {
|
||||
return (Integer)o;
|
||||
}
|
||||
catch(Exception e) {
|
||||
throw Err_.New_fmt(e, "failed to cast to int; obj={0}", Object_.To_str(o));
|
||||
}
|
||||
}
|
||||
|
||||
public static String To_str(int v) {return new Integer(v).toString();}
|
||||
|
||||
public static int Parse_or(String raw, int or) {
|
||||
// process args
|
||||
if (raw == null) return or;
|
||||
int raw_len = String_.Len(raw);
|
||||
if (raw_len == 0) return or;
|
||||
|
||||
// loop backwards from nth to 0th char
|
||||
int rv = 0, power_of_10 = 1;
|
||||
for (int idx = raw_len - 1; idx >= 0; idx--) {
|
||||
char cur = String_.Char_at(raw, idx);
|
||||
int digit = -1;
|
||||
switch (cur) {
|
||||
// numbers -> assign digit
|
||||
case '0': digit = 0; break; case '1': digit = 1; break; case '2': digit = 2; break; case '3': digit = 3; break; case '4': digit = 4; break;
|
||||
case '5': digit = 5; break; case '6': digit = 6; break; case '7': digit = 7; break; case '8': digit = 8; break; case '9': digit = 9; break;
|
||||
|
||||
// negative sign
|
||||
case '-':
|
||||
if (idx != 0) { // invalid if not 1st
|
||||
return or;
|
||||
}
|
||||
else { // is first; multiply by -1
|
||||
rv *= -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// anything else
|
||||
default:
|
||||
return or;
|
||||
}
|
||||
rv += (digit * power_of_10);
|
||||
power_of_10 *= 10;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static boolean Between(int v, int lhs, int rhs) {
|
||||
int lhs_comp = v == lhs ? 0 : (v < lhs ? -1 : 1);
|
||||
int rhs_comp = v == rhs ? 0 : (v < rhs ? -1 : 1);
|
||||
return (lhs_comp * rhs_comp) != 1; // 1 when v is (a) greater than both or (b) less than both
|
||||
}
|
||||
|
||||
private static int[] Log_10s = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, Int_.Max_value};
|
||||
public static int Log10(int v) {
|
||||
if (v == 0) return 0;
|
||||
int sign = 1;
|
||||
if (v < 0) {
|
||||
if (v == Int_.Min_value) return -9; // NOTE: Int_.Min_value * -1 = Int_.Min_value
|
||||
v *= -1;
|
||||
sign = -1;
|
||||
}
|
||||
int log_10s_len = Log_10s.length;
|
||||
int rv = log_10s_len - 2; // rv will only happen when v == Int_.Max_value
|
||||
int bgn = 0;
|
||||
if (v > 1000) { // optimization to reduce number of ops to < 5
|
||||
bgn = 3;
|
||||
if (v > 1000000) bgn = 6;
|
||||
}
|
||||
for (int i = bgn; i < log_10s_len; i++) {
|
||||
if (v < Log_10s[i]) {rv = i - 1; break;}
|
||||
}
|
||||
return rv * sign;
|
||||
}
|
||||
|
||||
public static int Count_digits(int v) {
|
||||
int log10 = Log10(v);
|
||||
return v > -1 ? log10 + 1 : log10 * -1 + 2;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
import org.junit.*; import gplx.tests.*;
|
||||
public class Int__tst {
|
||||
private final Int__fxt fxt = new Int__fxt();
|
||||
@Test public void Parse_or() {
|
||||
fxt.Test__Parse_or("123", 123); // basic
|
||||
fxt.Test__Parse_or_min_value(null); // null
|
||||
fxt.Test__Parse_or_min_value(""); // empty
|
||||
fxt.Test__Parse_or_min_value("1a"); // invalid number
|
||||
|
||||
fxt.Test__Parse_or("-123", -123); // negative
|
||||
fxt.Test__Parse_or_min_value("1-23"); // negative at invalid position
|
||||
}
|
||||
@Test public void Between() {
|
||||
fxt.Test__Between(1, 0, 2, true); // simple true
|
||||
fxt.Test__Between(3, 0, 2, false); // simple false
|
||||
fxt.Test__Between(0, 0, 2, true); // bgn true
|
||||
fxt.Test__Between(2, 0, 2, true); // end true
|
||||
}
|
||||
@Test public void Count_digits() {
|
||||
fxt.Test__Count_digits( 0, 1);
|
||||
fxt.Test__Count_digits( 9, 1);
|
||||
fxt.Test__Count_digits( 100, 3);
|
||||
fxt.Test__Count_digits( -1, 2);
|
||||
fxt.Test__Count_digits(-100, 4);
|
||||
}
|
||||
@Test public void Log10() {
|
||||
fxt.Test__Log10( 0, 0);
|
||||
fxt.Test__Log10( 1, 0);
|
||||
fxt.Test__Log10( 2, 0);
|
||||
fxt.Test__Log10( 10, 1);
|
||||
fxt.Test__Log10( 12, 1);
|
||||
fxt.Test__Log10( 100, 2);
|
||||
fxt.Test__Log10( 123, 2);
|
||||
fxt.Test__Log10( 1000, 3);
|
||||
fxt.Test__Log10( 1234, 3);
|
||||
fxt.Test__Log10( 10000, 4);
|
||||
fxt.Test__Log10( 12345, 4);
|
||||
fxt.Test__Log10( 100000, 5);
|
||||
fxt.Test__Log10( 123456, 5);
|
||||
fxt.Test__Log10( 1000000, 6);
|
||||
fxt.Test__Log10( 1234567, 6);
|
||||
fxt.Test__Log10( 10000000, 7);
|
||||
fxt.Test__Log10( 12345678, 7);
|
||||
fxt.Test__Log10( 100000000, 8);
|
||||
fxt.Test__Log10( 123456789, 8);
|
||||
fxt.Test__Log10( 1000000000, 9);
|
||||
fxt.Test__Log10( 1234567890, 9);
|
||||
fxt.Test__Log10(Int_.Max_value, 9);
|
||||
fxt.Test__Log10( -1, 0);
|
||||
fxt.Test__Log10( -10, -1);
|
||||
fxt.Test__Log10( -100, -2);
|
||||
fxt.Test__Log10( -1000000, -6);
|
||||
fxt.Test__Log10( -1000000000, -9);
|
||||
fxt.Test__Log10(Int_.Min_value, -9);
|
||||
fxt.Test__Log10(Int_.Min_value + 1, -9);
|
||||
}
|
||||
}
|
||||
class Int__fxt {
|
||||
public void Test__Parse_or(String raw, int expd) {
|
||||
Gftest_fxt.Eq__int(expd, Int_.Parse_or(raw, -1));
|
||||
}
|
||||
public void Test__Parse_or_min_value(String raw) {
|
||||
Gftest_fxt.Eq__int(Int_.Min_value, Int_.Parse_or(raw, Int_.Min_value));
|
||||
}
|
||||
public void Test__Between(int val, int lhs, int rhs, boolean expd) {
|
||||
Gftest_fxt.Eq__bool(expd, Int_.Between(val, lhs, rhs));
|
||||
}
|
||||
public void Test__Count_digits(int val, int expd) {
|
||||
Gftest_fxt.Eq__int(expd, Int_.Count_digits(val), Int_.To_str(val));
|
||||
}
|
||||
public void Test__Log10(int val, int expd) {
|
||||
Gftest_fxt.Eq__int(expd, Int_.Log10(val));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,17 +13,19 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Long_ {
|
||||
public static final String Cls_val_name = "long";
|
||||
public static final Class<?> Cls_ref_type = Long.class;
|
||||
package gplx.objects.primitives;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
public class LongUtl {
|
||||
public static final String ClsValName = "long";
|
||||
public static final Class<?> ClsRefType = Long.class;
|
||||
public static long Cast(Object o) {
|
||||
try {
|
||||
return (Long)o;
|
||||
}
|
||||
catch(Exception e) {
|
||||
throw Err_.New_fmt(e, "failed to cast to long; obj={0}", Object_.To_str(o));
|
||||
throw ErrUtl.NewFmt(e, "failed to cast to long; obj={0}", ObjectUtl.ToStr(o));
|
||||
}
|
||||
}
|
||||
public static String ToStr(long v) {return new Long(v).toString();}
|
||||
}
|
||||
20
baselib/src/gplx/objects/primitives/ShortUtl.java
Normal file
20
baselib/src/gplx/objects/primitives/ShortUtl.java
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
public class ShortUtl {
|
||||
public static final String ClsValName = "short";
|
||||
public static final Class<?> ClsRefType = Short.class;
|
||||
}
|
||||
119
baselib/src/gplx/objects/strings/AsciiByte.java
Normal file
119
baselib/src/gplx/objects/strings/AsciiByte.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
public class AsciiByte {
|
||||
public static final byte
|
||||
Null = 0 , Backfeed = 8, Tab = 9,
|
||||
Nl = 10, VerticalTab = 11, Formfeed = 12, Cr = 13,
|
||||
Escape = 27,
|
||||
Space = 32, Bang = 33, Quote = 34,
|
||||
Hash = 35, Dollar = 36, Percent = 37, Amp = 38, Apos = 39,
|
||||
ParenBgn = 40, ParenEnd = 41, Star = 42, Plus = 43, Comma = 44,
|
||||
Dash = 45, Dot = 46, Slash = 47, Num0 = 48, Num1 = 49,
|
||||
Num2 = 50, Num3 = 51, Num4 = 52, Num5 = 53, Num6 = 54,
|
||||
Num7 = 55, Num8 = 56, Num9 = 57, Colon = 58, Semic = 59,
|
||||
Lt = 60, Eq = 61, Gt = 62, Question = 63, At = 64,
|
||||
Ltr_A = 65, Ltr_B = 66, Ltr_C = 67, Ltr_D = 68, Ltr_E = 69,
|
||||
Ltr_F = 70, Ltr_G = 71, Ltr_H = 72, Ltr_I = 73, Ltr_J = 74,
|
||||
Ltr_K = 75, Ltr_L = 76, Ltr_M = 77, Ltr_N = 78, Ltr_O = 79,
|
||||
Ltr_P = 80, Ltr_Q = 81, Ltr_R = 82, Ltr_S = 83, Ltr_T = 84,
|
||||
Ltr_U = 85, Ltr_V = 86, Ltr_W = 87, Ltr_X = 88, Ltr_Y = 89,
|
||||
Ltr_Z = 90, BrackBgn = 91, Backslash = 92, BrackEnd = 93, Pow = 94, // Circumflex
|
||||
Underline = 95, Tick = 96, Ltr_a = 97, Ltr_b = 98, Ltr_c = 99,
|
||||
Ltr_d = 100, Ltr_e = 101, Ltr_f = 102, Ltr_g = 103, Ltr_h = 104,
|
||||
Ltr_i = 105, Ltr_j = 106, Ltr_k = 107, Ltr_l = 108, Ltr_m = 109,
|
||||
Ltr_n = 110, Ltr_o = 111, Ltr_p = 112, Ltr_q = 113, Ltr_r = 114,
|
||||
Ltr_s = 115, Ltr_t = 116, Ltr_u = 117, Ltr_v = 118, Ltr_w = 119,
|
||||
Ltr_x = 120, Ltr_y = 121, Ltr_z = 122, CurlyBgn = 123, Pipe = 124,
|
||||
CurlyEnd = 125, Tilde = 126, Delete = 127;
|
||||
|
||||
public static final byte
|
||||
AngleBgn = Lt,
|
||||
AngleEnd = Gt;
|
||||
|
||||
public static final int Len1 = 1;
|
||||
public static final byte Max7Bit = 127, AsciiMin = 0, AsciiMax = 127;
|
||||
public static boolean IsLtr(byte b) {
|
||||
return ( b >= Ltr_a && b <= Ltr_z
|
||||
|| b >= Ltr_A && b <= Ltr_Z);
|
||||
}
|
||||
public static boolean IsWs(byte b) {
|
||||
switch (b) {
|
||||
case Tab: case Nl: case Cr: case Space: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static boolean IsNum(byte b) {
|
||||
return b > Slash && b < Colon;
|
||||
}
|
||||
public static byte ToA7Int(byte b) {return (byte)(b - Num0);}
|
||||
public static byte ToA7Str(int digit) {
|
||||
switch (digit) {
|
||||
case 0: return Num0; case 1: return Num1; case 2: return Num2; case 3: return Num3; case 4: return Num4;
|
||||
case 5: return Num5; case 6: return Num6; case 7: return Num7; case 8: return Num8; case 9: return Num9;
|
||||
default: throw ErrUtl.NewFmt("unknown digit; digit={0}", digit);
|
||||
}
|
||||
}
|
||||
public static String ToStr(byte b) {return String.valueOf((char)b);}
|
||||
public static byte CaseUpper(byte b) {
|
||||
return b > 96 && b < 123
|
||||
? (byte)(b - 32)
|
||||
: b;
|
||||
}
|
||||
public static byte CaseLower(byte b) {
|
||||
return b > 64 && b < 91
|
||||
? (byte)(b + 32)
|
||||
: b;
|
||||
}
|
||||
public static final byte[]
|
||||
TabBry = new byte[] {Tab},
|
||||
NlBry = new byte[] {Nl},
|
||||
SpaceBry = new byte[] {Space},
|
||||
BangBry = new byte[] {Bang},
|
||||
QuoteBry = new byte[] {Quote},
|
||||
HashBry = new byte[] {Hash},
|
||||
DotBry = new byte[] {Dot},
|
||||
AngleBgnBry = new byte[] {AngleBgn},
|
||||
AngleEndBry = new byte[] {AngleEnd},
|
||||
CommaBry = new byte[] {Comma},
|
||||
ColonBry = new byte[] {Colon},
|
||||
SemicBry = new byte[] {Semic},
|
||||
EqBry = new byte[] {Eq},
|
||||
AmpBry = new byte[] {Amp},
|
||||
LtBry = new byte[] {Lt},
|
||||
GtBry = new byte[] {Gt},
|
||||
QuestionBry = new byte[] {Question},
|
||||
BrackBgnBry = new byte[] {BrackBgn},
|
||||
BrackEndBry = new byte[] {BrackEnd},
|
||||
AposBry = new byte[] {Apos},
|
||||
PipeBry = new byte[] {Pipe},
|
||||
UnderlineBry = new byte[] {Underline},
|
||||
SlashBry = new byte[] {Slash},
|
||||
StarBry = new byte[] {Star},
|
||||
DashBry = new byte[] {Dash},
|
||||
CrLfBry = new byte[] {Cr, Nl},
|
||||
Num0Bry = new byte[] {Num0},
|
||||
Num1Bry = new byte[] {Num1};
|
||||
}
|
||||
/*
|
||||
SYMBOLS
|
||||
-------
|
||||
Bang | Slash | 33 -> 47 | !"#$%&'()*+,-./
|
||||
Colon | At | 58 -> 64 | :;<=>?@
|
||||
BrackBgn | Tick | 91 -> 96 | [\]^_`
|
||||
CurlyBgn | Tilde | 123 -> 126 | {|}~
|
||||
*/
|
||||
96
baselib/src/gplx/objects/strings/StringUtl.java
Normal file
96
baselib/src/gplx/objects/strings/StringUtl.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.arrays.ArrayUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.primitives.IntUtl;
|
||||
import gplx.objects.strings.bfrs.GfoStrBldr;
|
||||
public class StringUtl {
|
||||
public static final Class<?> ClsRefType = String.class;
|
||||
public static final String ClsValName = "str" + "ing";
|
||||
public static final int FindNone = -1, PosNeg1 = -1;
|
||||
public static final String Empty = "", NullMark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n";
|
||||
|
||||
public static boolean Eq(String lhs, String rhs) {return lhs == null ? rhs == null : lhs.equals(rhs);}
|
||||
public static int Len(String s) {return s.length();}
|
||||
public static char CharAt(String s, int i) {return s.charAt(i);}
|
||||
|
||||
// use C# flavor ("a {0}") rather than Java format ("a %s"); also: (a) don't fail on format errors; (b) escape brackets by doubling
|
||||
private static final char FormatItmLhs = '{', FormatItmRhs = '}';
|
||||
public static String Format(String fmt, Object... args) {
|
||||
// method vars
|
||||
int argsLen = ArrayUtl.LenObjAry(args);
|
||||
if (argsLen == 0) return fmt; // nothing to format
|
||||
int fmtLen = Len(fmt);
|
||||
|
||||
// loop vars
|
||||
int pos = 0; String argIdxStr = ""; boolean insideBrackets = false;
|
||||
GfoStrBldr bfr = new GfoStrBldr();
|
||||
while (pos < fmtLen) { // loop over every char; NOTE: UT8-SAFE b/c only checking for "{"; "}"
|
||||
char c = CharAt(fmt, pos);
|
||||
if (insideBrackets) {
|
||||
if (c == FormatItmLhs) { // first FormatItmLhs is fake; add FormatItmLhs and whatever is in argIdxStr
|
||||
bfr.AddChar(FormatItmLhs).Add(argIdxStr);
|
||||
argIdxStr = "";
|
||||
}
|
||||
else if (c == FormatItmRhs) { // itm completed
|
||||
int argsIdx = IntUtl.ParseOr(argIdxStr, IntUtl.MinValue);
|
||||
String itm = argsIdx != IntUtl.MinValue && IntUtl.Between(argsIdx, 0, argsLen - 1) // check (a) argsIdx is num; (b) argsIdx is in bounds
|
||||
? ObjectUtl.ToStrOrNullMark(args[argsIdx]) // valid; add itm
|
||||
: FormatItmLhs + argIdxStr + FormatItmRhs; // not valid; just add String
|
||||
bfr.Add(itm);
|
||||
insideBrackets = false;
|
||||
argIdxStr = "";
|
||||
}
|
||||
else
|
||||
argIdxStr += c;
|
||||
}
|
||||
else {
|
||||
if (c == FormatItmLhs || c == FormatItmRhs) {
|
||||
boolean posIsEnd = pos == fmtLen - 1;
|
||||
if (posIsEnd) // last char is "{" or "}" (and not insideBrackets); ignore and just ad
|
||||
bfr.AddChar(c);
|
||||
else {
|
||||
char next = CharAt(fmt, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
bfr.AddChar(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
insideBrackets = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.AddChar(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (Len(argIdxStr) > 0) // unclosed bracket; add FormatItmLhs and whatever is in argIdxStr; ex: "{0"
|
||||
bfr.AddChar(FormatItmLhs).Add(argIdxStr);
|
||||
return bfr.ToStr();
|
||||
}
|
||||
|
||||
public static String NewByBryUtf8(byte[] v) {return v == null ? null : NewByBryUtf8(v, 0, v.length);}
|
||||
public static String NewByBryUtf8(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "UTF-8");
|
||||
}
|
||||
catch (Exception e) {throw ErrUtl.NewFmt(e, "unsupported encoding; bgn={0} end={1}", bgn, end);}
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings; import gplx.*; import gplx.objects.*;
|
||||
import java.lang.*;
|
||||
import gplx.objects.errs.*;
|
||||
import gplx.objects.strings.bfrs.*;
|
||||
import gplx.objects.arrays.*; import gplx.objects.primitives.*;
|
||||
public class String_ {
|
||||
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 Empty = "", Null_mark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n";
|
||||
|
||||
public static boolean Eq(String lhs, String rhs) {return lhs == null ? rhs == null : lhs.equals(rhs);}
|
||||
public static int Len(String s) {return s.length();}
|
||||
public static char Char_at(String s, int i) {return s.charAt(i);}
|
||||
|
||||
// use C# flavor ("a {0}") rather than Java format ("a %s"); also: (a) don't fail on format errors; (b) escape brackets by doubling
|
||||
private static final char FORMAT_ITM_LHS = '{', FORMAT_ITM_RHS = '}';
|
||||
public static String Format(String fmt, Object... args) {
|
||||
// method vars
|
||||
int args_len = Array_.Len_obj(args);
|
||||
if (args_len == 0) return fmt; // nothing to format
|
||||
int fmt_len = Len(fmt);
|
||||
|
||||
// loop vars
|
||||
int pos = 0; String arg_idx_str = ""; boolean inside_brackets = false;
|
||||
String_bfr bfr = new String_bfr();
|
||||
while (pos < fmt_len) { // loop over every char; NOTE: UT8-SAFE b/c only checking for "{"; "}"
|
||||
char c = Char_at(fmt, pos);
|
||||
if (inside_brackets) {
|
||||
if (c == FORMAT_ITM_LHS) { // first FORMAT_ITM_LHS is fake; add FORMAT_ITM_LHS and whatever is in arg_idx_str
|
||||
bfr.Add_char(FORMAT_ITM_LHS).Add(arg_idx_str);
|
||||
arg_idx_str = "";
|
||||
}
|
||||
else if (c == FORMAT_ITM_RHS) { // itm completed
|
||||
int args_idx = Int_.Parse_or(arg_idx_str, Int_.Min_value);
|
||||
String itm = args_idx != Int_.Min_value && Int_.Between(args_idx, 0, args_len - 1) // check (a) args_idx is num; (b) args_idx is in bounds
|
||||
? Object_.To_str_or_null_mark(args[args_idx]) // valid; add itm
|
||||
: FORMAT_ITM_LHS + arg_idx_str + FORMAT_ITM_RHS; // not valid; just add String
|
||||
bfr.Add(itm);
|
||||
inside_brackets = false;
|
||||
arg_idx_str = "";
|
||||
}
|
||||
else
|
||||
arg_idx_str += c;
|
||||
}
|
||||
else {
|
||||
if (c == FORMAT_ITM_LHS || c == FORMAT_ITM_RHS) {
|
||||
boolean pos_is_end = pos == fmt_len - 1;
|
||||
if (pos_is_end) // last char is "{" or "}" (and not inside_brackets); ignore and just ad
|
||||
bfr.Add_char(c);
|
||||
else {
|
||||
char next = Char_at(fmt, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
bfr.Add_char(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
inside_brackets = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.Add_char(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (Len(arg_idx_str) > 0) // unclosed bracket; add FORMAT_ITM_LHS and whatever is in arg_idx_str; ex: "{0"
|
||||
bfr.Add_char(FORMAT_ITM_LHS).Add(arg_idx_str);
|
||||
return bfr.To_str();
|
||||
}
|
||||
|
||||
public static String New_bry_utf8(byte[] v) {return v == null ? null : New_bry_utf8(v, 0, v.length);}
|
||||
public static String New_bry_utf8(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "UTF-8");
|
||||
}
|
||||
catch (Exception e) {throw Err_.New_fmt(e, "unsupported encoding; bgn={0} end={1}", bgn, end);}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings; import gplx.*; import gplx.objects.*;
|
||||
import org.junit.*; import gplx.tests.*;
|
||||
public class String__tst {
|
||||
private final String__fxt fxt = new String__fxt();
|
||||
@Test public void Len() {
|
||||
fxt.Test__Len("" , 0);
|
||||
fxt.Test__Len("abc", 3);
|
||||
}
|
||||
@Test public void Format() {
|
||||
fxt.Test__Format("" , ""); // empty fmt
|
||||
fxt.Test__Format("" , "", "a"); // empty fmt w/ args
|
||||
fxt.Test__Format("a" , "a"); // no args
|
||||
fxt.Test__Format("a" , "{0}", "a"); // args = 1
|
||||
fxt.Test__Format("a + b" , "{0} + {1}", "a", "b"); // args = n
|
||||
fxt.Test__Format("{" , "{{", 0); // escape "{"
|
||||
fxt.Test__Format("}" , "}}", 0); // escape "}"
|
||||
fxt.Test__Format("{a0c}" , "{a{0}c}", 0); // nested;
|
||||
fxt.Test__Format("{a{b}c}" , "{a{b}c}", 0); // nested; invalid
|
||||
fxt.Test__Format("{1}" , "{1}", "a"); // out of bounds
|
||||
fxt.Test__Format("{a} {b}" , "{a} {b}", 0); // invalid arg
|
||||
fxt.Test__Format("{a}0{b}1", "{a}{0}{b}{1}", 0, 1); // invalid and valid args
|
||||
fxt.Test__Format("{0", "{0", 0); // dangling
|
||||
}
|
||||
}
|
||||
class String__fxt {
|
||||
public void Test__Format(String expd, String fmt, Object... ary) {
|
||||
Gftest_fxt.Eq__str(expd, String_.Format(fmt, ary));
|
||||
}
|
||||
public void Test__Len(String v, int expd) {
|
||||
Gftest_fxt.Eq__int(expd, String_.Len(v));
|
||||
}
|
||||
}
|
||||
88
baselib/src/gplx/objects/strings/bfrs/GfoStrBldr.java
Normal file
88
baselib/src/gplx/objects/strings/bfrs/GfoStrBldr.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.bfrs;
|
||||
import gplx.objects.primitives.BoolUtl;
|
||||
import gplx.objects.primitives.CharCode;
|
||||
import gplx.objects.primitives.IntUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
import gplx.objects.strings.unicodes.UstringUtl;
|
||||
public class GfoStrBldr {
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
public int Len() {return sb.length();}
|
||||
public boolean HasNone() {return this.Len() == 0;}
|
||||
public boolean HasSome() {return this.Len() > 0;}
|
||||
public GfoStrBldr Clear() {Del(0, this.Len()); return this;}
|
||||
public GfoStrBldr Del(int bgn, int len) {sb.delete(bgn, len); return this;}
|
||||
public GfoStrBldr AddFmt(String format, Object... args) {Add(StringUtl.Format(format, args)); return this;}
|
||||
public GfoStrBldr AddAt(int idx, String s) {sb.insert(idx, s); return this;}
|
||||
public GfoStrBldr Add(String s) {sb.append(s); return this;}
|
||||
public GfoStrBldr AddChar(char c) {sb.append(c); return this;}
|
||||
public GfoStrBldr AddByte(byte i) {sb.append(i); return this;}
|
||||
public GfoStrBldr AddInt(int i) {sb.append(i); return this;}
|
||||
public GfoStrBldr AddLong(long i) {sb.append(i); return this;}
|
||||
public GfoStrBldr AddDouble(double i) {sb.append(i); return this;}
|
||||
public GfoStrBldr AddObj(Object o) {sb.append(o); return this;}
|
||||
public GfoStrBldr AddBry(byte[] v) {
|
||||
if (v != null)
|
||||
sb.append(StringUtl.NewByBryUtf8(v));
|
||||
return this;
|
||||
}
|
||||
public GfoStrBldr AddMid(String s, int bgn) {sb.append(s, bgn, s.length()); return this;}
|
||||
public GfoStrBldr AddMid(String s, int bgn, int count) {sb.append(s, bgn, count); return this;}
|
||||
public GfoStrBldr AddBool(boolean val) {
|
||||
this.Add(val ? BoolUtl.TrueStr : BoolUtl.FalseStr);
|
||||
return this;
|
||||
}
|
||||
public GfoStrBldr AddBoolAsYn(boolean val) {
|
||||
this.Add(val ? "y" : "n");
|
||||
return this;
|
||||
}
|
||||
public GfoStrBldr AddCharNl() {return AddChar(CharCode.NewLine);}
|
||||
public GfoStrBldr AddCharSpace() {return AddChar(CharCode.Space);}
|
||||
public GfoStrBldr AddCharColon() {return AddChar(CharCode.Colon);}
|
||||
public GfoStrBldr AddCharRepeat(char c, int repeat) {
|
||||
this.EnsureCapacity(this.Len() + repeat);
|
||||
for (int i = 0; i < repeat; i++)
|
||||
AddChar(c);
|
||||
return this;
|
||||
}
|
||||
public GfoStrBldr AddCharByCode(int code) {
|
||||
if (code >= UstringUtl.SurrogateCpBgn && code <= UstringUtl.SurrogateCpEnd) {
|
||||
sb.append((char)((code - 0x10000) / 0x400 + 0xD800));
|
||||
sb.append((char)((code - 0x10000) % 0x400 + 0xDC00));
|
||||
}
|
||||
else {
|
||||
sb.append((char)code);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoStrBldr AddIntPadBgn(char padChar, int strLen, int val) {
|
||||
int digitLen = IntUtl.CountDigits(val);
|
||||
int padLen = strLen - digitLen;
|
||||
if (padLen > 0) // note that this skips padLen == 0, as well as guarding against negative padLen; EX: pad(" ", 3, 1234) -> "1234"
|
||||
AddCharRepeat(padChar, padLen);
|
||||
AddInt(val);
|
||||
return this;
|
||||
}
|
||||
public String ToStr() {return sb.toString();}
|
||||
public String ToStrAndClear() {
|
||||
String rv = ToStr();
|
||||
Clear();
|
||||
return rv;
|
||||
}
|
||||
@Override public String toString() {return ToStr();}
|
||||
private void EnsureCapacity(int capacity) {sb.ensureCapacity(capacity);}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package gplx.objects.strings.bfrs;
|
||||
|
||||
import gplx.objects.strings.String_;
|
||||
|
||||
public class GfoStringBuilder {
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
public int Len() {return sb.length();}
|
||||
public GfoStringBuilder Clear() {
|
||||
sb.delete(0, sb.length());
|
||||
return this;
|
||||
}
|
||||
public GfoStringBuilder AddNl() {return Add("\n");}
|
||||
public GfoStringBuilder Add(int v) {sb.append(v); return this;}
|
||||
public GfoStringBuilder Add(String v) {sb.append(v); return this;}
|
||||
public GfoStringBuilder Add(char v) {sb.append(v); return this;}
|
||||
public GfoStringBuilder AddObj(Object v) {sb.append(v); return this;}
|
||||
public GfoStringBuilder AddMid(String s, int bgn) {sb.append(s, bgn, s.length()); return this;}
|
||||
public GfoStringBuilder AddMid(String s, int bgn, int end) {sb.append(s, bgn, end); return this;}
|
||||
public GfoStringBuilder AddFmt(String fmt, Object... args) {
|
||||
sb.append(String_.Format(fmt, args));
|
||||
return this;
|
||||
}
|
||||
public GfoStringBuilder AddRepeat(char c, int repeat) {
|
||||
sb.ensureCapacity(this.Len() + repeat);
|
||||
for (int i = 0; i < repeat; i++)
|
||||
sb.append(c);
|
||||
return this;
|
||||
}
|
||||
public String ToStr() {return sb.toString();}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.bfrs; import gplx.*; import gplx.objects.*; import gplx.objects.strings.*;
|
||||
import java.lang.*;
|
||||
import gplx.objects.primitives.*;
|
||||
import gplx.objects.errs.*;
|
||||
import gplx.objects.strings.unicodes.*;
|
||||
public class String_bfr {
|
||||
private java.lang.StringBuilder sb = new java.lang.StringBuilder();
|
||||
public boolean Has_none() {return this.Len() == 0;}
|
||||
public boolean Has_some() {return this.Len() > 0;}
|
||||
public String_bfr Add_fmt(String format, Object... args) {Add(String_.Format(format, args)); return this;}
|
||||
public String_bfr Add_char_pipe() {return Add_char(Char_code_.Pipe);}
|
||||
public String_bfr Add_char_nl() {return Add_char(Char_code_.New_line);}
|
||||
public String_bfr Add_char_space() {return Add_char(Char_code_.Space);}
|
||||
public String_bfr Add_char_colon() {return Add_char(Char_code_.Colon);}
|
||||
public String_bfr Add_char_repeat(char c, int repeat) {
|
||||
this.Ensure_capacity(this.Len() + repeat);
|
||||
for (int i = 0; i < repeat; i++)
|
||||
Add_char(c);
|
||||
return this;
|
||||
}
|
||||
public String_bfr Add_char_by_code(int code) {
|
||||
if (code >= Ustring_.Surrogate_cp_bgn && code <= Ustring_.Surrogate_cp_end) {
|
||||
sb.append((char)((code - 0x10000) / 0x400 + 0xD800));
|
||||
sb.append((char)((code - 0x10000) % 0x400 + 0xDC00));
|
||||
}
|
||||
else {
|
||||
sb.append((char)code);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public String_bfr Add_int_pad_bgn(char pad_char, int str_len, int val) {
|
||||
int digit_len = Int_.Count_digits(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_char_repeat(pad_char, pad_len);
|
||||
Add_int(val);
|
||||
return this;
|
||||
}
|
||||
public String_bfr Add_bool(boolean val) {
|
||||
this.Add(val ? Bool_.True_str : Bool_.False_str);
|
||||
return this;
|
||||
}
|
||||
public String_bfr Add_bool_as_yn(boolean val) {
|
||||
this.Add(val ? "y" : "n");
|
||||
return this;
|
||||
}
|
||||
public String_bfr Clear() {Del(0, this.Len()); return this;}
|
||||
public String To_str_and_clear() {
|
||||
String rv = To_str();
|
||||
Clear();
|
||||
return rv;
|
||||
}
|
||||
@Override public String toString() {return To_str();}
|
||||
public String To_str() {return sb.toString();}
|
||||
public int Len() {return sb.length();}
|
||||
public String_bfr Add_at(int idx, String s) {sb.insert(idx, s); return this;}
|
||||
public String_bfr Add(String s) {sb.append(s); return this;}
|
||||
public String_bfr Add_char(char c) {sb.append(c); return this;}
|
||||
public String_bfr Add_byte(byte i) {sb.append(i); return this;}
|
||||
public String_bfr Add_int(int i) {sb.append(i); return this;}
|
||||
public String_bfr Add_long(long i) {sb.append(i); return this;}
|
||||
public String_bfr Add_double(double i) {sb.append(i); return this;}
|
||||
public String_bfr Add_mid(char[] ary, int bgn, int count) {sb.append(ary, bgn, count); return this;}
|
||||
public String_bfr Add_obj(Object o) {sb.append(o); return this;}
|
||||
public String_bfr Add_bry(byte[] v) {
|
||||
if (v != null)
|
||||
sb.append(String_.New_bry_utf8(v));
|
||||
return this;
|
||||
}
|
||||
private void Ensure_capacity(int capacity) {sb.ensureCapacity(capacity);}
|
||||
public String_bfr Del(int bgn, int len) {sb.delete(bgn, len); return this;}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,15 +13,14 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.char_sources;
|
||||
|
||||
public interface Char_source {
|
||||
package gplx.objects.strings.charSources;
|
||||
public interface CharSource {
|
||||
String Src();
|
||||
int Get_data(int pos);
|
||||
int Len_in_data();
|
||||
int GetData(int pos);
|
||||
int LenInData();
|
||||
|
||||
String Substring(int bgn, int end);
|
||||
byte[] SubstringAsBry(int bgn, int end);
|
||||
int Index_of(Char_source find, int bgn);
|
||||
boolean Eq(int lhs_bgn, Char_source rhs, int rhs_bgn, int rhs_end);
|
||||
int IndexOf(CharSource find, int bgn);
|
||||
boolean Eq(int lhsBgn, CharSource rhs, int rhsBgn, int rhsEnd);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,18 +13,19 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.char_sources; import gplx.*; import gplx.objects.*; import gplx.objects.strings.*;
|
||||
public class Char_source_ {
|
||||
public static int Index_of_any(String src, char[] ary) {
|
||||
int src_len = String_.Len(src);
|
||||
int ary_len = ary.length;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
for (int j = 0; j < ary_len; j++) {
|
||||
if (String_.Char_at(src, i) == ary[j] ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
package gplx.objects.strings.charSources;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
public class CharSourceUtl {
|
||||
public static int IndexOfAny(String src, char[] ary) {
|
||||
int srcLen = StringUtl.Len(src);
|
||||
int aryLen = ary.length;
|
||||
for (int i = 0; i < srcLen; i++) {
|
||||
for (int j = 0; j < aryLen; j++) {
|
||||
if (StringUtl.CharAt(src, i) == ary[j] ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,168 +1,166 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes;
|
||||
|
||||
import gplx.objects.errs.Err_;
|
||||
import gplx.objects.strings.String_;
|
||||
import gplx.objects.strings.char_sources.Char_source;
|
||||
|
||||
public interface Ustring extends Char_source {
|
||||
int Len_in_chars();
|
||||
int Map_data_to_char(int pos);
|
||||
int Map_char_to_data(int pos);
|
||||
}
|
||||
class Ustring_single implements Ustring { // 1 char == 1 codepoint
|
||||
public Ustring_single(String src, int src_len) {
|
||||
this.src = src;
|
||||
this.src_len = src_len;
|
||||
}
|
||||
public String Src() {return src;} private final String src;
|
||||
public int Len_in_chars() {return src_len;} private final int src_len;
|
||||
public int Len_in_data() {return src_len;}
|
||||
public String Substring(int bgn, int end) {return src.substring(bgn, end);}
|
||||
public byte[] SubstringAsBry(int bgn, int end) {
|
||||
String rv = src.substring(bgn, end);
|
||||
try {
|
||||
return rv.getBytes("UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("failed to get bytes; src=" + src);
|
||||
}
|
||||
}
|
||||
public int Index_of(Char_source find, int bgn) {return src.indexOf(find.Src(), bgn);}
|
||||
public boolean Eq(int lhs_bgn, Char_source rhs, int rhs_bgn, int rhs_end) {
|
||||
if (src_len < lhs_bgn + rhs_end || rhs.Len_in_data() < rhs_bgn + rhs_end)
|
||||
return false;
|
||||
while ( --rhs_end>=0 )
|
||||
if (this.Get_data(lhs_bgn++) != rhs.Get_data(rhs_bgn++))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public int Get_data(int i) {return String_.Char_at(src, i);}
|
||||
public int Map_data_to_char(int i) {if (i < 0 || i > src_len) throw Err_.New_fmt("invalid idx; idx={0} src={1}", i, src); return i;}
|
||||
public int Map_char_to_data(int i) {if (i < 0 || i > src_len) throw Err_.New_fmt("invalid idx; idx={0} src={1}", i, src); return i;}
|
||||
}
|
||||
class Ustring_codepoints implements Ustring {
|
||||
private final int[] codes;
|
||||
public Ustring_codepoints(String src, int chars_len, int codes_len) {
|
||||
// set members
|
||||
this.src = src;
|
||||
this.chars_len = chars_len;
|
||||
this.codes_len = codes_len;
|
||||
|
||||
// make codes[]
|
||||
this.codes = new int[codes_len];
|
||||
int code_idx = 0;
|
||||
for (int i = 0; i < chars_len; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= Ustring_.Surrogate_hi_bgn && c <= Ustring_.Surrogate_hi_end) { // character is 1st part of surrogate-pair
|
||||
i++;
|
||||
if (i == chars_len) throw Err_.New_fmt("invalid surrogate pair found; src={0}", src);
|
||||
int c2 = src.charAt(i);
|
||||
codes[code_idx++] = Ustring_.Surrogate_cp_bgn + (c - Ustring_.Surrogate_hi_bgn) * Ustring_.Surrogate_range + (c2 - Ustring_.Surrogate_lo_bgn);
|
||||
}
|
||||
else {
|
||||
codes[code_idx++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Src() {return src;} private final String src;
|
||||
public String Substring(int bgn, int end) {
|
||||
int len = 0;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
int code = codes[i];
|
||||
len += code >= Ustring_.Surrogate_cp_bgn && code <= Ustring_.Surrogate_cp_end ? 2 : 1;
|
||||
}
|
||||
char[] rv = new char[len];
|
||||
int rv_idx = 0;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
int code = codes[i];
|
||||
if (code >= Ustring_.Surrogate_cp_bgn && code <= Ustring_.Surrogate_cp_end) {
|
||||
rv[rv_idx++] = (char)((code - 0x10000) / 0x400 + 0xD800);
|
||||
rv[rv_idx++] = (char)((code - 0x10000) % 0x400 + 0xDC00);
|
||||
}
|
||||
else {
|
||||
rv[rv_idx++] = (char)code;
|
||||
}
|
||||
}
|
||||
return new String(rv);
|
||||
}
|
||||
public byte[] SubstringAsBry(int bgn, int end) {
|
||||
String rv = src.substring(bgn, end);
|
||||
try {
|
||||
return rv.getBytes("UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("failed to get bytes; src=" + src);
|
||||
}
|
||||
}
|
||||
public int Index_of(Char_source find, int bgn) {
|
||||
int find_len = find.Len_in_data();
|
||||
int codes_len = codes.length;
|
||||
for (int i = bgn; i < codes.length; i++) {
|
||||
boolean found = true;
|
||||
for (int j = 0; j < find_len; j++) {
|
||||
int codes_idx = i + j;
|
||||
if (codes_idx >= codes_len) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (codes[codes_idx] != find.Get_data(j)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == true)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public boolean Eq(int lhs_bgn, Char_source rhs, int rhs_bgn, int rhs_end) {
|
||||
if (this.Len_in_data() < lhs_bgn + rhs_end || rhs.Len_in_data() < rhs_bgn + rhs_end)
|
||||
return false;
|
||||
while ( --rhs_end>=0 )
|
||||
if ((this.Get_data(lhs_bgn++) != rhs.Get_data(rhs_bgn++)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public int Len_in_chars() {return chars_len;} private final int chars_len;
|
||||
public int Len_in_data() {return codes_len;} private final int codes_len;
|
||||
public int Get_data(int i) {return codes[i];}
|
||||
public int Map_data_to_char(int code_pos) {
|
||||
if (code_pos == codes_len) return chars_len; // if char_pos is chars_len, return codes_len; allows "int end = u.Map_char_to_data(str_len)"
|
||||
|
||||
// sum all items before requested pos
|
||||
int rv = 0;
|
||||
for (int i = 0; i < code_pos; i++) {
|
||||
rv += codes[i] < Ustring_.Surrogate_cp_bgn ? 1 : 2;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public int Map_char_to_data(int char_pos) {
|
||||
if (char_pos == chars_len) return codes_len; // if char_pos is chars_len, return codes_len; allows "int end = u.Map_char_to_data(str_len)"
|
||||
|
||||
// sum all items before requested pos
|
||||
int rv = 0;
|
||||
for (int i = 0; i < char_pos; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= Ustring_.Surrogate_hi_bgn && c <= Ustring_.Surrogate_hi_end){ // Surrogate_hi
|
||||
if (i == char_pos - 1) // char_pos is Surrogate_lo; return -1 since Surrogate_lo doesn't map to a code_pos
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
rv++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
import gplx.objects.strings.charSources.CharSource;
|
||||
public interface Ustring extends CharSource {
|
||||
int LenInChars();
|
||||
int MapDataToChar(int pos);
|
||||
int MapCharToData(int pos);
|
||||
}
|
||||
class UstringSingle implements Ustring { // 1 char == 1 codepoint
|
||||
public UstringSingle(String src, int srcLen) {
|
||||
this.src = src;
|
||||
this.srcLen = srcLen;
|
||||
}
|
||||
public String Src() {return src;} private final String src;
|
||||
public int LenInChars() {return srcLen;} private final int srcLen;
|
||||
public int LenInData() {return srcLen;}
|
||||
public String Substring(int bgn, int end) {return src.substring(bgn, end);}
|
||||
public byte[] SubstringAsBry(int bgn, int end) {
|
||||
String rv = src.substring(bgn, end);
|
||||
try {
|
||||
return rv.getBytes("UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("failed to get bytes; src=" + src);
|
||||
}
|
||||
}
|
||||
public int IndexOf(CharSource find, int bgn) {return src.indexOf(find.Src(), bgn);}
|
||||
public boolean Eq(int lhsBgn, CharSource rhs, int rhsBgn, int rhsEnd) {
|
||||
if (srcLen < lhsBgn + rhsEnd || rhs.LenInData() < rhsBgn + rhsEnd)
|
||||
return false;
|
||||
while ( --rhsEnd>=0 )
|
||||
if (this.GetData(lhsBgn++) != rhs.GetData(rhsBgn++))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public int GetData(int i) {return StringUtl.CharAt(src, i);}
|
||||
public int MapDataToChar(int i) {if (i < 0 || i > srcLen) throw ErrUtl.NewFmt("invalid idx; idx={0} src={1}", i, src); return i;}
|
||||
public int MapCharToData(int i) {if (i < 0 || i > srcLen) throw ErrUtl.NewFmt("invalid idx; idx={0} src={1}", i, src); return i;}
|
||||
}
|
||||
class UstringCodepoints implements Ustring {
|
||||
private final int[] codes;
|
||||
public UstringCodepoints(String src, int charsLen, int codesLen) {
|
||||
// set members
|
||||
this.src = src;
|
||||
this.charsLen = charsLen;
|
||||
this.codesLen = codesLen;
|
||||
|
||||
// make codes[]
|
||||
this.codes = new int[codesLen];
|
||||
int codeIdx = 0;
|
||||
for (int i = 0; i < charsLen; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= UstringUtl.SurrogateHiBgn && c <= UstringUtl.SurrogateHiEnd) { // character is 1st part of surrogate-pair
|
||||
i++;
|
||||
if (i == charsLen) throw ErrUtl.NewFmt("invalid surrogate pair found; src={0}", src);
|
||||
int c2 = src.charAt(i);
|
||||
codes[codeIdx++] = UstringUtl.SurrogateCpBgn + (c - UstringUtl.SurrogateHiBgn) * UstringUtl.SurrogateRange + (c2 - UstringUtl.SurrogateLoBgn);
|
||||
}
|
||||
else {
|
||||
codes[codeIdx++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Src() {return src;} private final String src;
|
||||
public String Substring(int bgn, int end) {
|
||||
int len = 0;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
int code = codes[i];
|
||||
len += code >= UstringUtl.SurrogateCpBgn && code <= UstringUtl.SurrogateCpEnd ? 2 : 1;
|
||||
}
|
||||
char[] rv = new char[len];
|
||||
int rvIdx = 0;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
int code = codes[i];
|
||||
if (code >= UstringUtl.SurrogateCpBgn && code <= UstringUtl.SurrogateCpEnd) {
|
||||
rv[rvIdx++] = (char)((code - 0x10000) / 0x400 + 0xD800);
|
||||
rv[rvIdx++] = (char)((code - 0x10000) % 0x400 + 0xDC00);
|
||||
}
|
||||
else {
|
||||
rv[rvIdx++] = (char)code;
|
||||
}
|
||||
}
|
||||
return new String(rv);
|
||||
}
|
||||
public byte[] SubstringAsBry(int bgn, int end) {
|
||||
String rv = src.substring(bgn, end);
|
||||
try {
|
||||
return rv.getBytes("UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("failed to get bytes; src=" + src);
|
||||
}
|
||||
}
|
||||
public int IndexOf(CharSource find, int bgn) {
|
||||
int findLen = find.LenInData();
|
||||
int codesLen = codes.length;
|
||||
for (int i = bgn; i < codes.length; i++) {
|
||||
boolean found = true;
|
||||
for (int j = 0; j < findLen; j++) {
|
||||
int codesIdx = i + j;
|
||||
if (codesIdx >= codesLen) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (codes[codesIdx] != find.GetData(j)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == true)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public boolean Eq(int lhsBgn, CharSource rhs, int rhsBgn, int rhsEnd) {
|
||||
if (this.LenInData() < lhsBgn + rhsEnd || rhs.LenInData() < rhsBgn + rhsEnd)
|
||||
return false;
|
||||
while ( --rhsEnd>=0 )
|
||||
if ((this.GetData(lhsBgn++) != rhs.GetData(rhsBgn++)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public int LenInChars() {return charsLen;} private final int charsLen;
|
||||
public int LenInData() {return codesLen;} private final int codesLen;
|
||||
public int GetData(int i) {return codes[i];}
|
||||
public int MapDataToChar(int codePos) {
|
||||
if (codePos == codesLen) return charsLen; // if charPos is charsLen, return codesLen; allows "int end = u.MapCharToData(strLen)"
|
||||
|
||||
// sum all items before requested pos
|
||||
int rv = 0;
|
||||
for (int i = 0; i < codePos; i++) {
|
||||
rv += codes[i] < UstringUtl.SurrogateCpBgn ? 1 : 2;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public int MapCharToData(int charPos) {
|
||||
if (charPos == charsLen) return codesLen; // if charPos is charsLen, return codesLen; allows "int end = u.MapCharToData(strLen)"
|
||||
|
||||
// sum all items before requested pos
|
||||
int rv = 0;
|
||||
for (int i = 0; i < charPos; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= UstringUtl.SurrogateHiBgn && c <= UstringUtl.SurrogateHiEnd){ // SurrogateHi
|
||||
if (i == charPos - 1) // charPos is SurrogateLo; return -1 since SurrogateLo doesn't map to a codePos
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
rv++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
50
baselib/src/gplx/objects/strings/unicodes/UstringUtl.java
Normal file
50
baselib/src/gplx/objects/strings/unicodes/UstringUtl.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
public class UstringUtl {
|
||||
public static Ustring NewCodepoints(String src) {
|
||||
if (src == null) throw ErrUtl.NewNull("src");
|
||||
|
||||
// calc lens
|
||||
int charsLen = src.length();
|
||||
int codesLen = UstringUtl.Len(src, charsLen);
|
||||
|
||||
return charsLen == codesLen
|
||||
? new UstringSingle(src, charsLen)
|
||||
: new UstringCodepoints(src, charsLen, codesLen);
|
||||
}
|
||||
public static int Len(String src, int srcLen) {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < srcLen; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= SurrogateHiBgn && c <= SurrogateHiEnd) {
|
||||
i++;
|
||||
}
|
||||
rv++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final int // REF: https://en.wikipedia.org/wiki/Universal_Character_Set_characters
|
||||
SurrogateHiBgn = 0xD800, // 55,296: Surrogate high start
|
||||
SurrogateHiEnd = 0xDBFF, // 56,319: Surrogate high end
|
||||
SurrogateLoBgn = 0xDC00, // 56,320: Surrogate low start
|
||||
SurrogateLoEnd = 0xDFFF, // 57,343: Surrogate low end
|
||||
SurrogateCpBgn = 0x010000, // 65,536: Surrogate codepoint start
|
||||
SurrogateCpEnd = 0x10FFFF, // 1,114,111: Surrogate codepoint end
|
||||
SurrogateRange = 0x400; // 1,024: Surrogate range (end - start) for high / low
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes; import gplx.*; import gplx.objects.*; import gplx.objects.strings.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Ustring_ {
|
||||
public static Ustring New_codepoints(String src) {
|
||||
if (src == null) throw Err_.New_null("src");
|
||||
|
||||
// calc lens
|
||||
int chars_len = src.length();
|
||||
int codes_len = Ustring_.Len(src, chars_len);
|
||||
|
||||
return chars_len == codes_len
|
||||
? (Ustring)new Ustring_single(src, chars_len)
|
||||
: (Ustring)new Ustring_codepoints(src, chars_len, codes_len);
|
||||
}
|
||||
public static int Len(String src, int src_len) {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= Surrogate_hi_bgn && c <= Surrogate_hi_end) {
|
||||
i++;
|
||||
}
|
||||
rv++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final int // REF: https://en.wikipedia.org/wiki/Universal_Character_Set_characters
|
||||
Surrogate_hi_bgn = 0xD800 // 55,296: Surrogate high start
|
||||
, Surrogate_hi_end = 0xDBFF // 56,319: Surrogate high end
|
||||
, Surrogate_lo_bgn = 0xDC00 // 56,320: Surrogate low start
|
||||
, Surrogate_lo_end = 0xDFFF // 57,343: Surrogate low end
|
||||
, Surrogate_cp_bgn = 0x010000 // 65,536: Surrogate codepoint start
|
||||
, Surrogate_cp_end = 0x10FFFF // 1,114,111: Surrogate codepoint end
|
||||
, Surrogate_range = 0x400 // 1,024: Surrogate range (end - start) for high / low
|
||||
;
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes; import gplx.*; import gplx.objects.*; import gplx.objects.strings.*;
|
||||
import org.junit.*; import gplx.tests.*;
|
||||
import gplx.objects.errs.*;
|
||||
public class Ustring_tst {
|
||||
private final Ustring_fxt fxt = new Ustring_fxt();
|
||||
@Test public void Empty() {
|
||||
fxt.Init("");
|
||||
fxt.Test__Len(0, 0);
|
||||
}
|
||||
@Test public void Blank() {
|
||||
fxt.Init("");
|
||||
fxt.Test__Len(0, 0);
|
||||
}
|
||||
@Test public void Single() {
|
||||
fxt.Init("Abc");
|
||||
fxt.Test__Len(3, 3);
|
||||
fxt.Test__Get_code(65, 98, 99);
|
||||
fxt.Test__Map_code_to_char(0, 1, 2, 3);
|
||||
fxt.Test__Map_char_to_code(0, 1, 2, 3);
|
||||
}
|
||||
@Test public void Multi() {
|
||||
fxt.Init("a¢€𤭢b");
|
||||
fxt.Test__Len(5, 6);
|
||||
fxt.Test__Get_code(97, 162, 8364, 150370, 98);
|
||||
fxt.Test__Map_code_to_char(0, 1, 2, 3, 5, 6);
|
||||
fxt.Test__Map_char_to_code(0, 1, 2, 3, -1, 4, 5);
|
||||
}
|
||||
@Test public void Index_of() {
|
||||
fxt.Test__Index_of("abc", "b", 0, 1); // basic
|
||||
fxt.Test__Index_of("ab", "bc", 0, -1); // out-of-bounds
|
||||
fxt.Test__Index_of("a¢e", "¢", 0, 1); // check UTF-8 strings still match at byte-level
|
||||
}
|
||||
|
||||
@Test public void Substring() {
|
||||
fxt.Test__Substring("abc", 1, 2, "b"); // basic
|
||||
fxt.Test__Substring("¢bc", 1, 2, "b"); // check UTF-8 strings don't get lopped off
|
||||
}
|
||||
}
|
||||
class Ustring_fxt {
|
||||
private Ustring under;
|
||||
public void Init(String src) {
|
||||
this.under = Ustring_.New_codepoints(src);
|
||||
}
|
||||
public void Test__Len(int expd_codes, int expd_chars) {
|
||||
Gftest_fxt.Eq__int(expd_codes, under.Len_in_data(), "codes");
|
||||
Gftest_fxt.Eq__int(expd_chars, under.Len_in_chars(), "chars");
|
||||
}
|
||||
public void Test__Get_code(int... expd) {
|
||||
int actl_len = under.Len_in_data();
|
||||
int[] actl = new int[actl_len];
|
||||
for (int i = 0; i < actl_len; i++)
|
||||
actl[i] = under.Get_data(i);
|
||||
Gftest_fxt.Eq__ary(expd, actl);
|
||||
}
|
||||
public void Test__Map_code_to_char(int... expd) {
|
||||
int actl_len = under.Len_in_data() + 1;
|
||||
int[] actl = new int[actl_len];
|
||||
for (int i = 0; i < actl_len; i++)
|
||||
actl[i] = under.Map_data_to_char(i);
|
||||
Gftest_fxt.Eq__ary(expd, actl);
|
||||
}
|
||||
public void Test__Map_char_to_code(int... expd) {
|
||||
int actl_len = under.Len_in_chars() + 1;
|
||||
int[] actl = new int[actl_len];
|
||||
for (int i = 0; i < actl_len; i++) {
|
||||
int val = 0;
|
||||
try {
|
||||
val = under.Map_char_to_data(i);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
val = -1;
|
||||
Err_.Noop(exc);
|
||||
}
|
||||
actl[i] = val;
|
||||
}
|
||||
Gftest_fxt.Eq__ary(expd, actl);
|
||||
}
|
||||
public void Test__Index_of(String src_str, String find_str, int bgn, int expd) {
|
||||
Ustring src = Ustring_.New_codepoints(src_str);
|
||||
Ustring find = Ustring_.New_codepoints(find_str);
|
||||
int actl = src.Index_of(find, bgn);
|
||||
Gftest_fxt.Eq__int(expd, actl);
|
||||
}
|
||||
public void Test__Substring(String src_str, int bgn, int end, String expd) {
|
||||
Ustring src = Ustring_.New_codepoints(src_str);
|
||||
String actl = src.Substring(bgn, end);
|
||||
Gftest_fxt.Eq__str(expd, actl);
|
||||
}
|
||||
}
|
||||
65
baselib/src/gplx/objects/types/TypeIds.java
Normal file
65
baselib/src/gplx/objects/types/TypeIds.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.types;
|
||||
import gplx.objects.arrays.BryUtl;
|
||||
import gplx.objects.primitives.BoolUtl;
|
||||
import gplx.objects.primitives.ByteUtl;
|
||||
import gplx.objects.primitives.CharUtl;
|
||||
import gplx.objects.primitives.DoubleUtl;
|
||||
import gplx.objects.primitives.FloatUtl;
|
||||
import gplx.objects.primitives.IntUtl;
|
||||
import gplx.objects.primitives.LongUtl;
|
||||
import gplx.objects.primitives.ShortUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
public class TypeIds {
|
||||
public static final int // SERIALIZABLE.N
|
||||
IdObj = 0,
|
||||
IdNull = 1,
|
||||
IdBool = 2,
|
||||
IdByte = 3,
|
||||
IdShort = 4,
|
||||
IdInt = 5,
|
||||
IdLong = 6,
|
||||
IdFloat = 7,
|
||||
IdDouble = 8,
|
||||
IdChar = 9,
|
||||
IdStr = 10,
|
||||
IdBry = 11,
|
||||
IdDate = 12,
|
||||
IdDecimal = 13,
|
||||
IdArray = 14;
|
||||
|
||||
public static int ToIdByObj(Object o) {
|
||||
if (o == null) return TypeIds.IdNull;
|
||||
Class<?> type = o.getClass();
|
||||
return TypeIds.ToIdByCls(type);
|
||||
}
|
||||
public static int ToIdByCls(Class<?> type) {
|
||||
if (TypeUtl.Eq(type, IntUtl.ClsRefType)) return IdInt;
|
||||
else if (TypeUtl.Eq(type, StringUtl.ClsRefType)) return IdStr;
|
||||
else if (TypeUtl.Eq(type, BryUtl.ClsRefType)) return IdBry;
|
||||
else if (TypeUtl.Eq(type, BoolUtl.ClsRefType)) return IdBool;
|
||||
else if (TypeUtl.Eq(type, ByteUtl.ClsRefType)) return IdByte;
|
||||
else if (TypeUtl.Eq(type, LongUtl.ClsRefType)) return IdLong;
|
||||
else if (TypeUtl.Eq(type, DoubleUtl.ClsRefType)) return IdDouble;
|
||||
else if (TypeUtl.Eq(type, FloatUtl.ClsRefType)) return IdFloat;
|
||||
else if (TypeUtl.Eq(type, ShortUtl.ClsRefType)) return IdShort;
|
||||
else if (TypeUtl.Eq(type, CharUtl.ClsRefType)) return IdChar;
|
||||
// else if (TypeUtl.Eq(type, DecimalUtl.ClsRefType)) return IdDecimal;
|
||||
// else if (TypeUtl.Eq(type, DateUtl.ClsRefType)) return IdDate;
|
||||
else return IdObj;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@@ -13,11 +13,11 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.types; import gplx.*; import gplx.objects.*;
|
||||
public class Type_ {
|
||||
public static boolean Eq(Class<?> lhs, Class<?> rhs) {// DUPE_FOR_TRACKING: same as Object_.Eq
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
else return lhs.equals(rhs);
|
||||
}
|
||||
}
|
||||
package gplx.objects.types;
|
||||
public class TypeUtl {
|
||||
public static boolean Eq(Class<?> lhs, Class<?> rhs) {// NOTE: same as ObjectUtl.Eq
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
else return lhs.equals(rhs);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.types; import gplx.*; import gplx.objects.*;
|
||||
import gplx.objects.primitives.*;
|
||||
import gplx.objects.strings.*;
|
||||
public class Type_ids_ {
|
||||
public static final int // SERIALIZABLE.N
|
||||
Id__obj = 0
|
||||
, Id__null = 1
|
||||
, Id__bool = 2
|
||||
, Id__byte = 3
|
||||
, Id__short = 4
|
||||
, Id__int = 5
|
||||
, Id__long = 6
|
||||
, Id__float = 7
|
||||
, Id__double = 8
|
||||
, Id__char = 9
|
||||
, Id__str = 10
|
||||
, Id__bry = 11
|
||||
, Id__date = 12
|
||||
, Id__decimal = 13
|
||||
, Id__array = 14
|
||||
;
|
||||
|
||||
public static int To_id_by_obj(Object o) {
|
||||
if (o == null) return Type_ids_.Id__null;
|
||||
Class<?> type = o.getClass();
|
||||
return Type_ids_.To_id_by_type(type);
|
||||
}
|
||||
|
||||
public static int To_id_by_type(Class<?> type) {
|
||||
if (Type_.Eq(type, Int_.Cls_ref_type)) return Id__int;
|
||||
else if (Type_.Eq(type, String_.Cls_ref_type)) return Id__str;
|
||||
else if (Type_.Eq(type, byte[].class)) return Id__bry;
|
||||
else if (Type_.Eq(type, Bool_.Cls_ref_type)) return Id__bool;
|
||||
else if (Type_.Eq(type, Byte_.Cls_ref_type)) return Id__byte;
|
||||
else if (Type_.Eq(type, Long_.Cls_ref_type)) return Id__long;
|
||||
else if (Type_.Eq(type, Double_.Cls_ref_type)) return Id__double;
|
||||
// else if (Type_.Eq(type, Decimal_.Cls_ref_type)) return Id__decimal;
|
||||
// else if (Type_.Eq(type, Date_.Cls_ref_type)) return Id__date;
|
||||
else if (Type_.Eq(type, Float_.Cls_ref_type)) return Id__float;
|
||||
else if (Type_.Eq(type, Short_.Cls_ref_type)) return Id__short;
|
||||
else if (Type_.Eq(type, Char_.Cls_ref_type)) return Id__char;
|
||||
else return Id__obj;
|
||||
}
|
||||
}
|
||||
171
baselib/src/gplx/tests/GfoTstr.java
Normal file
171
baselib/src/gplx/tests/GfoTstr.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.tests;
|
||||
import gplx.objects.ObjectUtl;
|
||||
import gplx.objects.arrays.ArrayUtl;
|
||||
import gplx.objects.arrays.BryUtl;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.primitives.BoolUtl;
|
||||
import gplx.objects.primitives.ByteUtl;
|
||||
import gplx.objects.primitives.CharCode;
|
||||
import gplx.objects.primitives.IntUtl;
|
||||
import gplx.objects.primitives.LongUtl;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
import gplx.objects.strings.bfrs.GfoStrBldr;
|
||||
import gplx.objects.types.TypeIds;
|
||||
public class GfoTstr {
|
||||
private static final GfoStrBldr bfr = new GfoStrBldr();
|
||||
private static final String
|
||||
EqN = "!= ",
|
||||
Null = "<<NULL>>",
|
||||
SectionBgn = "\n************************************************************************************************\n",
|
||||
SectionMid = "\n------------------------------------------------------------------------------------------------\n",
|
||||
SectionEnd = "________________________________________________________________________________________________";
|
||||
|
||||
public static void Write(Object... ary) {
|
||||
GfoStrBldr bfr = new GfoStrBldr();
|
||||
int aryLen = ArrayUtl.Len(ary);
|
||||
for (int i = 0; i < aryLen; i++) {
|
||||
bfr.Add("'");
|
||||
bfr.Add(ObjectUtl.ToStrOrNullMark(ary[i]));
|
||||
bfr.Add("' ");
|
||||
}
|
||||
System.out.println(bfr.ToStr() + StringUtl.Lf);
|
||||
}
|
||||
public static void EqNull(boolean expd, Object val) {EqNull(expd, val, null);}
|
||||
public static void EqNull(boolean expd, Object val, String msgFmt, Object... msgArgs) {
|
||||
if ( expd && val != null
|
||||
|| !expd && val == null
|
||||
) {
|
||||
String expdStr = expd ? "null" : "not null";
|
||||
String actlStr = val == null ? "null" : "not null";
|
||||
WriteAndThrow(expdStr, actlStr, msgFmt, msgArgs);
|
||||
}
|
||||
}
|
||||
public static void EqBoolY(boolean actl) {EqBool(BoolUtl.Y, actl, null);}
|
||||
public static void EqBool(boolean expd, boolean actl) {EqBool(expd, actl, null);}
|
||||
public static void EqBool(boolean expd, boolean actl, String msgFmt, Object... msgArgs) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(BoolUtl.ToStrLower(expd), BoolUtl.ToStrLower(actl), msgFmt, msgArgs);
|
||||
}
|
||||
public static void EqInt(int expd, int actl) {EqInt(expd, actl, null);}
|
||||
public static void EqInt(int expd, int actl, String msgFmt, Object... msgArgs) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(IntUtl.ToStr(expd), IntUtl.ToStr(actl), msgFmt, msgArgs);
|
||||
}
|
||||
public static void EqLong(long expd, long actl) {EqLong(expd, actl, null);}
|
||||
public static void EqLong(long expd, long actl, String msgFmt, Object... msgArgs) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(LongUtl.ToStr(expd), LongUtl.ToStr(actl), msgFmt, msgArgs);
|
||||
}
|
||||
public static void EqStr(String expd, byte[] actl, String msgFmt, Object... msgArgs) {EqStr(expd, StringUtl.NewByBryUtf8(actl), msgFmt, msgArgs);}
|
||||
public static void EqStr(String expd, byte[] actl) {EqStr(expd, StringUtl.NewByBryUtf8(actl), null);}
|
||||
public static void EqStr(String expd, String actl) {EqStr(expd, actl, null);}
|
||||
public static void EqStr(String expd, String actl, String msgFmt, Object... msgArgs) {
|
||||
if (!StringUtl.Eq(expd, actl))
|
||||
WriteAndThrow(expd, actl, msgFmt, msgArgs);
|
||||
}
|
||||
public static void EqAry(Object[] expd, Object[] actl) {EqAry(TypeIds.IdObj, expd, actl, "");}
|
||||
public static void EqAry(int[] expd, int[] actl) {EqAry(TypeIds.IdInt, expd, actl, "");}
|
||||
public static void EqAry(String[] expd, String[] actl) {EqAry(TypeIds.IdBry, BryUtl.Ary(expd), BryUtl.Ary(actl), "noMsg");}
|
||||
private static void EqAry(int typeTid, Object expdAry, Object actlAry, String msgFmt, Object... msgArgs) {
|
||||
boolean[] failures = CalcFailures(typeTid, expdAry, actlAry);
|
||||
if (failures != null) {
|
||||
WriteFailHead(bfr, msgFmt, msgArgs);
|
||||
WriteFailBody(bfr, failures, typeTid, expdAry, actlAry);
|
||||
throw ErrUtl.NewMsg(bfr.ToStrAndClear());
|
||||
}
|
||||
}
|
||||
private static boolean[] CalcFailures(int tid, Object expdAry, Object actlAry) {
|
||||
int expdLen = ArrayUtl.Len(expdAry);
|
||||
int actlLen = ArrayUtl.Len(actlAry);
|
||||
int maxLen = expdLen > actlLen ? expdLen : actlLen;
|
||||
if (maxLen == 0) return null; // exit early if both arys are empty
|
||||
|
||||
boolean[] rv = null;
|
||||
for (int i = 0; i < maxLen; i++) {
|
||||
Object expdObj = i < expdLen ? ArrayUtl.GetAt(expdAry, i) : null;
|
||||
Object actlObj = i < actlLen ? ArrayUtl.GetAt(actlAry, i) : null;
|
||||
boolean eq = false;
|
||||
if (expdObj == null && actlObj == null) eq = true;
|
||||
else if (expdObj == null || actlObj == null) eq = false;
|
||||
else {
|
||||
switch (tid) {
|
||||
case TypeIds.IdBool: eq = BoolUtl.Cast(expdObj) == BoolUtl.Cast(actlObj); break;
|
||||
case TypeIds.IdLong: eq = LongUtl.Cast(expdObj) == LongUtl.Cast(actlObj); break;
|
||||
case TypeIds.IdInt: eq = IntUtl.Cast(expdObj) == IntUtl.Cast(actlObj); break;
|
||||
case TypeIds.IdByte: eq = ByteUtl.Cast(expdObj) == ByteUtl.Cast(actlObj); break;
|
||||
case TypeIds.IdBry: eq = BryUtl.Eq((byte[])expdObj, (byte[])actlObj); break;
|
||||
case TypeIds.IdObj: eq = ObjectUtl.Eq(expdObj, actlObj); break;
|
||||
}
|
||||
}
|
||||
if (!eq) {
|
||||
if (rv == null) {
|
||||
rv = new boolean[maxLen];
|
||||
}
|
||||
rv[i] = true;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void WriteFailHead(GfoStrBldr bfr, String msgFmt, Object[] msgArgs) {
|
||||
bfr.Add(SectionBgn);
|
||||
if (msgFmt != null) {
|
||||
bfr.Add(StringUtl.Format(msgFmt, msgArgs));
|
||||
bfr.Add(SectionMid);
|
||||
}
|
||||
}
|
||||
private static void WriteFailBody(GfoStrBldr bfr, boolean[] failures, int typeId, Object expdAry, Object actlAry) {
|
||||
int len = failures.length;
|
||||
int expdLen = ArrayUtl.Len(expdAry);
|
||||
int actlLen = ArrayUtl.Len(actlAry);
|
||||
for (int i = 0; i < len; i++) {
|
||||
boolean failure = failures[i];
|
||||
int padLen = 5 - IntUtl.CountDigits(i); // 5=assuming no more than 9999 failures in one test
|
||||
bfr.AddIntPadBgn(CharCode.Num0, padLen, i).AddCharColon().AddCharSpace();
|
||||
WriteFailItm(bfr, typeId, expdAry, expdLen, i);
|
||||
if (failure) {
|
||||
bfr.Add(EqN).AddCharRepeat(CharCode.Space, padLen - 1);
|
||||
WriteFailItm(bfr, typeId, actlAry, actlLen, i);
|
||||
}
|
||||
}
|
||||
bfr.Add(SectionEnd);
|
||||
}
|
||||
private static void WriteFailItm(GfoStrBldr bfr, int typeId, Object ary, int len, int idx) {
|
||||
if (idx < len) {
|
||||
Object val = ArrayUtl.GetAt(ary, idx);
|
||||
switch (typeId) {
|
||||
case TypeIds.IdBool: bfr.AddBoolAsYn(BoolUtl.Cast(val)); break;
|
||||
case TypeIds.IdBry: bfr.AddBry((byte[])val); break;
|
||||
case TypeIds.IdLong: bfr.AddLong(LongUtl.Cast(val)); break;
|
||||
case TypeIds.IdInt: bfr.AddInt(IntUtl.Cast(val)); break;
|
||||
case TypeIds.IdByte: bfr.AddInt((int)(ByteUtl.Cast(val))); break;
|
||||
case TypeIds.IdObj: bfr.Add(ObjectUtl.ToStr(val)); break;
|
||||
default: throw ErrUtl.NewUnhandledDefault(typeId);
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.Add(Null);
|
||||
bfr.AddCharNl();
|
||||
}
|
||||
private static void WriteAndThrow(String expd, String actl, String msgFmt, Object... msgArgs) {
|
||||
WriteFailHead(bfr, msgFmt, msgArgs);
|
||||
bfr.Add("expd: ").Add(expd).AddCharNl();
|
||||
bfr.Add("actl: ").Add(actl).AddCharNl();
|
||||
bfr.Add(SectionEnd);
|
||||
throw ErrUtl.NewMsg(bfr.ToStrAndClear());
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.tests; import gplx.*;
|
||||
import gplx.objects.*;
|
||||
import gplx.objects.errs.*;
|
||||
import gplx.objects.primitives.*; import gplx.objects.brys.*;
|
||||
import gplx.objects.strings.*; import gplx.objects.strings.bfrs.*;
|
||||
import gplx.objects.arrays.*; import gplx.objects.types.*;
|
||||
public class Gftest_fxt {
|
||||
private static final String_bfr bfr = new String_bfr();
|
||||
public static void Eq__ary(Object[] expd, Object[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__obj, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(boolean[] expd, boolean[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bool, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(int[] expd, int[] actl) {Eq__array(Type_ids_.Id__int, expd, actl, "");}
|
||||
public static void Eq__ary(int[] expd, int[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__int, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(long[] expd, long[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__long, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(byte[] expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__byte, expd, actl, msg_fmt, msg_args);}
|
||||
// public static void Eq__ary__lines(String expd, String actl) {Eq__ary__lines(expd, actl, "no_msg");}
|
||||
// public static void Eq__ary__lines(String expd, byte[] actl) {Eq__ary__lines(expd, String_.New_bry_utf8(actl), "no_msg");}
|
||||
// public static void Eq__ary__lines(String expd, byte[] actl, String msg_fmt, params Object[] msg_args) {Eq__ary__lines(expd, String_.New_bry_utf8(actl), msg_fmt, msg_args);}
|
||||
// public static void Eq__ary__lines(String expd, String actl, String msg_fmt, params Object[] msg_args) {Eq__array(Type_ids_.Id__str, Bry_split_.Split_lines(Bry_.New_utf08(expd)), Bry_split_.Split_lines(Bry_.New_utf08(actl)), msg_fmt, msg_args);}
|
||||
public static void Eq__ary(String[] expd, String[] actl) {Eq__array(Type_ids_.Id__bry, Bry_.Ary(expd), Bry_.Ary(actl), "no_msg");}
|
||||
public static void Eq__ary(String[] expd, String[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bry, Bry_.Ary(expd), Bry_.Ary(actl), msg_fmt, msg_args);}
|
||||
public static void Eq__ary(String[] expd, byte[][] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bry, Bry_.Ary(expd), actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(byte[][] expd, byte[][] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bry, expd, actl, msg_fmt, msg_args);}
|
||||
private static void Eq__array(int type_tid, Object expd_ary, Object actl_ary, String msg_fmt, Object... msg_args) {
|
||||
boolean[] failures = Calc__failures(type_tid, expd_ary, actl_ary);
|
||||
if (failures != null) {
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
Write_fail_ary(bfr, failures, type_tid, expd_ary, actl_ary);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
}
|
||||
public static void Eq__null(boolean expd, Object actl) {Eq__null(expd, actl, null);}
|
||||
public static void Eq__null(boolean expd, Object actl, String msg_fmt, Object... msg_args) {
|
||||
if ( expd && actl == null
|
||||
|| !expd && actl != null
|
||||
) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
String expd_str = expd ? "null" : "not null";
|
||||
String actl_str = actl == null ? "null" : "not null";
|
||||
bfr.Add("expd: ").Add(expd_str).Add_char_nl();
|
||||
bfr.Add("actl: ").Add(actl_str).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__obj_or_null(Object expd, Object actl) {
|
||||
if (expd == null) expd = Null;
|
||||
if (actl == null) actl = Null;
|
||||
Eq__str(Object_.To_str_or(expd, Null), Object_.To_str_or(actl, null), Null);
|
||||
}
|
||||
public static void Eq__str(String expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__str(expd, String_.New_bry_utf8(actl), msg_fmt, msg_args);}
|
||||
public static void Eq__str(String expd, byte[] actl) {Eq__str(expd, String_.New_bry_utf8(actl), null);}
|
||||
public static void Eq__str(String expd, String actl) {Eq__str(expd, actl, null);}
|
||||
public static void Eq__str(String expd, String actl, String msg_fmt, Object... msg_args) {
|
||||
if (String_.Eq(expd, actl)) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__bry(byte[] expd, byte[] actl) {Eq__bry(expd, actl, null);}
|
||||
public static void Eq__bry(byte[] expd, byte[] actl, String msg_fmt, Object... msg_args) {
|
||||
if (Bry_.Eq(expd, actl)) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add(String_.New_bry_utf8(expd)).Add_char_nl();
|
||||
bfr.Add("actl: ").Add(String_.New_bry_utf8(actl)).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__long(long expd, long actl) {Eq__long(expd, actl, null);}
|
||||
public static void Eq__long(long expd, long actl, String msg_fmt, Object... msg_args) {
|
||||
if (expd == actl) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add_long(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add_long(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__byte(byte expd, byte actl) {Eq__byte(expd, actl, null);}
|
||||
public static void Eq__byte(byte expd, byte actl, String msg_fmt, Object... msg_args) {
|
||||
if (expd == actl) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add_byte(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add_byte(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__int(int expd, int actl) {Eq__int(expd, actl, null);}
|
||||
public static void Eq__int(int expd, int actl, String msg_fmt, Object... msg_args) {
|
||||
if (expd == actl) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add_int(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add_int(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__bool_y(boolean actl) {Eq__bool(Bool_.Y, actl, null);}
|
||||
public static void Eq__bool_n(boolean actl) {Eq__bool(Bool_.N, actl, null);}
|
||||
public static void Eq__bool_y(boolean actl, String msg_fmt, Object... msg_args) {Eq__bool(Bool_.Y, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__bool(boolean expd, boolean actl) {Eq__bool(expd, actl, null);}
|
||||
public static void Eq__bool(boolean expd, boolean actl, String msg_fmt, Object... msg_args) {
|
||||
if (expd == actl) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add_bool(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add_bool(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__double(double expd, double actl) {Eq__double(expd, actl, null);}
|
||||
public static void Eq__double(double expd, double actl, String msg_fmt, Object... msg_args) {
|
||||
if (expd == actl) return;
|
||||
Write_fail_head(bfr, msg_fmt, msg_args);
|
||||
bfr.Add("expd: ").Add_double(expd).Add_char_nl();
|
||||
bfr.Add("actl: ").Add_double(actl).Add_char_nl();
|
||||
bfr.Add(Section_end);
|
||||
throw Err_.New_msg(bfr.To_str_and_clear());
|
||||
}
|
||||
private static void Write_fail_head(String_bfr bfr, String msg_fmt, Object[] msg_args) {
|
||||
bfr.Add(Section_bgn);
|
||||
if (msg_fmt != null) {
|
||||
bfr.Add(String_.Format(msg_fmt, msg_args));
|
||||
bfr.Add(Section_mid);
|
||||
}
|
||||
}
|
||||
private static void Write_fail_ary(String_bfr bfr, boolean[] failures, int type_id, Object expd_ary, Object actl_ary) {
|
||||
int len = failures.length;
|
||||
int expd_len = Array_.Len(expd_ary);
|
||||
int actl_len = Array_.Len(actl_ary);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
boolean failure = failures[i];
|
||||
int pad_len = 5 - Int_.Count_digits(i);
|
||||
bfr.Add_int_pad_bgn(Char_code_.Num_0, pad_len, i).Add_char_colon().Add_char_space();
|
||||
Write__itm(bfr, type_id, expd_ary, expd_len, i);
|
||||
if (failure) {
|
||||
bfr.Add(Eq_n).Add_char_repeat(Char_code_.Space, pad_len - 1);
|
||||
Write__itm(bfr, type_id, actl_ary, actl_len, i);
|
||||
}
|
||||
}
|
||||
bfr.Add(Section_end);
|
||||
}
|
||||
private static void Write__itm(String_bfr bfr, int type_id, Object ary, int len, int idx) {
|
||||
if (idx < len) {
|
||||
Object val = Array_.Get_at(ary, idx);
|
||||
switch (type_id) {
|
||||
case Type_ids_.Id__bool: bfr.Add_bool_as_yn(Bool_.Cast(val)); break;
|
||||
case Type_ids_.Id__bry: bfr.Add_bry((byte[])val); break;
|
||||
case Type_ids_.Id__long: bfr.Add_long(Long_.Cast(val)); break;
|
||||
case Type_ids_.Id__int: bfr.Add_int(Int_.Cast(val)); break;
|
||||
case Type_ids_.Id__byte: bfr.Add_int((int)(Byte_.Cast(val))); break;
|
||||
case Type_ids_.Id__obj: bfr.Add(Object_.To_str(val)); break;
|
||||
default: throw Err_.New_unhandled_default(type_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.Add(Null);
|
||||
bfr.Add_char_nl();
|
||||
}
|
||||
private static boolean[] Calc__failures(int tid, Object expd_ary, Object actl_ary) {
|
||||
int expd_len = Array_.Len(expd_ary);
|
||||
int actl_len = Array_.Len(actl_ary);
|
||||
int max_len = expd_len > actl_len ? expd_len : actl_len; if (max_len == 0) return null;
|
||||
boolean[] rv = null;
|
||||
for (int i = 0; i < max_len; ++i) {
|
||||
Object expd_obj = i < expd_len ? Array_.Get_at(expd_ary, i) : null;
|
||||
Object actl_obj = i < actl_len ? Array_.Get_at(actl_ary, i) : null;
|
||||
boolean eq = false;
|
||||
if (expd_obj == null && actl_obj == null) eq = true;
|
||||
else if (expd_obj == null || actl_obj == null) eq = false;
|
||||
else {
|
||||
switch (tid) {
|
||||
case Type_ids_.Id__bool: eq = Bool_.Cast(expd_obj) == Bool_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__bry: eq = Bry_.Eq((byte[])expd_obj, (byte[])actl_obj); break;
|
||||
case Type_ids_.Id__long: eq = Long_.Cast(expd_obj) == Long_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__int: eq = Int_.Cast(expd_obj) == Int_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__byte: eq = Byte_.Cast(expd_obj) == Byte_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__obj: eq = Object_.Eq(expd_obj, actl_obj); break;
|
||||
}
|
||||
}
|
||||
if (!eq) {
|
||||
if (rv == null) {
|
||||
rv = new boolean[max_len];
|
||||
}
|
||||
rv[i] = true;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static final String Null = "<<NULL>>";
|
||||
private static final String Eq_n = "!= "
|
||||
, Section_bgn = "\n************************************************************************************************\n"
|
||||
, Section_mid = "\n------------------------------------------------------------------------------------------------\n"
|
||||
, Section_end = "________________________________________________________________________________________________"
|
||||
;
|
||||
|
||||
// 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 Write(Object... ary) {
|
||||
String_bfr bfr = new String_bfr();
|
||||
int ary_len = Array_.Len(ary);
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
bfr.Add("'");
|
||||
bfr.Add(Object_.To_str_or_null_mark(ary[i]));
|
||||
bfr.Add("' ");
|
||||
}
|
||||
System.out.println(bfr.To_str() + String_.Lf);
|
||||
}
|
||||
}
|
||||
43
baselib/tst/gplx/objects/arrays/ArrayUtlTest.java
Normal file
43
baselib/tst/gplx/objects/arrays/ArrayUtlTest.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.arrays;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class ArrayUtlTest {
|
||||
@Test public void Append() {
|
||||
TestAppend(AryInt(), AryInt(1), AryInt(1)); // 0 + 1 = 1
|
||||
TestAppend(AryInt(0), AryInt(), AryInt(0)); // 1 + 0 = 1
|
||||
TestAppend(AryInt(0), AryInt(1), AryInt(0, 1)); // 1 + 1 = 2
|
||||
}
|
||||
private void TestAppend(int[] source, int[] added, int[] expd) {
|
||||
GfoTstr.EqAry(expd, (int[])ArrayUtl.Append(source, added));
|
||||
}
|
||||
@Test public void Resize() {
|
||||
TestResize(AryInt(0), 0, AryInt()); // 1 -> 0
|
||||
TestResize(AryInt(0, 1), 1, AryInt(0)); // 2 -> 1
|
||||
}
|
||||
private void TestResize(int[] source, int length, int[] expd) {
|
||||
GfoTstr.EqAry(expd, (int[])ArrayUtl.Resize(source, length));
|
||||
}
|
||||
@Test public void Insert() {
|
||||
TestInsert(AryObj(0, 1, 4, 5), AryObj(2, 3), 2, AryObj(0, 1, 2, 3, 4, 5));
|
||||
}
|
||||
private void TestInsert(Object[] cur, Object[] add, int addPos, Object[] expd) {
|
||||
GfoTstr.EqAry(expd, ArrayUtl.Insert(cur, add, addPos));
|
||||
}
|
||||
private Object[] AryObj(Object... ary) {return ary;}
|
||||
private int[] AryInt(int... ary) {return ary;}
|
||||
}
|
||||
37
baselib/tst/gplx/objects/lists/ComparerAbleSorterTest.java
Normal file
37
baselib/tst/gplx/objects/lists/ComparerAbleSorterTest.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
import gplx.objects.arrays.ArrayUtl;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class ComparerAbleSorterTest {
|
||||
@Test public void Basic() {
|
||||
Object[] src = new Object[] {0,8,1,7,2,6,3,5,4};
|
||||
new ComparerAbleSorter().Sort(src, src.length);
|
||||
GfoTstr.EqAry(src, Sequential(0, 8));
|
||||
}
|
||||
@Test public void Basic2() {
|
||||
Object[] src = new Object[] {"0","8","1","7","2","6","3","5","4"};
|
||||
new ComparerAbleSorter().Sort(src, src.length);
|
||||
GfoTstr.EqAry(src, new Object[] {"0","1","2","3","4","5","6","7","8"});
|
||||
}
|
||||
private Object[] Sequential(int bgn, int end) {
|
||||
Object[] rv = new Object[end - bgn + 1];
|
||||
for (int i = 0; i < ArrayUtl.Len(rv); i++)
|
||||
rv[i] = i + bgn;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,83 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.lists;
|
||||
|
||||
import gplx.tests.Gftest_fxt;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
|
||||
public class GfoIndexedListEntryTest {
|
||||
private GfoIndexedList<String, String> list = new GfoIndexedList<>();
|
||||
@Test public void Add() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
private GfoIndexedList<String, String> list = new GfoIndexedList<>();
|
||||
@Test public void Add() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
|
||||
testGetAt(0, "a");
|
||||
testGetAt(1, "b");
|
||||
testGetAt(2, "c");
|
||||
testGetByOrFail("A", "a");
|
||||
testGetByOrFail("B", "b");
|
||||
testGetByOrFail("C", "c");
|
||||
testIterate("a", "b", "c");
|
||||
}
|
||||
@Test public void DelBy() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
testGetAt(0, "a");
|
||||
testGetAt(1, "b");
|
||||
testGetAt(2, "c");
|
||||
testGetByOrFail("A", "a");
|
||||
testGetByOrFail("B", "b");
|
||||
testGetByOrFail("C", "c");
|
||||
testIterate("a", "b", "c");
|
||||
}
|
||||
@Test public void DelBy() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
|
||||
list.DelBy("A");
|
||||
list.DelBy("A");
|
||||
|
||||
testIterate("b", "c");
|
||||
testIterate("b", "c");
|
||||
|
||||
list.DelBy("B");
|
||||
list.DelBy("B");
|
||||
|
||||
testIterate("c");
|
||||
testIterate("c");
|
||||
|
||||
list.DelBy("C");
|
||||
list.DelBy("C");
|
||||
|
||||
testIterate();
|
||||
}
|
||||
@Test public void DelBy_SameVal() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "a");
|
||||
testIterate();
|
||||
}
|
||||
@Test public void DelBySameVal() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "a");
|
||||
|
||||
list.DelBy("C");
|
||||
list.DelBy("C");
|
||||
|
||||
testIterate("a", "b"); // fails if "b", "a"
|
||||
}
|
||||
@Test public void Set() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
testIterate("a", "b"); // fails if "b", "a"
|
||||
}
|
||||
@Test public void Set() {
|
||||
list.Add("A", "a");
|
||||
list.Add("B", "b");
|
||||
list.Add("C", "c");
|
||||
|
||||
list.Set("B", "bb");
|
||||
testGetByOrFail("B", "bb");
|
||||
testIterate("a", "bb", "c");
|
||||
}
|
||||
private void testGetByOrFail(String key, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, list.GetByOrFail(key));
|
||||
}
|
||||
private void testGetAt(int idx, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, list.GetAt(idx));
|
||||
}
|
||||
private void testIterate(String... expd) {
|
||||
String[] actl = new String[expd.length];
|
||||
int i = 0;
|
||||
for (String itm : list) {
|
||||
actl[i++] = itm;
|
||||
}
|
||||
Gftest_fxt.Eq__ary(expd, actl);
|
||||
}
|
||||
}
|
||||
list.Set("B", "bb");
|
||||
testGetByOrFail("B", "bb");
|
||||
testIterate("a", "bb", "c");
|
||||
}
|
||||
private void testGetByOrFail(String key, String expd) {
|
||||
GfoTstr.EqStr(expd, list.GetByOrFail(key));
|
||||
}
|
||||
private void testGetAt(int idx, String expd) {
|
||||
GfoTstr.EqStr(expd, list.GetAt(idx));
|
||||
}
|
||||
private void testIterate(String... expd) {
|
||||
String[] actl = new String[expd.length];
|
||||
int i = 0;
|
||||
for (String itm : list) {
|
||||
actl[i++] = itm;
|
||||
}
|
||||
GfoTstr.EqAry(expd, actl);
|
||||
}
|
||||
}
|
||||
|
||||
31
baselib/tst/gplx/objects/primitives/BoolUtlTest.java
Normal file
31
baselib/tst/gplx/objects/primitives/BoolUtlTest.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
import gplx.objects.lists.CompareAbleUtl;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.*;
|
||||
public class BoolUtlTest {
|
||||
private final BoolUtlTstr fxt = new BoolUtlTstr();
|
||||
@Test public void Compare() {
|
||||
fxt.TestCompare(BoolUtl.Y, BoolUtl.Y, CompareAbleUtl.Same);
|
||||
fxt.TestCompare(BoolUtl.N, BoolUtl.N, CompareAbleUtl.Same);
|
||||
fxt.TestCompare(BoolUtl.N, BoolUtl.Y, CompareAbleUtl.Less);
|
||||
fxt.TestCompare(BoolUtl.Y, BoolUtl.N, CompareAbleUtl.More);
|
||||
}
|
||||
}
|
||||
class BoolUtlTstr {
|
||||
public void TestCompare(boolean lhs, boolean rhs, int expd) {GfoTstr.EqInt(expd, BoolUtl.Compare(lhs, rhs));}
|
||||
}
|
||||
49
baselib/tst/gplx/objects/primitives/DoubleUtlTest.java
Normal file
49
baselib/tst/gplx/objects/primitives/DoubleUtlTest.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class DoubleUtlTest {
|
||||
private final DoubleUtlTstr tstr = new DoubleUtlTstr();
|
||||
|
||||
@Test
|
||||
public void TrimZeroes() {
|
||||
tstr.TestTrimZeroes("12.100" , "12.1");
|
||||
tstr.TestTrimZeroes("12.000" , "12");
|
||||
tstr.TestTrimZeroes("12.001" , "12.001");
|
||||
tstr.TestTrimZeroes("1020.00" , "1020");
|
||||
tstr.TestTrimZeroes("1020.00" , "1020");
|
||||
tstr.TestTrimZeroes("1.200e5" , "1.2E5");
|
||||
tstr.TestTrimZeroes("1.200e-05" , "1.2E-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ToStrByPrintF() {
|
||||
tstr.TestToStrByPrintF(1d / 2d , "0.5"); // fails with 0.50000000000000
|
||||
tstr.TestToStrByPrintF(5d / 100000000000000000d, "5E-17"); // fails with 5.0000000000000e-17
|
||||
tstr.TestToStrByPrintF(7538000d / 7773352000d , "0.00096972322879499"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.TestToStrByPrintF(56225d / 7776747000d , "7.2298867379895E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.TestToStrByPrintF(35746d / 7805411000d , "4.5796435319037E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
}
|
||||
}
|
||||
class DoubleUtlTstr {
|
||||
public void TestToStrByPrintF(double v, String expd) {
|
||||
GfoTstr.EqStr(expd, DoubleUtl.ToStrByPrintF(v));
|
||||
}
|
||||
public void TestTrimZeroes(String val, String expd) {
|
||||
GfoTstr.EqStr(expd, DoubleUtl.TrimZeroes(val));
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
|
||||
import gplx.tests.Gftest_fxt;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Double_Test {
|
||||
private final Double_Tstr tstr = new Double_Tstr();
|
||||
|
||||
@Test
|
||||
public void TrimZeroes() {
|
||||
tstr.Test_TrimZeroes("12.100" , "12.1");
|
||||
tstr.Test_TrimZeroes("12.000" , "12");
|
||||
tstr.Test_TrimZeroes("12.001" , "12.001");
|
||||
tstr.Test_TrimZeroes("1020.00" , "1020");
|
||||
tstr.Test_TrimZeroes("1020.00" , "1020");
|
||||
tstr.Test_TrimZeroes("1.200e5" , "1.2E5");
|
||||
tstr.Test_TrimZeroes("1.200e-05" , "1.2E-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ToStrByPrintF() {
|
||||
tstr.Test_ToStrByPrintF(1d / 2d , "0.5"); // fails with 0.50000000000000
|
||||
tstr.Test_ToStrByPrintF(5d / 100000000000000000d, "5E-17"); // fails with 5.0000000000000e-17
|
||||
tstr.Test_ToStrByPrintF(7538000d / 7773352000d , "0.00096972322879499"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.Test_ToStrByPrintF(56225d / 7776747000d , "7.2298867379895E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
tstr.Test_ToStrByPrintF(35746d / 7805411000d , "4.5796435319037E-06"); // fails with 0; ISSUE#:697; DATE:2020-08-11
|
||||
}
|
||||
}
|
||||
class Double_Tstr {
|
||||
public void Test_ToStrByPrintF(double v, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, Double_.ToStrByPrintF(v));
|
||||
}
|
||||
public void Test_TrimZeroes(String val, String expd) {
|
||||
Gftest_fxt.Eq__str(expd, Double_.TrimZeroes(val));
|
||||
}
|
||||
}
|
||||
91
baselib/tst/gplx/objects/primitives/IntUtlTest.java
Normal file
91
baselib/tst/gplx/objects/primitives/IntUtlTest.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.primitives;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class IntUtlTest {
|
||||
private final IntUtlTstr fxt = new IntUtlTstr();
|
||||
@Test public void ParseOr() {
|
||||
fxt.TestParseOr("123", 123); // basic
|
||||
fxt.TestParseOrMinValue(null); // null
|
||||
fxt.TestParseOrMinValue(""); // empty
|
||||
fxt.TestParseOrMinValue("1a"); // invalid number
|
||||
|
||||
fxt.TestParseOr("-123", -123); // negative
|
||||
fxt.TestParseOrMinValue("1-23"); // negative at invalid position
|
||||
}
|
||||
@Test public void Between() {
|
||||
fxt.TestBetween(1, 0, 2, true); // simple true
|
||||
fxt.TestBetween(3, 0, 2, false); // simple false
|
||||
fxt.TestBetween(0, 0, 2, true); // bgn true
|
||||
fxt.TestBetween(2, 0, 2, true); // end true
|
||||
}
|
||||
@Test public void CountDigits() {
|
||||
fxt.TestCountDigits( 0, 1);
|
||||
fxt.TestCountDigits( 9, 1);
|
||||
fxt.TestCountDigits( 100, 3);
|
||||
fxt.TestCountDigits( -1, 2);
|
||||
fxt.TestCountDigits(-100, 4);
|
||||
}
|
||||
@Test public void Log10() {
|
||||
fxt.TestLog10( 0, 0);
|
||||
fxt.TestLog10( 1, 0);
|
||||
fxt.TestLog10( 2, 0);
|
||||
fxt.TestLog10( 10, 1);
|
||||
fxt.TestLog10( 12, 1);
|
||||
fxt.TestLog10( 100, 2);
|
||||
fxt.TestLog10( 123, 2);
|
||||
fxt.TestLog10( 1000, 3);
|
||||
fxt.TestLog10( 1234, 3);
|
||||
fxt.TestLog10( 10000, 4);
|
||||
fxt.TestLog10( 12345, 4);
|
||||
fxt.TestLog10( 100000, 5);
|
||||
fxt.TestLog10( 123456, 5);
|
||||
fxt.TestLog10( 1000000, 6);
|
||||
fxt.TestLog10( 1234567, 6);
|
||||
fxt.TestLog10( 10000000, 7);
|
||||
fxt.TestLog10( 12345678, 7);
|
||||
fxt.TestLog10( 100000000, 8);
|
||||
fxt.TestLog10( 123456789, 8);
|
||||
fxt.TestLog10( 1000000000, 9);
|
||||
fxt.TestLog10( 1234567890, 9);
|
||||
fxt.TestLog10(IntUtl.MaxValue, 9);
|
||||
fxt.TestLog10( -1, 0);
|
||||
fxt.TestLog10( -10, -1);
|
||||
fxt.TestLog10( -100, -2);
|
||||
fxt.TestLog10( -1000000, -6);
|
||||
fxt.TestLog10( -1000000000, -9);
|
||||
fxt.TestLog10(IntUtl.MinValue, -9);
|
||||
fxt.TestLog10(IntUtl.MinValue + 1, -9);
|
||||
}
|
||||
}
|
||||
class IntUtlTstr {
|
||||
public void TestParseOr(String raw, int expd) {
|
||||
GfoTstr.EqInt(expd, IntUtl.ParseOr(raw, -1));
|
||||
}
|
||||
public void TestParseOrMinValue(String raw) {
|
||||
GfoTstr.EqInt(IntUtl.MinValue, IntUtl.ParseOr(raw, IntUtl.MinValue));
|
||||
}
|
||||
public void TestBetween(int val, int lhs, int rhs, boolean expd) {
|
||||
GfoTstr.EqBool(expd, IntUtl.Between(val, lhs, rhs));
|
||||
}
|
||||
public void TestCountDigits(int val, int expd) {
|
||||
GfoTstr.EqInt(expd, IntUtl.CountDigits(val), IntUtl.ToStr(val));
|
||||
}
|
||||
public void TestLog10(int val, int expd) {
|
||||
GfoTstr.EqInt(expd, IntUtl.Log10(val));
|
||||
}
|
||||
}
|
||||
48
baselib/tst/gplx/objects/strings/StringUtlTest.java
Normal file
48
baselib/tst/gplx/objects/strings/StringUtlTest.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class StringUtlTest {
|
||||
private final StringUtlTstr fxt = new StringUtlTstr();
|
||||
@Test public void Len() {
|
||||
fxt.TestLen("" , 0);
|
||||
fxt.TestLen("abc", 3);
|
||||
}
|
||||
@Test public void Format() {
|
||||
fxt.TestFormat("empty fmt" , "" , "");
|
||||
fxt.TestFormat("empty fmt w/ args" , "" , "", "a");
|
||||
fxt.TestFormat("no args" , "a" , "a");
|
||||
fxt.TestFormat("args = 1" , "a" , "{0}", "a");
|
||||
fxt.TestFormat("args = n" , "a + b" , "{0} + {1}", "a", "b");
|
||||
fxt.TestFormat("escape {" , "{" , "{{", 0);
|
||||
fxt.TestFormat("escape }" , "}" , "}}", 0);
|
||||
fxt.TestFormat("nested" , "{a0c}" , "{a{0}c}", 0);
|
||||
fxt.TestFormat("nested; invalid" , "{a{b}c}" , "{a{b}c}", 0);
|
||||
fxt.TestFormat("out of bounds" , "{1}" , "{1}", "a");
|
||||
fxt.TestFormat("invalid arg" , "{a} {b}" , "{a} {b}", 0);
|
||||
fxt.TestFormat("invalid and valid args" , "{a}0{b}1", "{a}{0}{b}{1}", 0, 1);
|
||||
fxt.TestFormat("dangling" , "{0" , "{0", 0);
|
||||
}
|
||||
}
|
||||
class StringUtlTstr {
|
||||
public void TestLen(String v, int expd) {
|
||||
GfoTstr.EqInt(expd, StringUtl.Len(v));
|
||||
}
|
||||
public void TestFormat(String note, String expd, String fmt, Object... ary) {
|
||||
GfoTstr.EqStr(expd, StringUtl.Format(fmt, ary), note);
|
||||
}
|
||||
}
|
||||
105
baselib/tst/gplx/objects/strings/unicodes/UstringUtlTest.java
Normal file
105
baselib/tst/gplx/objects/strings/unicodes/UstringUtlTest.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.objects.strings.unicodes;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.tests.GfoTstr;
|
||||
import org.junit.Test;
|
||||
public class UstringUtlTest {
|
||||
private final UstringTstr fxt = new UstringTstr();
|
||||
@Test public void Empty() {
|
||||
fxt.Init("");
|
||||
fxt.TestLen(0, 0);
|
||||
}
|
||||
@Test public void Blank() {
|
||||
fxt.Init("");
|
||||
fxt.TestLen(0, 0);
|
||||
}
|
||||
@Test public void Single() {
|
||||
fxt.Init("Abc");
|
||||
fxt.TestLen(3, 3);
|
||||
fxt.TestGetCode(65, 98, 99);
|
||||
fxt.TestMapCodeToChar(0, 1, 2, 3);
|
||||
fxt.TestMapCharToCode(0, 1, 2, 3);
|
||||
}
|
||||
@Test public void Multi() {
|
||||
fxt.Init("a¢€𤭢b");
|
||||
fxt.TestLen(5, 6);
|
||||
fxt.TestGetCode(97, 162, 8364, 150370, 98);
|
||||
fxt.TestMapCodeToChar(0, 1, 2, 3, 5, 6);
|
||||
fxt.TestMapCharToCode(0, 1, 2, 3, -1, 4, 5);
|
||||
}
|
||||
@Test public void IndexOf() {
|
||||
fxt.TestIndexOf("abc", "b", 0, 1); // basic
|
||||
fxt.TestIndexOf("ab", "bc", 0, -1); // out-of-bounds
|
||||
fxt.TestIndexOf("a¢e", "¢", 0, 1); // check UTF-8 strings still match at byte-level
|
||||
}
|
||||
|
||||
@Test public void Substring() {
|
||||
fxt.TestSubstring("abc", 1, 2, "b"); // basic
|
||||
fxt.TestSubstring("¢bc", 1, 2, "b"); // check UTF-8 strings don't get lopped off
|
||||
}
|
||||
}
|
||||
class UstringTstr {
|
||||
private Ustring under;
|
||||
public void Init(String src) {
|
||||
this.under = UstringUtl.NewCodepoints(src);
|
||||
}
|
||||
public void TestLen(int expdCodes, int expdChars) {
|
||||
GfoTstr.EqInt(expdCodes, under.LenInData(), "codes");
|
||||
GfoTstr.EqInt(expdChars, under.LenInChars(), "chars");
|
||||
}
|
||||
public void TestGetCode(int... expd) {
|
||||
int actlLen = under.LenInData();
|
||||
int[] actl = new int[actlLen];
|
||||
for (int i = 0; i < actlLen; i++)
|
||||
actl[i] = under.GetData(i);
|
||||
GfoTstr.EqAry(expd, actl);
|
||||
}
|
||||
public void TestMapCodeToChar(int... expd) {
|
||||
int actlLen = under.LenInData() + 1;
|
||||
int[] actl = new int[actlLen];
|
||||
for (int i = 0; i < actlLen; i++)
|
||||
actl[i] = under.MapDataToChar(i);
|
||||
GfoTstr.EqAry(expd, actl);
|
||||
}
|
||||
public void TestMapCharToCode(int... expd) {
|
||||
int actlLen = under.LenInChars() + 1;
|
||||
int[] actl = new int[actlLen];
|
||||
for (int i = 0; i < actlLen; i++) {
|
||||
int val = 0;
|
||||
try {
|
||||
val = under.MapCharToData(i);
|
||||
}
|
||||
catch (Exception exc) {
|
||||
val = -1;
|
||||
ErrUtl.Noop(exc);
|
||||
}
|
||||
actl[i] = val;
|
||||
}
|
||||
GfoTstr.EqAry(expd, actl);
|
||||
}
|
||||
public void TestIndexOf(String srcStr, String findStr, int bgn, int expd) {
|
||||
Ustring src = UstringUtl.NewCodepoints(srcStr);
|
||||
Ustring find = UstringUtl.NewCodepoints(findStr);
|
||||
int actl = src.IndexOf(find, bgn);
|
||||
GfoTstr.EqInt(expd, actl);
|
||||
}
|
||||
public void TestSubstring(String srcStr, int bgn, int end, String expd) {
|
||||
Ustring src = UstringUtl.NewCodepoints(srcStr);
|
||||
String actl = src.Substring(bgn, end);
|
||||
GfoTstr.EqStr(expd, actl);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user