mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
Refactor: Pull more classes into baselib
This commit is contained in:
@@ -13,7 +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.events;
|
||||
package gplx.frameworks.events;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
public class GfoEvent<A> {
|
||||
@@ -13,7 +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.events;
|
||||
package gplx.frameworks.events;
|
||||
public interface GfoEventOwner {
|
||||
boolean EventsEnabled(); void EventsEnabledSet(boolean v);
|
||||
}
|
||||
@@ -13,7 +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.events;
|
||||
package gplx.frameworks.events;
|
||||
public interface GfoHandler<A> {
|
||||
void Run(GfoEventOwner sender, A args);
|
||||
}
|
||||
@@ -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;
|
||||
public class FloatUtl {
|
||||
public static final String ClsValName = "float";
|
||||
public static final Class<?> ClsRefType = Float.class;
|
||||
package gplx.frameworks.objects;
|
||||
public interface ToStrAble {
|
||||
String ToStr();
|
||||
}
|
||||
@@ -13,10 +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.*;
|
||||
public class Err extends RuntimeException {
|
||||
private final String msg;
|
||||
public Err(String msg) {this.msg = msg;}
|
||||
@Override public String getMessage() {return msg;}
|
||||
package gplx.frameworks.objects;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
public class ToStrAbleUtl {
|
||||
public static ToStrAble CastOrNull(Object obj) {return obj instanceof ToStrAble ? (ToStrAble)obj : null;}
|
||||
}
|
||||
270
baselib/src/gplx/frameworks/tests/GfoTstr.java
Normal file
270
baselib/src/gplx/frameworks/tests/GfoTstr.java
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
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.frameworks.tests;
|
||||
import gplx.frameworks.objects.ToStrAble;
|
||||
import gplx.frameworks.objects.ToStrAbleUtl;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.basics.constants.CharCode;
|
||||
import gplx.types.basics.utls.ArrayUtl;
|
||||
import gplx.types.basics.utls.BoolUtl;
|
||||
import gplx.types.basics.utls.BryLni;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.CharUtl;
|
||||
import gplx.types.basics.utls.ClassUtl;
|
||||
import gplx.types.basics.utls.DoubleUtl;
|
||||
import gplx.types.basics.utls.FloatUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.LongUtl;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import gplx.types.basics.utls.TypeIds;
|
||||
import gplx.types.commons.GfoDate;
|
||||
import gplx.types.commons.GfoDecimal;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class GfoTstr {
|
||||
private static final GfoStringBldr bfr = new GfoStringBldr();
|
||||
private static final String
|
||||
EqN = "!= ",
|
||||
Null = "<<NULL>>",
|
||||
SectionBgn = "\n************************************************************************************************\n",
|
||||
SectionMid = "\n------------------------------------------------------------------------------------------------\n",
|
||||
SectionEnd = "________________________________________________________________________________________________";
|
||||
|
||||
public static void Debug(Object... ary) {Write(ary);}
|
||||
public static void Write(byte[] s, int b, int e) {Write(BryLni.Mid(s, b, e));}
|
||||
public static void Write() {Write("tmp");}
|
||||
public static void Write(Object... ary) {
|
||||
GfoStringBldr bfr = new GfoStringBldr();
|
||||
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.Nl);
|
||||
}
|
||||
public static void EqNull(Object actl) {EqNull(true , actl, null);}
|
||||
public static void EqNull(Object actl, String fmt, Object... args) {EqNull(true , actl, StringUtl.Format(fmt, args));}
|
||||
public static void EqNotNull(Object actl) {EqNull(false, actl, null);}
|
||||
public static void EqNotNull(Object actl, String fmt, Object... args) {EqNull(false, actl, StringUtl.Format(fmt, args));}
|
||||
private static final void EqNull(boolean expd, Object actl, String fmt, Object... args) {
|
||||
if ( expd && actl != null
|
||||
|| !expd && actl == null
|
||||
) {
|
||||
String expdStr = expd ? "null" : "not null";
|
||||
String actlStr = actl == null ? "null" : "not null";
|
||||
WriteAndThrow(expdStr, actlStr, fmt, args);
|
||||
}
|
||||
}
|
||||
public static void EqBoolY(boolean actl) {Eq(true , actl, null);}
|
||||
public static void EqBoolY(boolean actl, String fmt, Object... args) {Eq(true , actl, StringUtl.Format(fmt, args));}
|
||||
public static void EqBoolN(boolean actl) {Eq(false, actl, null);}
|
||||
public static void EqBoolN(boolean actl, String fmt, Object... args) {Eq(false, actl, StringUtl.Format(fmt, args));}
|
||||
public static void Eq(boolean expd, boolean actl) {Eq(expd, actl, null);}
|
||||
public static void Eq(boolean expd, boolean actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(BoolUtl.ToStrLower(expd), BoolUtl.ToStrLower(actl), fmt, args);
|
||||
}
|
||||
public static void EqByte(byte expd, byte actl) {Eq(expd, actl, null);}
|
||||
public static void EqByte(byte expd, byte actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(ByteUtl.ToStr(expd), ByteUtl.ToStr(actl), fmt, args);
|
||||
}
|
||||
public static void Eq(int expd, int actl) {Eq(expd, actl, null);}
|
||||
public static void Eq(int expd, int actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(IntUtl.ToStr(expd), IntUtl.ToStr(actl), fmt, args);
|
||||
}
|
||||
public static void EqLong(long expd, long actl) {EqLong(expd, actl, null);}
|
||||
public static void EqLong(long expd, long actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(LongUtl.ToStr(expd), LongUtl.ToStr(actl), fmt, args);
|
||||
}
|
||||
public static void EqFloat(float expd, float actl) {EqFloat(expd, actl, null);}
|
||||
public static void EqFloat(float expd, float actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(FloatUtl.ToStr(expd), FloatUtl.ToStr(actl), fmt, args);
|
||||
}
|
||||
public static void EqDouble(double expd, double actl) {EqDouble(expd, actl, null);}
|
||||
public static void EqDouble(double expd, double actl, String fmt, Object... args) {
|
||||
if (expd != actl)
|
||||
WriteAndThrow(DoubleUtl.ToStr(expd), DoubleUtl.ToStr(actl), fmt, args);
|
||||
}
|
||||
public static void Eq(byte[] expd, byte[] actl) {Eq(StringUtl.NewU8(expd), StringUtl.NewU8(actl), null);}
|
||||
public static void Eq(byte[] expd, byte[] actl, String fmt, Object... args) {Eq(StringUtl.NewU8(expd), StringUtl.NewU8(actl), fmt, args);}
|
||||
public static void Eq(byte[] expd, String actl) {Eq(StringUtl.NewU8(expd), actl, null);}
|
||||
public static void Eq(byte[] expd, String actl, String fmt, Object... args) {Eq(StringUtl.NewU8(expd), actl, fmt, args);}
|
||||
public static void Eq(String expd, byte[] actl) {Eq(expd, StringUtl.NewU8(actl), null);}
|
||||
public static void Eq(String expd, byte[] actl, String fmt, Object... args) {Eq(expd, StringUtl.NewU8(actl), fmt, args);}
|
||||
public static void Eq(String expd, String actl) {Eq(expd, actl, null);}
|
||||
public static void Eq(String expd, String actl, String fmt, Object... args) {
|
||||
if (!StringUtl.Eq(expd, actl))
|
||||
WriteAndThrow(expd, actl, fmt, args);
|
||||
}
|
||||
public static void Eq(GfoDate expd, GfoDate actl) {Eq(expd.ToStrGplx(), actl.ToStrGplx());}
|
||||
public static void Eq(GfoDate expd, GfoDate actl, String fmt, Object... args) {Eq(expd.ToStrGplx(), actl.ToStrGplx(), fmt, args);}
|
||||
public static void Eq(GfoDecimal expd, GfoDecimal actl) {EqDouble(expd.ToDouble(), actl.ToDouble());}
|
||||
public static void EqErr(Exception exc, Class<?> type) {
|
||||
if (!ClassUtl.Eq(exc.getClass(), type))
|
||||
throw ErrUtl.NewArgs("error types do not match", "expdType", ClassUtl.CanonicalName(type), "actlType", ClassUtl.NameByObj(exc), "actlMsg", ErrUtl.Message(exc));
|
||||
}
|
||||
public static void ErrHas(Exception e, String hdr) {
|
||||
if (!StringUtl.Has(ErrUtl.ToStrFull(e), hdr))
|
||||
throw ErrUtl.NewFmt("could not find '{0}' in '{1}'", hdr, ErrUtl.ToStrFull(e));
|
||||
}
|
||||
public static void Eq(ToStrAble expd, ToStrAble actl) {Eq(expd.ToStr(), actl.ToStr());}
|
||||
public static void Eq(ToStrAble expd, ToStrAble actl, String fmt, Object... args) {Eq(expd.ToStr(), actl.ToStr(), fmt, args);}
|
||||
public static void EqObj(Object expd, Object actl) {EqObj(expd, actl, "");}
|
||||
public static void EqObj(Object expd, Object actl, String msgFmt, Object... msgArgs) {
|
||||
if (!ObjectUtl.Eq(expd, actl))
|
||||
WriteAndThrow(ObjectUtl.ToStr(expd), ObjectUtl.ToStr(actl), msgFmt, msgArgs);
|
||||
}
|
||||
public static void EqObjToStr(Object expd, Object actl) {
|
||||
Eq(ObjectUtl.ToStrOrNullMark(expd), ObjectUtl.ToStrOrNullMark(actl));
|
||||
}
|
||||
// NOTE: EqLines will ignore differences in last trailing line; EX: expd="a" == actl ="a\n"
|
||||
public static void EqLines(String expd, String actl) {EqAry(TypeIds.IdStr, SplitLines(expd), SplitLines(actl), null);}
|
||||
public static void EqLines(String expd, String actl, String fmt, Object... args) {EqAry(TypeIds.IdStr, SplitLines(expd), SplitLines(actl), fmt, args);}
|
||||
public static void EqLines(String expd, byte[] actl) {EqAry(TypeIds.IdStr, SplitLines(expd), SplitLines(StringUtl.NewU8(actl)), null);}
|
||||
public static void EqLines(String expd, byte[] actl, String fmt, Object... args) {EqAry(TypeIds.IdStr, SplitLines(expd), SplitLines(StringUtl.NewU8(actl)), fmt, args);}
|
||||
public static void EqLines(byte[][] expd, byte[][] actl) {EqAry(TypeIds.IdBry, expd, actl, null);}
|
||||
public static void EqLines(byte[][] expd, byte[][] actl, String fmt, Object... args) {EqAry(TypeIds.IdBry, expd, actl, fmt, args);}
|
||||
public static void EqLines(String[] expd, String[] actl) {EqAry(TypeIds.IdBry, BryUtl.Ary(expd), BryUtl.Ary(actl), null);}
|
||||
public static void EqLines(String[] expd, String[] actl, String fmt, Object... args) {EqAry(TypeIds.IdBry, BryUtl.Ary(expd), BryUtl.Ary(actl), fmt, args);}
|
||||
public static void EqLines(String[] expd, byte[][] actl) {EqAry(TypeIds.IdBry, BryUtl.Ary(expd), actl, null);}
|
||||
public static void EqLines(String[] expd, byte[][] actl, String fmt, Object... args) {EqAry(TypeIds.IdBry, BryUtl.Ary(expd), actl, fmt, args);}
|
||||
public static void EqAry(boolean[] expd, boolean[] actl) {EqAry(TypeIds.IdBool, expd, actl, null);}
|
||||
public static void EqAry(boolean[] expd, boolean[] actl, String fmt, Object... args) {EqAry(TypeIds.IdBool, expd, actl, fmt, args);}
|
||||
public static void EqAry(byte[] expd, byte[] actl) {EqAry(TypeIds.IdByte, expd, actl, null);}
|
||||
public static void EqAry(byte[] expd, byte[] actl, String fmt, Object... args) {EqAry(TypeIds.IdByte, expd, actl, fmt, args);}
|
||||
public static void EqAry(int[] expd, int[] actl) {EqAry(TypeIds.IdInt, expd, actl, null);}
|
||||
public static void EqAry(int[] expd, int[] actl, String msg) {EqAry(TypeIds.IdInt, expd, actl, msg);}
|
||||
public static void EqAry(long[] expd, long[] actl) {EqAry(TypeIds.IdLong, expd, actl, null);}
|
||||
public static void EqAry(long[] expd, long[] actl, String msg) {EqAry(TypeIds.IdLong, expd, actl, msg);}
|
||||
public static void EqAry(int[] expd, int[] actl, String msg, Object... args) {EqAry(TypeIds.IdInt, expd, actl, msg, args);}
|
||||
public static void EqAryObj(Object expd, Object actl) {EqAry(TypeIds.IdObj, expd, actl, null);}
|
||||
public static void EqAryObj(Object expd, Object actl, String fmt, Object... args) {EqAry(TypeIds.IdObj, expd, actl, fmt, args);}
|
||||
private static String[] SplitLines(String s) {
|
||||
if (s == null) s = "";
|
||||
return StringUtl.Split(s, CharUtl.NewLine);
|
||||
}
|
||||
// NOTE: EqAryObjAry compares on .toString, not .equals; this should be changed to compare on .equals, but need to add .equals to .hashcode to multiple types
|
||||
private static final int IdToStr = -1;
|
||||
public static void EqAryObjAry(Object[] expd, Object[] actl) {EqAry(IdToStr, expd, actl, null);}
|
||||
public static void EqAryObjAry(Object[] expd, Object[] actl, String fmt, Object... args) {EqAry(IdToStr, expd, actl, fmt, args);}
|
||||
private static final 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());
|
||||
}
|
||||
}
|
||||
public static void Fail(String fmt, Object... args) {
|
||||
throw ErrUtl.NewMsg(StringUtl.Format(fmt, args));
|
||||
}
|
||||
public static void FailBcExpdError() {Eq(false, true, "fail expd error");}
|
||||
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 = BryLni.Eq((byte[])expdObj, (byte[])actlObj); break;
|
||||
case TypeIds.IdObj: eq = ObjectUtl.Eq(expdObj, actlObj); break;
|
||||
case TypeIds.IdStr: eq = StringUtl.Eq(StringUtl.Cast(expdObj), StringUtl.Cast(actlObj)); break;
|
||||
case IdToStr: eq = StringUtl.Eq(ToStrOrNativeToString(expdObj), ToStrOrNativeToString(actlObj)); break;
|
||||
}
|
||||
}
|
||||
if (!eq) {
|
||||
if (rv == null) {
|
||||
rv = new boolean[maxLen];
|
||||
}
|
||||
rv[i] = true;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void WriteFailHead(GfoStringBldr bfr, String msgFmt, Object[] msgArgs) {
|
||||
bfr.Add(SectionBgn);
|
||||
if (msgFmt != null) {
|
||||
bfr.Add(StringUtl.Format(msgFmt, msgArgs));
|
||||
bfr.Add(SectionMid);
|
||||
}
|
||||
}
|
||||
private static void WriteFailBody(GfoStringBldr 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(GfoStringBldr 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.Add((byte[])val); break;
|
||||
case TypeIds.IdLong: bfr.AddLong(LongUtl.Cast(val)); break;
|
||||
case TypeIds.IdInt: bfr.Add(IntUtl.Cast(val)); break;
|
||||
case TypeIds.IdByte: bfr.Add(ByteUtl.Cast(val)); break;
|
||||
case TypeIds.IdObj: bfr.Add(ObjectUtl.ToStr(val)); break;
|
||||
case TypeIds.IdStr: bfr.Add(StringUtl.Cast(val)); break;
|
||||
case IdToStr: bfr.Add(ToStrOrNativeToString(val)); break;
|
||||
default: throw ErrUtl.NewUnhandled(typeId);
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.Add(Null);
|
||||
bfr.AddCharNl();
|
||||
}
|
||||
protected 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());
|
||||
}
|
||||
private static String ToStrOrNativeToString(Object o) {
|
||||
ToStrAble strAble = ToStrAbleUtl.CastOrNull(o);
|
||||
return strAble == null
|
||||
? ObjectUtl.ToStrOrNullMark(o)
|
||||
: strAble.ToStr();
|
||||
}
|
||||
}
|
||||
34
baselib/src/gplx/langs/html/HtmlEntityCodes.java
Normal file
34
baselib/src/gplx/langs/html/HtmlEntityCodes.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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.langs.html;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
public class HtmlEntityCodes {
|
||||
public static final String
|
||||
NlStr = " "
|
||||
;
|
||||
public static final byte[]
|
||||
LtBry = BryUtl.NewA7("<"),
|
||||
GtBry = BryUtl.NewA7(">"),
|
||||
AmpBry = BryUtl.NewA7("&"),
|
||||
QuoteBry = BryUtl.NewA7("""),
|
||||
AposNumBry = BryUtl.NewA7("'"),
|
||||
EqBry = BryUtl.NewA7("="),
|
||||
NlBry = BryUtl.NewA7(NlStr),
|
||||
CrBry = BryUtl.NewA7(" "),
|
||||
TabBry = BryUtl.NewA7("	"),
|
||||
SpaceBry = BryUtl.NewA7(" "),
|
||||
NbspNumBry = BryUtl.NewA7(" ");
|
||||
}
|
||||
9
baselib/src/gplx/libs/ios/IoConsts.java
Normal file
9
baselib/src/gplx/libs/ios/IoConsts.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package gplx.libs.ios;
|
||||
public class IoConsts {
|
||||
public static final int
|
||||
LenKB = 1024,
|
||||
LenMB = 1048576,
|
||||
LenGB = 1073741824;
|
||||
public static final long LenMBAsLong = LenMB;
|
||||
public static final long LenNull = -1;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
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,43 +0,0 @@
|
||||
/*
|
||||
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,110 +0,0 @@
|
||||
/*
|
||||
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,96 +0,0 @@
|
||||
/*
|
||||
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,88 +0,0 @@
|
||||
/*
|
||||
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,171 +0,0 @@
|
||||
/*
|
||||
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());
|
||||
}
|
||||
}
|
||||
77
baselib/src/gplx/types/basics/arrays/IntAry.java
Normal file
77
baselib/src/gplx/types/basics/arrays/IntAry.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
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.types.basics.arrays;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class IntAry {
|
||||
private int max;
|
||||
public IntAry(int max) {
|
||||
this.len = 0;
|
||||
this.max = max;
|
||||
this.ary = new int[max];
|
||||
}
|
||||
public int Len() {return len;} private int len;
|
||||
public int[] Ary() {return ary;} private int[] ary;
|
||||
public void Clear() {
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i] = 0;
|
||||
len = 0;
|
||||
}
|
||||
public int GetAt(int i) {
|
||||
if (i > -1 && i < len)
|
||||
return ary[i];
|
||||
else
|
||||
throw ErrUtl.NewArgs("index is invalid", "i", i, "len", len);
|
||||
}
|
||||
public void Add(int v) {
|
||||
if (len == max) {
|
||||
int newMax = max * 2;
|
||||
int[] newAry = new int[newMax];
|
||||
for (int i = 0; i < len; ++i)
|
||||
newAry[i] = ary[i];
|
||||
this.ary = newAry;
|
||||
this.max = newMax;
|
||||
}
|
||||
ary[len] = v;
|
||||
++len;
|
||||
}
|
||||
public int PopOrFail() {
|
||||
if (len == 0) throw ErrUtl.NewArgs("stack is empty");
|
||||
return PopOr(-1);
|
||||
}
|
||||
public int PopOr(int or) {
|
||||
if (len == 0) return or;
|
||||
int rv = ary[len - 1];
|
||||
--len;
|
||||
return rv;
|
||||
}
|
||||
public int IdxOf(int find) {
|
||||
for (int i = len - 1; i > -1; --i) {
|
||||
if (ary[i] == find)
|
||||
return i;
|
||||
}
|
||||
return NotFound;
|
||||
}
|
||||
public boolean DelFromEnd(int find) {
|
||||
int findIdx = IdxOf(find); if (findIdx == NotFound) return false;
|
||||
int lastIdx = len - 1;
|
||||
for (int i = findIdx; i < lastIdx; ++i)
|
||||
ary[i] = ary[i + 1];
|
||||
ary[lastIdx] = 0;
|
||||
--len;
|
||||
return true;
|
||||
}
|
||||
public static final int NotFound = -1;
|
||||
}
|
||||
172
baselib/src/gplx/types/basics/arrays/IntAryUtl.java
Normal file
172
baselib/src/gplx/types/basics/arrays/IntAryUtl.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
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.types.basics.arrays;
|
||||
import gplx.types.commons.lists.GfoListBase;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.basics.utls.ArrayUtl;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
public class IntAryUtl {
|
||||
public static final int[] Empty = new int[0];
|
||||
public static int[] New(int... v) {return v;}
|
||||
public static void CopyTo(int[] src, int src_len, int[] trg) {
|
||||
for (int i = 0; i < src_len; ++i)
|
||||
trg[i] = src[i];
|
||||
}
|
||||
public static int[] Mid(int[] src, int bgn, int end) {
|
||||
int len = end - bgn + 1;
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = src[i + bgn];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static String ToStr(String spr, int... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (i != 0) sb.Add(spr);
|
||||
int itm = ary[i];
|
||||
sb.Add(itm);
|
||||
}
|
||||
return sb.ToStrAndClear();
|
||||
}
|
||||
public static int[] Parse(String raw, String spr) {
|
||||
String[] ary = StringUtl.Split(raw, spr);
|
||||
int len = ary.length;
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = IntUtl.Parse(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
// parses to a reqd len; EX: "1" -> "[1, 0]"
|
||||
public static int[] Parse(String raw_str, int reqd_len, int[] or) {
|
||||
byte[] raw_bry = BryUtl.NewA7(raw_str);
|
||||
int raw_bry_len = raw_bry.length;
|
||||
int[] rv = new int[reqd_len];
|
||||
int cur_val = 0, cur_mult = 1, cur_idx = reqd_len - 1; boolean signed = false;
|
||||
for (int i = raw_bry_len - 1; i > -2; i--) {
|
||||
byte b = i == -1 ? AsciiByte.Comma : raw_bry[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
if (signed) return or;
|
||||
cur_val += (b - AsciiByte.Num0) * cur_mult;
|
||||
cur_mult *= 10;
|
||||
break;
|
||||
case AsciiByte.Space: case AsciiByte.Nl: case AsciiByte.Cr: case AsciiByte.Tab:
|
||||
break;
|
||||
case AsciiByte.Comma:
|
||||
if (cur_idx < 0) return or;
|
||||
rv[cur_idx--] = cur_val;
|
||||
cur_val = 0; cur_mult = 1;
|
||||
signed = false;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
if (signed) return or;
|
||||
cur_val *= -1;
|
||||
signed = true;
|
||||
break;
|
||||
case AsciiByte.Plus: // noop; all values positive by default
|
||||
if (signed) return or;
|
||||
signed = true;
|
||||
break;
|
||||
default:
|
||||
return or;
|
||||
}
|
||||
}
|
||||
return cur_idx == -1 ? rv : or; // cur_idx == -1 checks for unfilled; EX: Ary_parse("1,2", 3, null) is unfilled
|
||||
}
|
||||
|
||||
// optimizes parse
|
||||
public static int[] ParseOr(byte[] src, int[] or) {
|
||||
try {
|
||||
if (BryUtl.IsNullOrEmpty(src)) return or; // null, "" should return [0]
|
||||
int raw_len = src.length;
|
||||
int[] rv = null; int rv_idx = 0, rv_len = 0;
|
||||
int pos = 0;
|
||||
int num_bgn = -1, num_end = -1;
|
||||
boolean itm_done = false, itm_is_rng = false;
|
||||
int rng_bgn = IntUtl.MinValue;
|
||||
while (true) {
|
||||
boolean pos_is_last = pos == raw_len;
|
||||
if ( itm_done
|
||||
|| pos_is_last
|
||||
) {
|
||||
if (num_bgn == -1) return or; // empty itm; EX: "1,"; "1,,2"
|
||||
int num = BryUtl.ToIntOr(src, num_bgn, num_end, IntUtl.MinValue);
|
||||
if (num == IntUtl.MinValue) return or; // not a number; parse failed
|
||||
if (rv_len == 0) { // rv not init'd
|
||||
rv_len = (raw_len / 2) + 1; // default rv_len to len of String / 2; + 1 to avoid fraction rounding down
|
||||
rv = new int[rv_len];
|
||||
}
|
||||
int add_len = 1;
|
||||
if (itm_is_rng) {
|
||||
add_len = num - rng_bgn + GfoListBase.Base1;
|
||||
if (add_len == 0) return or; // bgn >= end;
|
||||
}
|
||||
if (add_len + rv_idx > rv_len) { // ary out of space; resize
|
||||
rv_len = (add_len + rv_idx) * 2;
|
||||
rv = (int[])ArrayUtl.Resize(rv, rv_len);
|
||||
}
|
||||
if (itm_is_rng) {
|
||||
for (int i = rng_bgn; i <= num; i++)
|
||||
rv[rv_idx++] = i;
|
||||
}
|
||||
else {
|
||||
rv[rv_idx++] = num;
|
||||
}
|
||||
num_bgn = num_end = -1;
|
||||
itm_done = itm_is_rng = false;
|
||||
rng_bgn = IntUtl.MinValue;
|
||||
if (pos_is_last) break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
if (num_bgn == -1) // num_bgn not set
|
||||
num_bgn = pos;
|
||||
num_end = pos + 1; // num_end is always after pos; EX: "9": num_end = 1; "98,7": num_end=2
|
||||
break;
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr: // NOTE: parseNumList replaces ws with '', so "1 1" will become "11"
|
||||
break;
|
||||
case AsciiByte.Comma:
|
||||
if (pos == raw_len -1) return or; // eos; EX: "1,"
|
||||
if (num_bgn == -1) return or; // empty itm; EX: ","; "1,,2"
|
||||
itm_done = true;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
if (pos == raw_len -1) return or; // eos; EX: "1-"
|
||||
if (num_bgn == -1) return or; // no rng_bgn; EX: "-2"
|
||||
rng_bgn = BryUtl.ToIntOr(src, num_bgn, pos, IntUtl.MinValue);
|
||||
if (rng_bgn == IntUtl.MinValue) return or;
|
||||
num_bgn = -1;
|
||||
itm_is_rng = true;
|
||||
break;
|
||||
default:
|
||||
return or;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return (rv_idx == rv_len) // on the off-chance that rv_len == rv_idx; EX: "1"
|
||||
? rv
|
||||
: (int[])ArrayUtl.Resize(rv, rv_idx);
|
||||
} catch (Exception e) {return or;}
|
||||
}
|
||||
}
|
||||
58
baselib/src/gplx/types/basics/arrays/IntAryUtlTest.java
Normal file
58
baselib/src/gplx/types/basics/arrays/IntAryUtlTest.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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.types.basics.arrays;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.frameworks.tests.GfoTstr;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import org.junit.Test;
|
||||
public class IntAryUtlTest {
|
||||
private final IntAryTstr tstr = new IntAryTstr();
|
||||
@Test public void Parse() {
|
||||
tstr.TestParse("1,2,3" , 3, IntAryUtl.Empty, 1, 2, 3);
|
||||
tstr.TestParse("123,321,213" , 3, IntAryUtl.Empty, 123, 321, 213);
|
||||
tstr.TestParse(" 1, 2,3" , 3, IntAryUtl.Empty, 1, 2, 3);
|
||||
tstr.TestParse("-1,+2,-3" , 3, IntAryUtl.Empty, -1, 2, -3);
|
||||
tstr.TestParse(IntUtl.ToStr(IntUtl.MinValue) , 1, IntAryUtl.Empty, IntUtl.MinValue);
|
||||
tstr.TestParse(IntUtl.ToStr(IntUtl.MaxValue) , 1, IntAryUtl.Empty, IntUtl.MaxValue);
|
||||
tstr.TestParse("1,2" , 1, IntAryUtl.Empty);
|
||||
tstr.TestParse("1" , 2, IntAryUtl.Empty);
|
||||
tstr.TestParse("a" , 1, IntAryUtl.Empty);
|
||||
tstr.TestParse("1-2," , 1, IntAryUtl.Empty);
|
||||
}
|
||||
@Test public void ParseOr() {
|
||||
tstr.TestParseOr("1", 1);
|
||||
tstr.TestParseOr("123", 123);
|
||||
tstr.TestParseOr("1,2,123", 1, 2, 123);
|
||||
tstr.TestParseOr("1,2,12,123", 1, 2, 12, 123);
|
||||
tstr.TestParseOr("1-5", 1, 2, 3, 4, 5);
|
||||
tstr.TestParseOr("1-1", 1);
|
||||
tstr.TestParseOr("1-3,7,11-13,21", 1, 2, 3, 7, 11, 12, 13, 21);
|
||||
|
||||
tstr.TestParseOrEmpty("1 2"); // NOTE: MW would gen 12; treat as invalid
|
||||
tstr.TestParseOrEmpty("1,"); // eos
|
||||
tstr.TestParseOrEmpty("1,,2"); // empty comma
|
||||
tstr.TestParseOrEmpty("1-"); // eos
|
||||
tstr.TestParseOrEmpty("3-1"); // bgn > end
|
||||
tstr.TestParseOrEmpty("1,a,2");
|
||||
tstr.TestParseOrEmpty("a-1,2");
|
||||
tstr.TestParseOrEmpty("-1"); // no rng bgn
|
||||
}
|
||||
}
|
||||
class IntAryTstr {
|
||||
public void TestParse(String raw, int reqd_len, int[] or, int... expd) {GfoTstr.EqAry(expd, IntAryUtl.Parse(raw, reqd_len, or), "failed to parse: {0}", raw);}
|
||||
public void TestParseOrEmpty(String raw) {GfoTstr.EqAry(IntAryUtl.Empty, IntAryUtl.ParseOr(BryUtl.NewA7(raw), IntAryUtl.Empty));}
|
||||
public void TestParseOr(String raw, int... expd) {GfoTstr.EqAry(expd , IntAryUtl.ParseOr(BryUtl.NewA7(raw), IntAryUtl.Empty));}
|
||||
}
|
||||
@@ -13,19 +13,15 @@ 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;
|
||||
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 ErrUtl.NewFmt(e, "failed to cast to long; obj={0}", ObjectUtl.ToStr(o));
|
||||
}
|
||||
package gplx.types.basics.arrays;
|
||||
public class ObjAry {
|
||||
private ObjAry(Object[] ary) {
|
||||
this.ary = ary;
|
||||
}
|
||||
public static String ToStr(long v) {return new Long(v).toString();}
|
||||
public Object[] Ary() {return ary;} private final Object[] ary;
|
||||
public Object GetAt(int i) {return ary[i];}
|
||||
public Object GetAt0() {return ary[0];}
|
||||
public Object GetAt1() {return ary[1];}
|
||||
public static ObjAry New(Object... ary) {return new ObjAry(ary);}
|
||||
public static ObjAry NewPair(Object val0, Object val1) {return new ObjAry(new Object[] {val0, val1});}
|
||||
}
|
||||
@@ -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.strings;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
package gplx.types.basics.constants;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class AsciiByte {
|
||||
public static final byte
|
||||
Null = 0 , Backfeed = 8, Tab = 9,
|
||||
@@ -13,7 +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;
|
||||
package gplx.types.basics.constants;
|
||||
public class CharCode {
|
||||
public static final char
|
||||
NewLine = '\n',
|
||||
159
baselib/src/gplx/types/basics/encoders/HexUtl.java
Normal file
159
baselib/src/gplx/types/basics/encoders/HexUtl.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
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.types.basics.encoders;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class HexUtl {
|
||||
public static int ParseOr(byte[] src, int or) {return ParseOr(src, 0, src.length, or);}
|
||||
public static int ParseOr(byte[] src, int bgn, int end, int or) {
|
||||
int rv = 0; int factor = 1;
|
||||
byte b;
|
||||
for (int i = end - 1; i >= bgn; i--) {
|
||||
switch (src[i]) {
|
||||
case AsciiByte.Num0: b = 0; break; case AsciiByte.Num1: b = 1; break; case AsciiByte.Num2: b = 2; break; case AsciiByte.Num3: b = 3; break; case AsciiByte.Num4: b = 4; break;
|
||||
case AsciiByte.Num5: b = 5; break; case AsciiByte.Num6: b = 6; break; case AsciiByte.Num7: b = 7; break; case AsciiByte.Num8: b = 8; break; case AsciiByte.Num9: b = 9; break;
|
||||
case AsciiByte.Ltr_A: b = 10; break; case AsciiByte.Ltr_B: b = 11; break; case AsciiByte.Ltr_C: b = 12; break; case AsciiByte.Ltr_D: b = 13; break; case AsciiByte.Ltr_E: b = 14; break; case AsciiByte.Ltr_F: b = 15; break;
|
||||
case AsciiByte.Ltr_a: b = 10; break; case AsciiByte.Ltr_b: b = 11; break; case AsciiByte.Ltr_c: b = 12; break; case AsciiByte.Ltr_d: b = 13; break; case AsciiByte.Ltr_e: b = 14; break; case AsciiByte.Ltr_f: b = 15; break;
|
||||
default: b = ByteUtl.MaxValue127; break;
|
||||
}
|
||||
if (b == ByteUtl.MaxValue127) return or;
|
||||
rv += b * factor;
|
||||
factor *= 16;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int Parse(String src) {
|
||||
int rv = ParseOr(src, -1); if (rv == -1) throw ErrUtl.NewParse("hexstring","src");
|
||||
return rv;
|
||||
}
|
||||
public static int ParseOr(String src, int or) {
|
||||
int rv = 0; int digit = 0, factor = 1, len = StringUtl.Len(src);
|
||||
for (int i = len - 1; i > -1; --i) {
|
||||
digit = ToInt(StringUtl.CharAt(src, i));
|
||||
if (digit == -1) return or;
|
||||
rv += digit * factor;
|
||||
factor *= 16;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] ParseHexToBry(String src) {return ParseHexToBry(BryUtl.NewU8(src));}
|
||||
public static byte[] ParseHexToBry(byte[] src) {
|
||||
int src_len = src.length;
|
||||
if ((src_len % 2) != 0) throw ErrUtl.NewArgs("hex_utl: hex_string must have an even length; src=~{0}", src);
|
||||
int ary_len = src_len / 2;
|
||||
byte[] rv = new byte[ary_len];
|
||||
int rv_idx = 0;
|
||||
|
||||
for (int i = 0; i < src_len; i += 2) {
|
||||
int val = ParseOr(src, i, i + 2, -1);
|
||||
if (val == -1) throw ErrUtl.NewArgs("hex_utl: hex_string has invalid char; src=~{0}", src);
|
||||
rv[rv_idx] = (byte)val;
|
||||
rv_idx++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] EncodeBry(byte[] src) {
|
||||
int src_len = src.length;
|
||||
byte[] trg = new byte[src_len * 2];
|
||||
EncodeBry(src, trg);
|
||||
return trg;
|
||||
}
|
||||
public static void EncodeBry(byte[] src, byte[] trg) {
|
||||
int src_len = src.length, trg_len = trg.length;
|
||||
if (trg_len != src_len * 2) throw ErrUtl.NewArgs("hex", "trg.len must be src.len * 2", "src_len", src_len, "trg_len", trg_len);
|
||||
int trg_idx = -1;
|
||||
for (int src_idx = 0; src_idx < src_len; ++src_idx) {
|
||||
byte src_byte = src[src_idx];
|
||||
trg[++trg_idx] = ToByteLcase(0xf & src_byte >>> 4);
|
||||
trg[++trg_idx] = ToByteLcase(0xf & src_byte);
|
||||
}
|
||||
}
|
||||
public static String ToStr(int val, int pad) {
|
||||
char[] ary = new char[8]; int idx = 8; // 8 is max len of hexString; (2^4 * 8); EX: int.MaxValue = 7FFFFFFF
|
||||
do {
|
||||
int byt = val % 16;
|
||||
ary[--idx] = ToChar(byt);
|
||||
val /= 16;
|
||||
} while (val > 0);
|
||||
while (8 - idx < pad) // pad left with zeros
|
||||
ary[--idx] = '0';
|
||||
return StringUtl.NewCharAry(ary, idx, 8-idx);
|
||||
}
|
||||
public static void Write(byte[] bry, int bgn, int end, int val) {
|
||||
for (int i = end - 1; i > bgn - 1; i--) {
|
||||
int b = val % 16;
|
||||
bry[i] = ToByteUcase(b);
|
||||
val /= 16;
|
||||
if (val == 0) break;
|
||||
}
|
||||
}
|
||||
public static boolean IsHexMany(byte... ary) {
|
||||
for (byte itm : ary) {
|
||||
if (!IsHex(itm))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean IsHex(byte itm) {
|
||||
switch (itm) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
case AsciiByte.Ltr_A: case AsciiByte.Ltr_B: case AsciiByte.Ltr_C: case AsciiByte.Ltr_D: case AsciiByte.Ltr_E: case AsciiByte.Ltr_F:
|
||||
case AsciiByte.Ltr_a: case AsciiByte.Ltr_b: case AsciiByte.Ltr_c: case AsciiByte.Ltr_d: case AsciiByte.Ltr_e: case AsciiByte.Ltr_f:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static int ToInt(char c) {
|
||||
switch (c) {
|
||||
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
|
||||
case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
|
||||
case 'A': return 10; case 'B': return 11; case 'C': return 12; case 'D': return 13; case 'E': return 14; case 'F': return 15;
|
||||
case 'a': return 10; case 'b': return 11; case 'c': return 12; case 'd': return 13; case 'e': return 14; case 'f': return 15;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
private static char ToChar(int val) {
|
||||
switch (val) {
|
||||
case 0: return '0'; case 1: return '1'; case 2: return '2'; case 3: return '3'; case 4: return '4';
|
||||
case 5: return '5'; case 6: return '6'; case 7: return '7'; case 8: return '8'; case 9: return '9';
|
||||
case 10: return 'A'; case 11: return 'B'; case 12: return 'C'; case 13: return 'D'; case 14: return 'E'; case 15: return 'F';
|
||||
default: throw ErrUtl.NewParse("hexstring", IntUtl.ToStr(val));
|
||||
}
|
||||
}
|
||||
protected static byte ToByteUcase(int v) {
|
||||
switch (v) {
|
||||
case 0: return AsciiByte.Num0; case 1: return AsciiByte.Num1; case 2: return AsciiByte.Num2; case 3: return AsciiByte.Num3; case 4: return AsciiByte.Num4;
|
||||
case 5: return AsciiByte.Num5; case 6: return AsciiByte.Num6; case 7: return AsciiByte.Num7; case 8: return AsciiByte.Num8; case 9: return AsciiByte.Num9;
|
||||
case 10: return AsciiByte.Ltr_A; case 11: return AsciiByte.Ltr_B; case 12: return AsciiByte.Ltr_C; case 13: return AsciiByte.Ltr_D; case 14: return AsciiByte.Ltr_E; case 15: return AsciiByte.Ltr_F;
|
||||
default: throw ErrUtl.NewParse("hexstring", IntUtl.ToStr(v));
|
||||
}
|
||||
}
|
||||
protected static byte ToByteLcase(int v) {
|
||||
switch (v) {
|
||||
case 0: return AsciiByte.Num0; case 1: return AsciiByte.Num1; case 2: return AsciiByte.Num2; case 3: return AsciiByte.Num3;
|
||||
case 4: return AsciiByte.Num4; case 5: return AsciiByte.Num5; case 6: return AsciiByte.Num6; case 7: return AsciiByte.Num7;
|
||||
case 8: return AsciiByte.Num8; case 9: return AsciiByte.Num9; case 10: return AsciiByte.Ltr_a; case 11: return AsciiByte.Ltr_b;
|
||||
case 12: return AsciiByte.Ltr_c; case 13: return AsciiByte.Ltr_d; case 14: return AsciiByte.Ltr_e; case 15: return AsciiByte.Ltr_f;
|
||||
default: throw ErrUtl.NewParse("hexstring", IntUtl.ToStr(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
76
baselib/src/gplx/types/basics/encoders/HexUtlTest.java
Normal file
76
baselib/src/gplx/types/basics/encoders/HexUtlTest.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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.types.basics.encoders;
|
||||
import gplx.frameworks.tests.GfoTstr;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import org.junit.Test;
|
||||
public class HexUtlTest {
|
||||
private final HexUtlTstr tstr = new HexUtlTstr();
|
||||
@Test public void To_int() {
|
||||
tstr.TestParse("0" , 0);
|
||||
tstr.TestParse("F" , 15);
|
||||
tstr.TestParse("0F" , 15);
|
||||
tstr.TestParse("10" , 16);
|
||||
tstr.TestParse("20" , 32);
|
||||
tstr.TestParse("FF" , 255);
|
||||
tstr.TestParse("100" , 256);
|
||||
tstr.TestParse("0a" , 10);
|
||||
tstr.TestParse("7FFFFFFF" , IntUtl.MaxValue);
|
||||
tstr.TestParseOr("100" , 256);
|
||||
}
|
||||
@Test public void To_str() {
|
||||
tstr.TestToStr(0 , "0");
|
||||
tstr.TestToStr(15 , "F");
|
||||
tstr.TestToStr(16 , "10");
|
||||
tstr.TestToStr(32 , "20");
|
||||
tstr.TestToStr(255 , "FF");
|
||||
tstr.TestToStr(IntUtl.MaxValue, "7FFFFFFF");
|
||||
|
||||
tstr.TestToStr(15, 2 , "0F");
|
||||
tstr.TestToStr(15, 3 , "00F");
|
||||
}
|
||||
@Test public void Write() {
|
||||
tstr.TestWrite("[00000000]", 1, 9, 15, "[0000000F]");
|
||||
tstr.TestWrite("[00000000]", 1, 9, 255, "[000000FF]");
|
||||
}
|
||||
@Test public void Encode() {
|
||||
tstr.TestParseHexToBry("E2A7BC", 226, 167, 188);
|
||||
}
|
||||
}
|
||||
class HexUtlTstr {
|
||||
public void TestWrite(String s, int bgn, int end, int val, String expd) {
|
||||
byte[] bry = BryUtl.NewA7(s);
|
||||
HexUtl.Write(bry, bgn, end, val);
|
||||
GfoTstr.Eq(expd, StringUtl.NewA7(bry));
|
||||
}
|
||||
public void TestParse(String raw, int expd) {
|
||||
int actl = HexUtl.Parse(raw);
|
||||
GfoTstr.Eq(expd, actl);
|
||||
}
|
||||
public void TestParseOr(String raw, int expd) {GfoTstr.Eq(expd, HexUtl.ParseOr(BryUtl.NewA7(raw), -1));}
|
||||
public void TestToStr(int val, String expd) {TestToStr(val, 0, expd);}
|
||||
public void TestToStr(int val, int pad, String expd) {
|
||||
String actl = HexUtl.ToStr(val, pad);
|
||||
GfoTstr.Eq(expd, actl);
|
||||
}
|
||||
public void TestParseHexToBry(String val, int... expd) {
|
||||
byte[] actl = HexUtl.ParseHexToBry(BryUtl.NewU8(val));
|
||||
GfoTstr.EqAry(ByteUtl.AryByInts(expd), actl, "encode");
|
||||
}
|
||||
}
|
||||
106
baselib/src/gplx/types/basics/strings/bfrs/GfoStringBldr.java
Normal file
106
baselib/src/gplx/types/basics/strings/bfrs/GfoStringBldr.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
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.types.basics.strings.bfrs;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.constants.CharCode;
|
||||
import gplx.types.basics.strings.unicodes.Utf16Utl;
|
||||
import gplx.types.basics.utls.BoolUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
public class GfoStringBldr extends StringBuilderLni {
|
||||
public boolean HasNone() {return this.Len() == 0;}
|
||||
public boolean HasSome() {return this.Len() > 0;}
|
||||
public GfoStringBldr Clear() {LniDel(0, this.Len()); return this;}
|
||||
public GfoStringBldr AddFmt(String format, Object... args) {LniAdd(StringUtl.Format(format, args)); return this;}
|
||||
public GfoStringBldr Add(byte[] v) {
|
||||
if (v != null)
|
||||
this.LniAdd(StringUtl.NewU8(v));
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddChar(char v) {this.LniAddChar(v); return this;}
|
||||
public GfoStringBldr AddByte(byte v) {this.LniAddByte(v); return this;}
|
||||
public GfoStringBldr Add(int v) {this.LniAdd(v); return this;}
|
||||
public GfoStringBldr Add(String v) {this.LniAdd(v); return this;}
|
||||
public GfoStringBldr AddLong(long v) {this.LniAddLong(v); return this;}
|
||||
public GfoStringBldr AddObj(Object v) {this.LniAddObj(v); return this;}
|
||||
public GfoStringBldr AddMid(String v, int bgn) {this.LniAddMid(v, bgn, v.length()); return this;}
|
||||
public GfoStringBldr AddMid(String v, int bgn, int len) {this.LniAddMid(v, bgn, len); return this;}
|
||||
public GfoStringBldr AddBool(boolean val) {
|
||||
this.LniAdd(val ? BoolUtl.TrueStr : BoolUtl.FalseStr);
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddBoolAsYn(boolean val) {
|
||||
this.LniAdd(val ? "y" : "n");
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddCharNl() {return AddChar(CharCode.NewLine);}
|
||||
public GfoStringBldr AddCharSpace() {return AddChar(CharCode.Space);}
|
||||
public GfoStringBldr AddCharColon() {return AddChar(CharCode.Colon);}
|
||||
public GfoStringBldr AddCharRepeat(char c, int repeat) {
|
||||
this.LniEnsureCapacity(this.Len() + repeat);
|
||||
for (int i = 0; i < repeat; i++)
|
||||
AddChar(c);
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddByteRepeat(byte c, int repeat) {
|
||||
this.LniEnsureCapacity(this.Len() + repeat);
|
||||
for (int i = 0; i < repeat; i++)
|
||||
AddByte(c);
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddCharByCode(int code) {
|
||||
if (code >= Utf16Utl.SurrogateCpBgn && code <= Utf16Utl.SurrogateCpEnd) {
|
||||
this.LniAddChar((char)((code - 0x10000) / 0x400 + 0xD800));
|
||||
this.LniAddChar((char)((code - 0x10000) % 0x400 + 0xDC00));
|
||||
}
|
||||
else {
|
||||
this.LniAddChar((char)code);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr 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);
|
||||
Add(val);
|
||||
return this;
|
||||
}
|
||||
public GfoStringBldr AddIntFixed(int val, int digits) {return AddIntPad(val, IntUtl.Log10(val), digits);}
|
||||
public GfoStringBldr AddIntPad(int val, int valLog, int arySlots) {
|
||||
if (val < 0) {
|
||||
AddCharByCode(AsciiByte.Dash);
|
||||
val *= -1; // make positive
|
||||
valLog *= -1; // valLog will be negative; make positive
|
||||
arySlots -= 1; // reduce slot by 1
|
||||
}
|
||||
if (valLog >= arySlots) {
|
||||
val %= IntUtl.Log10Vals[arySlots];
|
||||
}
|
||||
for (int i = 0; i < arySlots; i++) {
|
||||
int logIdx = arySlots - i - 1;
|
||||
int div = logIdx < IntUtl.Log10ValsLen ? IntUtl.Log10Vals[logIdx] : IntUtl.MaxValue;
|
||||
AddCharByCode((byte)((val / div) + 48));
|
||||
val %= div;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public String ToStrAndClear() {
|
||||
String rv = ToStr();
|
||||
Clear();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package gplx.types.basics.strings.bfrs;
|
||||
import java.lang.StringBuilder;
|
||||
public class StringBuilderLni {
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
public final int Len() {return sb.length();}
|
||||
protected final void LniDel(int bgn, int len) {sb.delete(bgn, len);}
|
||||
protected final void LniAddByte(byte i) {sb.append(i);}
|
||||
public final void LniAddChar(char c) {sb.append(c);}
|
||||
protected final void LniAdd(int i) {sb.append(i);}
|
||||
protected final void LniAddLong(long i) {sb.append(i);}
|
||||
public final void LniAdd(String s) {sb.append(s);}
|
||||
protected final void LniAddObj(Object o) {sb.append(o);}
|
||||
protected final void LniAddMid(String s, int bgn, int len) {sb.append(s, bgn, len);}
|
||||
protected final void LniEnsureCapacity(int capacity) {sb.ensureCapacity(capacity);}
|
||||
public final String ToStr() {return sb.toString();}
|
||||
@Override public final String toString() {return sb.toString();}
|
||||
}
|
||||
@@ -13,7 +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.strings.charSources;
|
||||
package gplx.types.basics.strings.charSources;
|
||||
public interface CharSource {
|
||||
String Src();
|
||||
int GetData(int pos);
|
||||
@@ -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.strings.charSources;
|
||||
import gplx.objects.strings.StringUtl;
|
||||
package gplx.types.basics.strings.charSources;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
public class CharSourceUtl {
|
||||
public static int IndexOfAny(String src, char[] ary) {
|
||||
int srcLen = StringUtl.Len(src);
|
||||
@@ -13,10 +13,10 @@ 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;
|
||||
package gplx.types.basics.strings.unicodes;
|
||||
import gplx.types.basics.strings.charSources.CharSource;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public interface Ustring extends CharSource {
|
||||
int LenInChars();
|
||||
int MapDataToChar(int pos);
|
||||
@@ -65,11 +65,11 @@ class UstringCodepoints implements Ustring {
|
||||
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
|
||||
if (c >= Utf16Utl.SurrogateHiBgn && c <= Utf16Utl.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);
|
||||
codes[codeIdx++] = Utf16Utl.SurrogateCpBgn + (c - Utf16Utl.SurrogateHiBgn) * Utf16Utl.SurrogateRange + (c2 - Utf16Utl.SurrogateLoBgn);
|
||||
}
|
||||
else {
|
||||
codes[codeIdx++] = c;
|
||||
@@ -81,13 +81,13 @@ class UstringCodepoints implements Ustring {
|
||||
int len = 0;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
int code = codes[i];
|
||||
len += code >= UstringUtl.SurrogateCpBgn && code <= UstringUtl.SurrogateCpEnd ? 2 : 1;
|
||||
len += code >= Utf16Utl.SurrogateCpBgn && code <= Utf16Utl.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) {
|
||||
if (code >= Utf16Utl.SurrogateCpBgn && code <= Utf16Utl.SurrogateCpEnd) {
|
||||
rv[rvIdx++] = (char)((code - 0x10000) / 0x400 + 0xD800);
|
||||
rv[rvIdx++] = (char)((code - 0x10000) % 0x400 + 0xDC00);
|
||||
}
|
||||
@@ -143,7 +143,7 @@ class UstringCodepoints implements Ustring {
|
||||
// sum all items before requested pos
|
||||
int rv = 0;
|
||||
for (int i = 0; i < codePos; i++) {
|
||||
rv += codes[i] < UstringUtl.SurrogateCpBgn ? 1 : 2;
|
||||
rv += codes[i] < Utf16Utl.SurrogateCpBgn ? 1 : 2;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class UstringCodepoints implements Ustring {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < charPos; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= UstringUtl.SurrogateHiBgn && c <= UstringUtl.SurrogateHiEnd){ // SurrogateHi
|
||||
if (c >= Utf16Utl.SurrogateHiBgn && c <= Utf16Utl.SurrogateHiEnd){ // SurrogateHi
|
||||
if (i == charPos - 1) // charPos is SurrogateLo; return -1 since SurrogateLo doesn't map to a codePos
|
||||
return -1;
|
||||
}
|
||||
@@ -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.strings.unicodes;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
package gplx.types.basics.strings.unicodes;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class UstringUtl {
|
||||
public static Ustring NewCodepoints(String src) {
|
||||
if (src == null) throw ErrUtl.NewNull("src");
|
||||
@@ -31,7 +31,7 @@ public class UstringUtl {
|
||||
int rv = 0;
|
||||
for (int i = 0; i < srcLen; i++) {
|
||||
char c = src.charAt(i);
|
||||
if (c >= SurrogateHiBgn && c <= SurrogateHiEnd) {
|
||||
if (c >= Utf16Utl.SurrogateHiBgn && c <= Utf16Utl.SurrogateHiEnd) {
|
||||
i++;
|
||||
}
|
||||
rv++;
|
||||
@@ -39,12 +39,4 @@ public class UstringUtl {
|
||||
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
|
||||
}
|
||||
139
baselib/src/gplx/types/basics/strings/unicodes/Utf16Utl.java
Normal file
139
baselib/src/gplx/types/basics/strings/unicodes/Utf16Utl.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
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.types.basics.strings.unicodes;
|
||||
import gplx.types.basics.wrappers.IntRef;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class Utf16Utl {
|
||||
public static int SurrogateMerge(int hi, int lo) { // REF: http://perldoc.perl.org/Encode/Unicode.html
|
||||
return 0x10000 + (hi - 0xD800) * 0x400 + (lo - 0xDC00);
|
||||
}
|
||||
public static void SurrogateSplit(int v, IntRef hi, IntRef lo) {
|
||||
hi.ValSet((v - 0x10000) / 0x400 + 0xD800);
|
||||
lo.ValSet((v - 0x10000) % 0x400 + 0xDC00);
|
||||
}
|
||||
public static int DecodeToInt(byte[] ary, int pos) {
|
||||
byte b0 = ary[pos];
|
||||
if ((b0 & 0x80) == 0) {
|
||||
return b0;
|
||||
}
|
||||
else if ((b0 & 0xE0) == 0xC0) {
|
||||
return ( b0 & 0x1f) << 6
|
||||
| ( ary[pos + 1] & 0x3f)
|
||||
;
|
||||
}
|
||||
else if ((b0 & 0xF0) == 0xE0) {
|
||||
return ( b0 & 0x0f) << 12
|
||||
| ((ary[pos + 1] & 0x3f) << 6)
|
||||
| ( ary[pos + 2] & 0x3f)
|
||||
;
|
||||
}
|
||||
else if ((b0 & 0xF8) == 0xF0) {
|
||||
return ( b0 & 0x07) << 18
|
||||
| ((ary[pos + 1] & 0x3f) << 12)
|
||||
| ((ary[pos + 2] & 0x3f) << 6)
|
||||
| ( ary[pos + 3] & 0x3f)
|
||||
;
|
||||
}
|
||||
else
|
||||
throw ErrUtl.NewArgs("invalid utf8 byte", "byte", b0);
|
||||
}
|
||||
public static byte[] EncodeIntToBry(int c) {
|
||||
int bry_len = LenByInt(c);
|
||||
byte[] bry = new byte[bry_len];
|
||||
EncodeInt(c, bry, 0);
|
||||
return bry;
|
||||
}
|
||||
public static int EncodeChar(int c, char[] c_ary, int c_pos, byte[] b_ary, int b_pos) {
|
||||
if ((c > -1)
|
||||
&& (c < 128)) {
|
||||
b_ary[ b_pos] = (byte)c;
|
||||
return 1;
|
||||
}
|
||||
else if (c < 2048) {
|
||||
b_ary[ b_pos] = (byte)(0xC0 | (c >> 6));
|
||||
b_ary[++b_pos] = (byte)(0x80 | (c & 0x3F));
|
||||
return 1;
|
||||
}
|
||||
else if((c > 55295) // 0xD800
|
||||
&& (c < 56320)) { // 0xDFFF
|
||||
if (c_pos >= c_ary.length) throw ErrUtl.NewArgs("incomplete surrogate pair at end of String", "char", c);
|
||||
char nxt_char = c_ary[c_pos + 1];
|
||||
int v = SurrogateMerge(c, nxt_char);
|
||||
b_ary[b_pos] = (byte)(0xF0 | (v >> 18));
|
||||
b_ary[++b_pos] = (byte)(0x80 | (v >> 12) & 0x3F);
|
||||
b_ary[++b_pos] = (byte)(0x80 | (v >> 6) & 0x3F);
|
||||
b_ary[++b_pos] = (byte)(0x80 | (v & 0x3F));
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
b_ary[b_pos] = (byte)(0xE0 | (c >> 12));
|
||||
b_ary[++b_pos] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
b_ary[++b_pos] = (byte)(0x80 | (c & 0x3F));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
public static int EncodeInt(int c, byte[] src, int pos) {
|
||||
if ((c > -1)
|
||||
&& (c < 128)) {
|
||||
src[ pos] = (byte)c;
|
||||
return 1;
|
||||
}
|
||||
else if (c < 2048) {
|
||||
src[ pos] = (byte)(0xC0 | (c >> 6));
|
||||
src[++pos] = (byte)(0x80 | (c & 0x3F));
|
||||
return 2;
|
||||
}
|
||||
else if (c < 65536) {
|
||||
src[pos] = (byte)(0xE0 | (c >> 12));
|
||||
src[++pos] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
src[++pos] = (byte)(0x80 | (c & 0x3F));
|
||||
return 3;
|
||||
}
|
||||
else if (c < 2097152) {
|
||||
src[pos] = (byte)(0xF0 | (c >> 18));
|
||||
src[++pos] = (byte)(0x80 | (c >> 12) & 0x3F);
|
||||
src[++pos] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
src[++pos] = (byte)(0x80 | (c & 0x3F));
|
||||
return 4;
|
||||
}
|
||||
else throw ErrUtl.NewArgs("UTF-16 int must be between 0 and 2097152", "char", c);
|
||||
}
|
||||
private static int LenByInt(int c) {
|
||||
if ((c > -1)
|
||||
&& (c < 128)) return 1; // 1 << 7
|
||||
else if (c < 2048) return 2; // 1 << 11
|
||||
else if (c < 65536) return 3; // 1 << 16
|
||||
else if (c < 2097152) return 4;
|
||||
else throw ErrUtl.NewArgs("UTF-16 int must be between 0 and 2097152", "char", c);
|
||||
}
|
||||
public static int LenByChar(int c) {
|
||||
if ((c > -1)
|
||||
&& (c < 128)) return 1; // 1 << 7
|
||||
else if (c < 2048) return 2; // 1 << 11
|
||||
else if ((c > 55295) // 0xD800
|
||||
&& (c < 56320)) return 4; // 0xDFFF
|
||||
else if (c < 65536) return 3; // 1 << 16
|
||||
else throw ErrUtl.NewArgs("UTF-16 int must be between 0 and 65536", "char", c);
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
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.types.basics.strings.unicodes;
|
||||
import gplx.frameworks.tests.GfoTstr;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.wrappers.IntRef;
|
||||
import org.junit.Test;
|
||||
public class Utf16UtlTest {
|
||||
private Utf16UtlTstr tstr = new Utf16UtlTstr();
|
||||
@Test public void EncodeDecode() {
|
||||
tstr.TestEncodeDecode(162, 194, 162); // cent; ¢
|
||||
tstr.TestEncodeDecode(8364, 226, 130, 172); // euro; €
|
||||
tstr.TestEncodeDecode(150370, 240, 164, 173, 162); // example from [[UTF-8]]; should be encoded as two bytes; 𤭢
|
||||
tstr.TestEncodeDecode(143489, 240, 163, 130, 129); // EX: 駣𣂁脁 DATE:2017-04-22; 𣂁
|
||||
}
|
||||
@Test public void Surrogate() {
|
||||
tstr.TestSurrogate(0x64321, 0xD950, 0xDF21); // example from w:UTF-16
|
||||
tstr.TestSurrogate(66643, 55297, 56403); // example from d:Boomerang
|
||||
}
|
||||
}
|
||||
class Utf16UtlTstr {
|
||||
private IntRef hiRef = IntRef.NewNeg1(), loRef = IntRef.NewNeg1();
|
||||
public void TestEncodeDecode(int expd_c_int, int... expd_int) {
|
||||
byte[] expd = BryUtl.NewByInts(expd_int);
|
||||
byte[] bfr = new byte[10];
|
||||
int bfr_len = Utf16Utl.EncodeInt(expd_c_int, bfr, 0);
|
||||
byte[] actl = BryUtl.MidByLen(bfr, 0, bfr_len);
|
||||
GfoTstr.Eq(expd, actl);
|
||||
int actl_c_int = Utf16Utl.DecodeToInt(bfr, 0);
|
||||
GfoTstr.Eq(expd_c_int, actl_c_int);
|
||||
}
|
||||
public void TestSurrogate(int v, int hi, int lo) {
|
||||
GfoTstr.Eq(v, Utf16Utl.SurrogateMerge((char)hi, (char)lo));
|
||||
Utf16Utl.SurrogateSplit(v, hiRef, loRef);
|
||||
GfoTstr.Eq(hi, hiRef.Val());
|
||||
GfoTstr.Eq(lo, loRef.Val());
|
||||
}
|
||||
}
|
||||
192
baselib/src/gplx/types/basics/strings/unicodes/Utf8Utl.java
Normal file
192
baselib/src/gplx/types/basics/strings/unicodes/Utf8Utl.java
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
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.types.basics.strings.unicodes;
|
||||
import gplx.types.basics.utls.BryLni;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
public class Utf8Utl {
|
||||
public static int LenOfBry(byte[] ary) {
|
||||
if (ary == null) return 0;
|
||||
int rv = 0;
|
||||
int pos = 0, len = ary.length;
|
||||
while (pos < len) {
|
||||
int char_len = LenOfCharBy1stByte(ary[pos]);
|
||||
++rv;
|
||||
pos += char_len;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int LenOfCharBy1stByte(byte b) {// SEE:w:UTF-8
|
||||
int i = b & 0xff; // PATCH.JAVA:need to convert to unsigned byte
|
||||
switch (i) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
|
||||
case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31:
|
||||
case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
|
||||
case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63:
|
||||
case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79:
|
||||
case 80: case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88: case 89: case 90: case 91: case 92: case 93: case 94: case 95:
|
||||
case 96: case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107: case 108: case 109: case 110: case 111:
|
||||
case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127:
|
||||
case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143:
|
||||
case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159:
|
||||
case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175:
|
||||
case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191:
|
||||
return 1;
|
||||
case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207:
|
||||
case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223:
|
||||
return 2;
|
||||
case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239:
|
||||
return 3;
|
||||
case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247:
|
||||
return 4;
|
||||
default: throw ErrUtl.NewArgs("invalid initial utf8 byte", "byte", b);
|
||||
}
|
||||
}
|
||||
public static byte[] GetCharAtPosAsBry(byte[] bry, int pos) {
|
||||
int len = LenOfCharBy1stByte(bry[pos]);
|
||||
return BryLni.Mid(bry, pos, pos + len);
|
||||
}
|
||||
public static byte[] IncrementCharAtLastPos(byte[] bry) { // EX: abc -> abd; complexity is for multi-byte chars
|
||||
int bry_len = bry.length; if (bry_len == 0) return bry;
|
||||
int pos = bry_len - 1;
|
||||
while (true) { // loop bwds
|
||||
int cur_char_pos0 = GetPrvCharPos0Old(bry, pos); // get byte0 of char
|
||||
int cur_char_len = (pos - cur_char_pos0) + 1; // calc len of char
|
||||
int nxt_char = Codepoint_max;
|
||||
if (cur_char_len == 1) { // len=1; just change 1 byte
|
||||
nxt_char = IncrementChar(bry[cur_char_pos0]); // get next char
|
||||
if (nxt_char < 128) { // single-byte char; just change pos
|
||||
bry = BryUtl.Copy(bry); // always return new bry; never reuse existing
|
||||
bry[cur_char_pos0] = (byte)nxt_char;
|
||||
return bry;
|
||||
}
|
||||
}
|
||||
int cur_char = Utf16Utl.DecodeToInt(bry, cur_char_pos0);
|
||||
nxt_char = IncrementChar(cur_char);
|
||||
if (nxt_char != IntUtl.MinValue) {
|
||||
byte[] nxt_char_as_bry = Utf16Utl.EncodeIntToBry(nxt_char);
|
||||
bry = BryUtl.Add(BryLni.Mid(bry, 0, cur_char_pos0), nxt_char_as_bry);
|
||||
return bry;
|
||||
}
|
||||
pos = cur_char_pos0 - 1;
|
||||
if (pos < 0) return null;
|
||||
}
|
||||
}
|
||||
public static int GetPrvCharPos0Old(byte[] bry, int pos) { // find pos0 of char while moving bwd through bry; see test
|
||||
int stop = pos - 4; // UTF8 char has max of 4 bytes
|
||||
if (stop < 0) stop = 0; // if at pos 0 - 3, stop at 0
|
||||
for (int i = pos - 1; i >= stop; i--) { // start at pos - 1, and move bwd; NOTE: pos - 1 to skip pos, b/c pos will never definitively yield any char_len info
|
||||
byte b = bry[i];
|
||||
int char_len = LenOfCharBy1stByte(b);
|
||||
switch (char_len) { // if char_len is multi-byte and pos is at correct multi-byte pos (pos - i = # of bytes - 1), then pos0 found; EX: € = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct pos for 3 byte char -> return
|
||||
case 2: if (pos - i == 1) return i; break;
|
||||
case 3: if (pos - i == 2) return i; break;
|
||||
case 4: if (pos - i == 3) return i; break;
|
||||
}
|
||||
}
|
||||
return pos; // no mult-byte char found; return pos
|
||||
}
|
||||
public static int GetPrvCharPos0(byte[] src, int cur) { // find pos0 of char while moving bwd through src; see test
|
||||
// do bounds checks
|
||||
if (cur == 0) return -1;
|
||||
if (cur <= -1 || cur > src.length) throw ErrUtl.NewArgs("invalid index for get_prv_char_pos0", "src", src, "cur", cur);
|
||||
|
||||
// start at cur - 1; note bounds checks above
|
||||
int pos = cur - 1;
|
||||
|
||||
// get 1st byte and check if ASCII for (a) error-checking (ASCII can only be in 1st byte); (b) performance
|
||||
byte b = src[pos];
|
||||
if (b >= 0 && b <= ByteUtl.MaxValue127) return pos;
|
||||
|
||||
// loop maximum of 4 times; note that UTF8 char has max of 4 bytes
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int char_len = LenOfCharBy1stByte(b);
|
||||
switch (char_len) { // if char_len is multi-byte and cur is at correct multi-byte pos (cur - i = # of bytes - 1), then pos0 found; EX: € = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct cur for 3 byte char -> return
|
||||
case 2: if (i == 1) return pos; break;
|
||||
case 3: if (i == 2) return pos; break;
|
||||
case 4: if (i == 3) return pos; break;
|
||||
}
|
||||
|
||||
// decrement and set byte
|
||||
pos--;
|
||||
b = src[pos];
|
||||
}
|
||||
|
||||
throw ErrUtl.NewArgs("could not get prv_char", "src", src, "cur", cur);
|
||||
}
|
||||
public static int IncrementChar(int cur) {
|
||||
while (cur++ < Codepoint_max) {
|
||||
if (cur == Codepoint_surrogate_bgn) cur = Codepoint_surrogate_end + 1; // skip over surrogate range
|
||||
if (!CodepointValid(cur)) continue;
|
||||
return cur;
|
||||
}
|
||||
return IntUtl.MinValue;
|
||||
}
|
||||
private static boolean CodepointValid(int v) {
|
||||
return Character.isDefined(v);
|
||||
}
|
||||
public static final int
|
||||
Codepoint_max = 0x10FFFF, //see http://unicode.org/glossary/
|
||||
Codepoint_surrogate_bgn = 0xD800,
|
||||
Codepoint_surrogate_end = 0xDFFF;
|
||||
}
|
||||
/*
|
||||
== Definitions ==
|
||||
=== a7 vs u8 ===
|
||||
* a7 -> ASCII (7 bits)
|
||||
* u8 -> UTF-8 (8 bytes)
|
||||
|
||||
In retrospect, better abbreviations would have been:
|
||||
* ascii -> ASCII
|
||||
* utf08 -> UTF-8
|
||||
* utf16 -> UTF-16
|
||||
|
||||
=== General ===
|
||||
==== Byte ====
|
||||
* Standard definition; 8 bits (2^8 or 256)
|
||||
|
||||
==== Codepoint ====
|
||||
* Represents 1 atomic character but can be composed of multiple bytes
|
||||
** Examples:
|
||||
<pre>
|
||||
1 byte : "a" (letter a)
|
||||
2 bytes: "¢" (cent)
|
||||
3 bytes: "€" (euro)
|
||||
4 bytes: "𤭢" (Chinese character)
|
||||
</pre>
|
||||
* Defined by unicode as a sequence of 4 hexadecimals (2 bytes) or 8 hexadecimals (4 bytes); REF:http://www.unicode.org
|
||||
** 4 hexadecimal is 2 bytes (2^(4 * 4) -> 2^16)
|
||||
|
||||
==== char ====
|
||||
* Java definition of a codepoint which is encoded as 2 bytes (2^16 or 65,536)
|
||||
* For Western langauges: 1 codepoint equals 1 char (2 bytes);
|
||||
** For example, chars like "a", "œ", "é" are 1 Java char
|
||||
* For Eastern langauges: 1 codepoint can equal 2 chars (4 bytes);
|
||||
** For example, chars like "駣" are 2 Java chars though they represent 1 conceptual codepoint (in English terms, "駣" is a single letter just like the letter "a")
|
||||
|
||||
==== Supplementary characters ====
|
||||
* Represents a codepoint which is defined by 3 or 4 bytes
|
||||
* Is defined by 1 surrogate pair
|
||||
** lo-surrogate : 2 bytes
|
||||
** hi-surrogate : 2 bytes
|
||||
|
||||
=== Conventions ===
|
||||
* Codepoints will be rendered as one int (4 bytes), not 4 hexadecimals (1 byte) 8 hexadecimal (4 bytes)
|
||||
* The "char" datatype will rarely be used in code; instead byte arrays or codepoint-ints will be used
|
||||
* The "character" word will not be used in comments; instead the "codepoint" word will be used
|
||||
*/
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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.types.basics.strings.unicodes;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.frameworks.tests.GfoTstr;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import org.junit.Test;
|
||||
public class Utf8UtlTest {
|
||||
private Utf8UtlTstr tstr = new Utf8UtlTstr();
|
||||
@Test public void Get_prv_char_pos0() {
|
||||
tstr.TestGetPrvCharPos0("abcd", 3); // len=1; (note that bry.len = 4)
|
||||
tstr.TestGetPrvCharPos0("a", 0); // len=1; short-String
|
||||
tstr.TestGetPrvCharPos0("abc¢", 3); // len=2; (note that bry.len = 5)
|
||||
tstr.TestGetPrvCharPos0("abc€", 3); // len=3; (note that bry.len = 6)
|
||||
tstr.TestGetPrvCharPos0("abc" + StringUtl.NewU8(ByteUtl.AryByInts(240, 164, 173, 162)), 3); // len=4; (note that bry.len = 7)
|
||||
}
|
||||
@Test public void Increment_char_at_last_pos() {
|
||||
tstr.TestIncrementCharAtLastPos("a", "b");
|
||||
tstr.TestIncrementCharAtLastPos("abc", "abd");
|
||||
tstr.TestIncrementCharAtLastPos("É", "Ê"); // len=2
|
||||
tstr.TestIncrementCharAtLastPos("€", "₭"); // len=3
|
||||
}
|
||||
// @Test public void Increment_char_at_last_pos_exhaustive_check() { // check all values; commented for perf
|
||||
// Bry_bfr bfr = Bry_bfr_.New();
|
||||
// int bgn = 32;
|
||||
// while (true) {
|
||||
// byte[] bgn_bry = Utf16_.Encode_int_to_bry(bgn);
|
||||
// int end = Utf8_.Increment_char(bgn);
|
||||
// if (end == Utf8_.Codepoint_max) break;
|
||||
//// if (bgn > 1024 * 1024) break;
|
||||
// byte[] end_by_codepoint_next = Utf16_.Encode_int_to_bry(end);
|
||||
// byte[] end_by_increment_char = Utf8_.Increment_char_at_last_pos(bgn_bry);
|
||||
// if (!Bry_.Eq(end_by_codepoint_next, end_by_increment_char)) {
|
||||
// Tfds.Write(bgn);
|
||||
// }
|
||||
//// bfr .Add_int_variable(bgn).Add_byte(Byte_ascii.Tab)
|
||||
//// .Add(bgn_bry).Add_byte(Byte_ascii.Tab)
|
||||
//// .Add(end_by_codepoint_next).Add_byte(Byte_ascii.Tab)
|
||||
//// .Add(end_by_increment_char).Add_byte(Byte_ascii.Tab)
|
||||
//// .Add_byte_nl()
|
||||
//// ;
|
||||
// bgn = end;
|
||||
// bgn_bry = end_by_codepoint_next;
|
||||
// }
|
||||
// Tfds.WriteText(bfr.To_str_and_clear());
|
||||
// }
|
||||
}
|
||||
class Utf8UtlTstr {
|
||||
public void TestGetPrvCharPos0(String srcStr, int expd) {
|
||||
byte[] srcBry = BryUtl.NewU8(srcStr);
|
||||
GfoTstr.Eq(expd, Utf8Utl.GetPrvCharPos0(srcBry, srcBry.length));
|
||||
GfoTstr.Eq(expd, Utf8Utl.GetPrvCharPos0Old(srcBry, srcBry.length - 1));
|
||||
}
|
||||
public void TestIncrementCharAtLastPos(String str, String expd) {GfoTstr.Eq(expd, StringUtl.NewU8(Utf8Utl.IncrementCharAtLastPos(BryUtl.NewU8(str))));}
|
||||
}
|
||||
32
baselib/src/gplx/types/basics/utls/ArrayLni.java
Normal file
32
baselib/src/gplx/types/basics/utls/ArrayLni.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package gplx.types.basics.utls;
|
||||
import java.lang.System;
|
||||
import java.lang.reflect.Array;
|
||||
public class ArrayLni {
|
||||
public static final Object Cast(Object o) {return o;} // NOTE: leftover from .NET; casts System.Object to System.Array
|
||||
public static final int Len(Object ary) {return Array.getLength(ary);}
|
||||
public static final Object GetAt(Object ary, int i) {return Array.get(ary, i);}
|
||||
public static final void SetAt(Object ary, int i, Object o) {Array.set(ary, i, o);}
|
||||
public static final Object Create(Class<?> c, int count) {return Array.newInstance(c, count);}
|
||||
public static final Class<?> ComponentType(Object ary) {return ary.getClass().getComponentType();}
|
||||
public static final void CopyTo(Object src, int srcBgn
|
||||
, Object trg, int trgBgn, int srcLen) {System.arraycopy(src, srcBgn, trg, trgBgn, srcLen);}
|
||||
|
||||
public static final Object Resize(Object src, int trgLen) {
|
||||
Object trg = Create(ComponentType(src), trgLen);
|
||||
int srcLen = Len(src);
|
||||
int copyLen = srcLen > trgLen ? trgLen : srcLen; // trgLen can either expand or shrink
|
||||
CopyTo(src, 0, trg, 0, copyLen);
|
||||
return trg;
|
||||
}
|
||||
public static final Object ResizeAddAry(Object src, Object... add) {
|
||||
int srcLen = Len(src);
|
||||
int addLen = add == null ? 0 : add.length;
|
||||
int trgLen = srcLen + addLen;
|
||||
Object trg = Create(ComponentType(src), trgLen);
|
||||
CopyTo(src, 0, trg, 0, srcLen);
|
||||
for (int i = 0; i < addLen; i++) {
|
||||
SetAt(trg, i + srcLen, add[i]);
|
||||
}
|
||||
return trg;
|
||||
}
|
||||
}
|
||||
@@ -13,17 +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.arrays;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
import gplx.objects.lists.ComparerAble;
|
||||
import gplx.objects.lists.ComparerAbleSorter;
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.commons.lists.ComparerAble;
|
||||
import gplx.types.commons.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 class ArrayUtl extends ArrayLni {
|
||||
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);}
|
||||
@@ -31,7 +26,6 @@ public class ArrayUtl {
|
||||
}
|
||||
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) {
|
||||
@@ -40,13 +34,6 @@ public class ArrayUtl {
|
||||
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);
|
||||
@@ -74,9 +61,4 @@ public class ArrayUtl {
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,13 @@ 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;
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
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;
|
||||
@@ -33,15 +29,8 @@ public class BoolUtl {
|
||||
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 String ToStrLower(boolean v) {return v ? TrueStr : FalseStr;}
|
||||
public static boolean Cast(Object o) {try {return (Boolean)o;} catch (Exception e) {throw ErrUtl.NewCast(boolean.class, o);}}
|
||||
public static boolean Parse(String raw) {
|
||||
if ( StringUtl.Eq(raw, TrueStr)
|
||||
|| StringUtl.Eq(raw, "True") // needed for Store_Wtr(){boolVal.toString();}
|
||||
101
baselib/src/gplx/types/basics/utls/BryLni.java
Normal file
101
baselib/src/gplx/types/basics/utls/BryLni.java
Normal file
@@ -0,0 +1,101 @@
|
||||
package gplx.types.basics.utls;
|
||||
public class BryLni {
|
||||
public static final byte[] Empty = new byte[0];
|
||||
public static final int LenSafe(byte[] v) {return v == null ? 0 : v.length;}
|
||||
public static final boolean Eq(byte[] lhs, byte[] rhs) {return Eq(lhs, 0, LenSafe(lhs), rhs, 0, LenSafe(rhs));}
|
||||
public static final boolean Eq(byte[] lhs, int lhsBgn, byte[] rhs) {return Eq(lhs, lhsBgn, LenSafe(lhs), rhs, 0, LenSafe(rhs));}
|
||||
public static final boolean Eq(byte[] lhs, int lhsBgn, int lhsEnd, byte[] rhs) {return Eq(lhs, lhsBgn, lhsEnd, rhs, 0, LenSafe(rhs));}
|
||||
public static final boolean Eq(byte[] lhs, int lhsBgn, int lhsEnd, byte[] rhs, int rhsBgn, int rhsEnd) {
|
||||
if (lhsBgn == -1) return false;
|
||||
int lhsLen = LenSafe(lhs);
|
||||
if (lhsEnd > lhsLen) lhsEnd = lhsLen; // must limit lhsEnd to lhsLen, else ArrayIndexOutOfBounds below; DATE:2015-01-31
|
||||
|
||||
int rhsLen = rhsEnd - rhsBgn;
|
||||
if (rhsLen != lhsEnd - lhsBgn) return false;
|
||||
if (rhsLen == 0) return lhsEnd - lhsBgn == 0; // "" only matches ""
|
||||
for (int i = 0; i < rhsLen; i++) {
|
||||
int lhsPos = lhsBgn + i;
|
||||
if (lhsPos >= lhsEnd) return false; // ran out of lhs; exit; EX: lhs=ab; rhs=abc
|
||||
if (lhs[lhsPos] != rhs[i + rhsBgn]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static final byte[] NewA7(String str) {
|
||||
if (str == null) return null;
|
||||
int strLen = str.length(); // PERF:NATIVE
|
||||
if (strLen == 0) return Empty;
|
||||
byte[] rv = new byte[strLen];
|
||||
for (int i = 0; i < strLen; ++i) {
|
||||
char c = str.charAt(i); // PERF:NATIVE
|
||||
if (c > 128) c = '?';
|
||||
rv[i] = (byte)c;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int NewU8ByLen(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;
|
||||
}
|
||||
public static void NewU8Write(String src, int srcLen, byte[] trg, int trgPos) {
|
||||
for (int i = 0; i < srcLen; ++i) {
|
||||
char c = src.charAt(i);
|
||||
if ( c < 128) {
|
||||
trg[trgPos++] = (byte)c;
|
||||
}
|
||||
else if ( c < 2048) {
|
||||
trg[trgPos++] = (byte)(0xC0 | (c >> 6));
|
||||
trg[trgPos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
else if ( (c > 55295) // 0xD800
|
||||
&& (c < 56320)) { // 0xDFFF
|
||||
if (i >= srcLen) throw ErrLni.NewMsg("incomplete surrogate pair at end of String");
|
||||
char nxtChar = src.charAt(i + 1);
|
||||
int v = 0x10000 + (c - 0xD800) * 0x400 + (nxtChar - 0xDC00);
|
||||
trg[trgPos++] = (byte)(0xF0 | (v >> 18));
|
||||
trg[trgPos++] = (byte)(0x80 | (v >> 12) & 0x3F);
|
||||
trg[trgPos++] = (byte)(0x80 | (v >> 6) & 0x3F);
|
||||
trg[trgPos++] = (byte)(0x80 | (v & 0x3F));
|
||||
++i;
|
||||
}
|
||||
else {
|
||||
trg[trgPos++] = (byte)(0xE0 | (c >> 12));
|
||||
trg[trgPos++] = (byte)(0x80 | (c >> 6) & 0x3F);
|
||||
trg[trgPos++] = (byte)(0x80 | (c & 0x3F));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void CopyTo(byte[] src, int srcBgn, int srcEnd, byte[] trg, int trgBgn) {
|
||||
int trgAdj = trgBgn - srcBgn;
|
||||
for (int i = srcBgn; i < srcEnd; i++)
|
||||
trg[i + trgAdj] = src[i];
|
||||
}
|
||||
public static byte[] Resize(byte[] src, int trgLen) {return Resize(src, 0, trgLen);}
|
||||
public static byte[] Resize(byte[] src, int srcBgn, int trgLen) {
|
||||
byte[] trg = new byte[trgLen];
|
||||
int srcLen = src.length;
|
||||
if (srcLen > trgLen) srcLen = trgLen; // trgLen can be less than srcLen
|
||||
CopyTo(src, srcBgn, srcLen, trg, 0);
|
||||
return trg;
|
||||
}
|
||||
public static byte[] Mid(byte[] src, int bgn) {return Mid(src, bgn, src.length);}
|
||||
public static byte[] Mid(byte[] src, int bgn, int end) {
|
||||
try {
|
||||
int len = end - bgn; if (len == 0) return BryLni.Empty;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = bgn; i < end; i++)
|
||||
rv[i - bgn] = src[i];
|
||||
return rv;
|
||||
} catch (Exception e) {throw ErrLni.NewMsg("mid failed; " + " bgn=" + bgn + " end=" + end);}
|
||||
}
|
||||
}
|
||||
752
baselib/src/gplx/types/basics/utls/BryUtl.java
Normal file
752
baselib/src/gplx/types/basics/utls/BryUtl.java
Normal file
@@ -0,0 +1,752 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.custom.brys.BryFind;
|
||||
import gplx.types.commons.GfoDecimal;
|
||||
import gplx.types.commons.GfoDecimalUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
public class BryUtl extends BryLni {
|
||||
public static final Class<?> ClsRefType = byte[].class;
|
||||
public static final String ClsValName = "byte[]";
|
||||
public static final byte[][] AryEmpty = new byte[0][];
|
||||
public static final byte[] TrimAryWs = Mask(256, AsciiByte.Tab, AsciiByte.Nl, AsciiByte.Cr, AsciiByte.Space);
|
||||
public static final byte DlmFld = (byte)'|';
|
||||
public static final byte DlmRow = (byte)'\n';
|
||||
public static final byte DlmQuote = (byte)'"';
|
||||
public static final byte AsciiZero = 48;
|
||||
public static final String FmtCsvDte = "yyyyMMdd HHmmss.fff";
|
||||
public static byte ByteNegSign = (byte)'-';
|
||||
public static int Len(byte[] v) {return v == null ? 0 : v.length;}
|
||||
public static boolean IsNotNullOrEmpty(byte[] v) {return v != null && v.length > 0;}
|
||||
public static boolean IsNullOrEmpty(byte[] v) {return v == null || v.length == 0;}
|
||||
public static boolean HasAtEnd(byte[] src, byte[] lkp, int src_bgn, int src_end) {
|
||||
int lkp_len = lkp.length;
|
||||
if (src_bgn < 0) return false;
|
||||
int pos = src_end - lkp_len; if (pos < src_bgn) return false; // lkp is longer than src
|
||||
for (int i = 0; i < lkp_len; i++) {
|
||||
if (lkp[i] != src[i + pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static void Set(byte[] src, int bgn, int end, byte[] repl) {
|
||||
int repl_len = repl.length;
|
||||
for (int i = 0; i < repl_len; i++)
|
||||
src[i + bgn] = repl[i];
|
||||
}
|
||||
public static void CopyToReversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
|
||||
// copies src to trg, but in reverse order; EX: trg="1" src="432." -> "1.234"
|
||||
int len = src_end - src_bgn;
|
||||
for (int i = 0; i < len; i++)
|
||||
trg[trg_bgn + i] = src[src_end - i - 1];
|
||||
}
|
||||
public static boolean HasAtBgn(byte[] src, byte lkp) {return BryUtl.HasAtBgn(src, lkp, 0);}
|
||||
public static boolean HasAtBgn(byte[] src, byte lkp, int src_bgn) {return src_bgn < src.length ? src[src_bgn] == lkp : false;}
|
||||
public static boolean HasAtBgn(byte[] src, byte[] lkp) {return BryUtl.HasAtBgn(src, lkp, 0, src.length);}
|
||||
public static boolean HasAtBgn(byte[] src, byte[] lkp, int src_bgn, int src_end) {
|
||||
int lkp_len = lkp.length;
|
||||
if (lkp_len + src_bgn > src_end) return false; // lkp is longer than src
|
||||
for (int i = 0; i < lkp_len; i++) {
|
||||
if (lkp[i] != src[i + src_bgn]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean HasAtEnd(byte[] src, byte lkp) {
|
||||
if (src == null) return false;
|
||||
int src_len = src.length;
|
||||
if (src_len == 0) return false;
|
||||
return src[src_len - 1] == lkp;
|
||||
}
|
||||
public static boolean HasAtEnd(byte[] src, byte[] lkp) {
|
||||
int src_len = src.length;
|
||||
return HasAtEnd(src, lkp, src_len - lkp.length, src_len);
|
||||
}
|
||||
public static byte[] Copy(byte[] src) {
|
||||
int src_len = src.length;
|
||||
byte[] trg = new byte[src_len];
|
||||
for (int i = 0; i < src_len; ++i)
|
||||
trg[i] = src[i];
|
||||
return trg;
|
||||
}
|
||||
public static byte[] RepeatSpace(int len) {return BryUtl.Repeat(AsciiByte.Space, len);}
|
||||
public static byte[] Repeat(byte b, int len) {
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] RepeatBry(byte[] bry, int len) {
|
||||
int bry_len = bry.length;
|
||||
int rv_len = len * bry_len;
|
||||
byte[] rv = new byte[rv_len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (int j = 0; j < bry_len; j++) {
|
||||
rv[(i * bry_len) + j] = bry[j];
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte[] src, byte b) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len + 1];
|
||||
CopyTo(src, 0, src_len, rv, 0);
|
||||
rv[src_len] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte b, byte[] src) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len + 1];
|
||||
CopyTo(src, 0, src_len, rv, 1);
|
||||
rv[0] = b;
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Add(byte[]... all) {
|
||||
int all_len = all.length, rv_len = 0;
|
||||
for (int i = 0; i < all_len; ++i) {
|
||||
byte[] cur = all[i]; if (cur == null) continue;
|
||||
rv_len += cur.length;
|
||||
}
|
||||
byte[] rv = new byte[rv_len];
|
||||
int rv_idx = 0;
|
||||
for (int i = 0; i < all_len; ++i) {
|
||||
byte[] cur = all[i]; if (cur == null) continue;
|
||||
int cur_len = cur.length;
|
||||
for (int j = 0; j < cur_len; ++j)
|
||||
rv[rv_idx++] = cur[j];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] AddWithDlm(byte[] dlm, byte[]... ary) {
|
||||
int ary_len = ary.length;
|
||||
if (ary_len == 0) return BryUtl.Empty;
|
||||
int dlm_len = dlm.length;
|
||||
int rv_len = dlm_len * (ary_len - 1); // rv will have at least as many dlms as itms - 1
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (itm != null) rv_len += itm.length;
|
||||
}
|
||||
int rv_pos = 0;
|
||||
byte[] rv = new byte[rv_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (i != 0) {
|
||||
for (int j = 0; j < dlm_len; j++) {
|
||||
rv[rv_pos++] = dlm[j];
|
||||
}
|
||||
}
|
||||
if (itm == null) continue;
|
||||
int itm_len = itm.length;
|
||||
for (int j = 0; j < itm_len; j++) {
|
||||
rv[rv_pos++] = itm[j];
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] AddWithDlm(byte dlm, byte[]... ary) {
|
||||
int ary_len = ary.length;
|
||||
if (ary_len == 0) return BryUtl.Empty;
|
||||
int rv_len = ary_len - 1; // rv will have at least as many dlms as itms - 1
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (itm != null) rv_len += itm.length;
|
||||
}
|
||||
int rv_pos = 0;
|
||||
byte[] rv = new byte[rv_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
if (i != 0) rv[rv_pos++] = dlm;
|
||||
if (itm == null) continue;
|
||||
int itm_len = itm.length;
|
||||
for (int j = 0; j < itm_len; j++) {
|
||||
rv[rv_pos++] = itm[j];
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte GetAtEnd(byte[] bry) {return bry[bry.length - 1];} // don't bother checking for errors; depend on error trace
|
||||
public static boolean HasAt(byte[] src, int src_len, int pos, byte b) {return (pos < src_len) && (src[pos] == b);}
|
||||
public static boolean Has(byte[] src, byte lkp) {
|
||||
if (src == null) return false;
|
||||
int len = src.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
if (src[i] == lkp) return true;
|
||||
return false;
|
||||
}
|
||||
public static void ReplaceAllDirect(byte[] src, byte find, byte repl) {BryUtl.ReplaceAllDirect(src, find, repl, 0, src.length);}
|
||||
public static void ReplaceAllDirect(byte[] src, byte find, byte repl, int bgn, int end) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
if (b == find) src[i] = repl;
|
||||
}
|
||||
}
|
||||
public static byte[] TrimBgn(byte[] v, byte trim, int bgn) {
|
||||
boolean trimmed = false;
|
||||
int len = v.length;
|
||||
int pos = bgn;
|
||||
for (; pos < len; pos++) {
|
||||
if (v[pos] == trim) {
|
||||
trimmed = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return trimmed ? BryLni.Mid(v, pos, len) : v;
|
||||
}
|
||||
public static byte[] TrimEnd(byte[] v, byte trim, int end) {
|
||||
boolean trimmed = false;
|
||||
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len
|
||||
for (; pos > -1; pos--) {
|
||||
if (v[pos] == trim) {
|
||||
trimmed = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return trimmed ? BryLni.Mid(v, 0, pos + 1) : v;
|
||||
}
|
||||
public static int Compare(byte[] lhs, byte[] rhs) {
|
||||
if (lhs == null) return CompareAbleUtl.More;
|
||||
else if (rhs == null) return CompareAbleUtl.Less;
|
||||
else return BryUtl.Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
|
||||
}
|
||||
public static int Compare(byte[] lhs, int lhs_bgn, int lhs_end, byte[] rhs, int rhs_bgn, int rhs_end) {
|
||||
int lhs_len = lhs_end - lhs_bgn, rhs_len = rhs_end - rhs_bgn;
|
||||
int min = lhs_len < rhs_len ? lhs_len : rhs_len;
|
||||
int rv = CompareAbleUtl.Same;
|
||||
for (int i = 0; i < min; i++) {
|
||||
rv = (lhs[i + lhs_bgn] & 0xff) - (rhs[i + rhs_bgn] & 0xff); // PATCH.JAVA:need to convert to unsigned byte
|
||||
if (rv != CompareAbleUtl.Same) return rv > CompareAbleUtl.Same ? CompareAbleUtl.More : CompareAbleUtl.Less; // NOTE: changed from if (rv != CompareAble_.Same) return rv; DATE:2013-04-25
|
||||
}
|
||||
return IntUtl.Compare(lhs_len, rhs_len); // lhs and rhs share same beginning bytes; return len comparisons
|
||||
}
|
||||
public static boolean EqCiA7(byte[] lhs, byte[] rhs, int rhs_bgn, int rhs_end) {
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
int lhs_len = lhs.length;
|
||||
int rhs_len = rhs_end - rhs_bgn;
|
||||
if (lhs_len != rhs_len) return false;
|
||||
for (int i = 0; i < lhs_len; i++) {
|
||||
byte lhs_b = lhs[i]; if (lhs_b > 64 && lhs_b < 91) lhs_b += 32; // lowercase
|
||||
byte rhs_b = rhs[i + rhs_bgn]; if (rhs_b > 64 && rhs_b < 91) rhs_b += 32; // lowercase
|
||||
if (lhs_b != rhs_b) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean MatchWithSwap(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end, byte swap_src, byte swap_trg) {// same as above, but used by XOWA for ttl matches;
|
||||
int src_len = src.length;
|
||||
if (src_end > src_len) src_end = src_len; // must limit src_end to src_len, else ArrayIndexOutOfBounds below; DATE:2015-01-31
|
||||
int find_len = find_end - find_bgn;
|
||||
if (find_len != src_end - src_bgn) return false;
|
||||
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
|
||||
for (int i = 0; i < find_len; i++) {
|
||||
int pos = src_bgn + i;
|
||||
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
|
||||
byte src_byte = src[pos]; if (src_byte == swap_src) src_byte = swap_trg;
|
||||
byte trg_byte = find[i + find_bgn]; if (trg_byte == swap_src) trg_byte = swap_trg;
|
||||
if (src_byte != trg_byte) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static byte[] Limit(byte[] src, int len) {
|
||||
if (src == null) return null;
|
||||
int src_len = src.length;
|
||||
return len < src_len ? BryLni.Mid(src, 0, len) : src;
|
||||
}
|
||||
public static byte[] MidByLen(byte[] src, int bgn, int len) {return Mid(src, bgn, bgn + len);}
|
||||
public static byte[] MidByLenSafe(byte[] src, int bgn, int len) {
|
||||
int src_len = src.length;
|
||||
if (bgn < 0) bgn = 0;
|
||||
if (len + bgn > src_len) len = (src_len - bgn);
|
||||
return Mid(src, bgn, bgn + len);
|
||||
}
|
||||
public static byte[] MidSafe(byte[] src, int bgn, int end) {
|
||||
if (src == null) return null;
|
||||
int src_len = src.length;
|
||||
if (bgn < 0)
|
||||
bgn = 0;
|
||||
else if (bgn >= src_len)
|
||||
bgn = src_len;
|
||||
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
else if (end >= src_len)
|
||||
end = src_len;
|
||||
|
||||
if (bgn > end)
|
||||
bgn = end;
|
||||
else if (end < bgn)
|
||||
end = bgn;
|
||||
|
||||
return Mid(src, bgn, end);
|
||||
}
|
||||
public static byte[] MidWithTrim(byte[] src, int bgn, int end) {
|
||||
int len = end - bgn; if (len == 0) return BryUtl.Empty;
|
||||
int actl_bgn = bgn, actl_end = end;
|
||||
// trim at bgn
|
||||
boolean chars_seen = false;
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
switch (src[i]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
break;
|
||||
default:
|
||||
chars_seen = true;
|
||||
actl_bgn = i;
|
||||
i = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!chars_seen) return BryUtl.Empty; // all ws
|
||||
// trim at end
|
||||
for (int i = end - 1; i >= actl_bgn; --i) {
|
||||
switch (src[i]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
break;
|
||||
default:
|
||||
actl_end = i + 1;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// extract mid
|
||||
len = actl_end - actl_bgn; if (len == 0) return BryUtl.Empty;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = actl_bgn; i < actl_end; ++i)
|
||||
rv[i - actl_bgn] = src[i];
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Mask(int len, byte... itms) {
|
||||
byte[] rv = new byte[len];
|
||||
int itms_len = itms.length;
|
||||
for (int i = 0; i < itms_len; i++) {
|
||||
byte itm = itms[i];
|
||||
rv[itm & 0xFF] = itm; // PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Trim(byte[] src) {return BryUtl.Trim(src, 0, src.length, true, true, TrimAryWs, true);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end) {return BryUtl.Trim(src, bgn, end, true, true, TrimAryWs, true);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary, boolean reuse_bry_if_noop) {
|
||||
int txt_bgn = bgn, txt_end = end;
|
||||
boolean all_ws = true;
|
||||
if (trim_bgn) {
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = src[i];
|
||||
if (trim_ary[b & 0xFF] == AsciiByte.Null) {
|
||||
txt_bgn = i;
|
||||
i = end;
|
||||
all_ws = false;
|
||||
}
|
||||
}
|
||||
if (all_ws) return BryUtl.Empty;
|
||||
}
|
||||
if (trim_end) {
|
||||
for (int i = end - 1; i > -1; i--) {
|
||||
byte b = src[i];
|
||||
if (trim_ary[b & 0xFF] == AsciiByte.Null) {
|
||||
txt_end = i + 1;
|
||||
i = -1;
|
||||
all_ws = false;
|
||||
}
|
||||
}
|
||||
if (all_ws) return BryUtl.Empty;
|
||||
}
|
||||
|
||||
if ( reuse_bry_if_noop
|
||||
&& bgn == 0 && end == src.length // Trim is called on entire bry, not subset
|
||||
&& bgn == txt_bgn && end == txt_end // Trim hasn't trimmed anything
|
||||
) {
|
||||
return src;
|
||||
}
|
||||
else
|
||||
return BryLni.Mid(src, txt_bgn, txt_end);
|
||||
}
|
||||
public static boolean MatchBwdAny(byte[] src, int src_end, int src_bgn, byte[] find) { // NOTE: utf8 doesn't matter (matching byte for byte)
|
||||
int find_len = find.length;
|
||||
for (int i = 0; i < find_len; i++) {
|
||||
int src_pos = src_end - i;
|
||||
int find_pos = find_len - i - 1;
|
||||
if (src_pos < src_bgn) return false; // ran out of src; exit; EX: src=ab; find=abc
|
||||
if (src[src_pos] != find[find_pos]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static 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.NewU8(itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Cast(Object val) {return (byte[])val;}
|
||||
public static byte[] NewByByte(byte b) {return new byte[] {b};}
|
||||
public static byte[] CoalesceToEmpty(byte[] v) {return v == null ? BryUtl.Empty : v;}
|
||||
public static byte[] Coalesce(byte[] v, byte[] or) {return v == null ? or : v;}
|
||||
public static byte[] NewU8Safe(String str) {return str == null ? null : BryUtl.NewU8(str);}
|
||||
public static byte[] NewU8(String src) {
|
||||
try {
|
||||
int srcLen = src.length();
|
||||
if (srcLen == 0) return BryUtl.Empty;
|
||||
int bryLen = NewU8ByLen(src, srcLen);
|
||||
byte[] bry = new byte[bryLen];
|
||||
NewU8Write(src, srcLen, bry, 0);
|
||||
return bry;
|
||||
}
|
||||
catch (Exception e) {throw ErrUtl.NewFmt(e, "invalid UTF-8 sequence; src={0}", src);}
|
||||
}
|
||||
public static byte[][] AryObj(Object... ary) {
|
||||
if (ary == null) return BryUtl.AryEmpty;
|
||||
int ary_len = ary.length;
|
||||
byte[][] rv = new byte[ary_len][];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
Object itm = ary[i];
|
||||
rv[i] = itm == null ? null : BryUtl.NewU8(ObjectUtl.ToStrOrEmpty(itm));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static boolean AryEq(byte[][] lhs, byte[][] rhs) {
|
||||
int lhs_len = lhs.length;
|
||||
int rhs_len = rhs.length;
|
||||
if (lhs_len != rhs_len) return false;
|
||||
for (int i = 0; i < lhs_len; ++i)
|
||||
if (!BryLni.Eq(lhs[i], rhs[i])) return false;
|
||||
return true;
|
||||
}
|
||||
public static byte[] IncrementLast(byte[] ary) {return BryUtl.IncrementLast(ary, ary.length - 1);}
|
||||
public static byte[] IncrementLast(byte[] ary, int end_idx) {
|
||||
for (int i = end_idx; i > -1; i--) {
|
||||
byte end_val_old = ary[i];
|
||||
byte end_val_new = (byte)(end_val_old + 1);
|
||||
ary[i] = end_val_new;
|
||||
if (end_val_new > (end_val_old & 0xff)) break; // PATCH.JAVA:need to convert to unsigned byte
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
public static byte[] UcaseAll(byte[] src) {return BryUtl.XcaseAll(BoolUtl.Y, src, 0, -1);}
|
||||
public static byte[] LcaseAll(byte[] src) {return BryUtl.XcaseAll(BoolUtl.N, src, 0, -1);}
|
||||
public static byte[] LcaseAll(byte[] src, int bgn, int end) {return BryUtl.XcaseAll(BoolUtl.N, src, bgn, end);}
|
||||
private static byte[] XcaseAll(boolean upper, byte[] src, int bgn, int end) {
|
||||
if (src == null) return null;
|
||||
int len = end == -1 ? src.length : end - bgn; if (len == 0) return src;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte b = src[i + bgn];
|
||||
if (upper) {
|
||||
if (b > 96 && b < 123) b -= 32;
|
||||
}
|
||||
else {
|
||||
if (b > 64 && b < 91) b += 32;
|
||||
}
|
||||
rv[i] = b;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] Ucase1st(byte[] src) {return BryUtl.Xcase1st(BoolUtl.Y, src);}
|
||||
public static byte[] Lcase1st(byte[] src) {return BryUtl.Xcase1st(BoolUtl.N, src);}
|
||||
private static byte[] Xcase1st(boolean upper, byte[] src) {
|
||||
if (src == null) return null;
|
||||
int len = src.length; if (len == 0) return src;
|
||||
byte[] rv = new byte[len];
|
||||
byte b = src[0];
|
||||
if (upper) {
|
||||
if (b > 96 && b < 123) b -= 32;
|
||||
}
|
||||
else {
|
||||
if (b > 64 && b < 91) b += 32;
|
||||
}
|
||||
rv[0] = b;
|
||||
for (int i = 1; i < len; ++i) {
|
||||
rv[i] = src[i];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[] ReplaceCreate(byte[] src, byte find, byte replace) {
|
||||
byte[] rv = BryUtl.Copy(src);
|
||||
BryUtl.ReplaceReuse(rv, find, replace);
|
||||
return rv;
|
||||
}
|
||||
public static void ReplaceReuse(byte[] src, byte find, byte replace) {
|
||||
int src_len = src.length;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
if (src[i] == find) src[i] = replace;
|
||||
}
|
||||
}
|
||||
public static byte[] Replace(byte[] src, byte find, byte replace) {return BryUtl.Replace(src, 0, src.length, find, replace);}
|
||||
public static byte[] Replace(byte[] src, int bgn, int end, byte find, byte replace) {
|
||||
int src_len = src.length;
|
||||
byte[] rv = new byte[src_len];
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
byte b = src[i];
|
||||
rv[i] = b == find ? replace : b;
|
||||
}
|
||||
for (int i = end; i < src_len; ++i)
|
||||
rv[i] = src[i];
|
||||
return rv;
|
||||
}
|
||||
public static byte[] NewByInts(int... ary) {
|
||||
int len = ary.length;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = (byte)ary[i];
|
||||
return rv;
|
||||
}
|
||||
public static int ToIntByA7(byte[] v) {
|
||||
int v_len = v.length;
|
||||
int mod = 8 * (v_len - 1);
|
||||
int rv = 0;
|
||||
for (int i = 0; i < v_len; i++) {
|
||||
rv |= v[i] << mod;
|
||||
mod -= 8;
|
||||
}
|
||||
return rv;
|
||||
// return ((0xFF & v[0]) << 24)
|
||||
// | ((0xFF & v[1]) << 16)
|
||||
// | ((0xFF & v[2]) << 8)
|
||||
// | (0xFF & v[3]);
|
||||
}
|
||||
public static byte[] NewByInt(int v) {
|
||||
byte b0 = (byte)(v >> 24);
|
||||
byte b1 = (byte)(v >> 16);
|
||||
byte b2 = (byte)(v >> 8);
|
||||
byte b3 = (byte)(v);
|
||||
if (b0 != 0) return new byte[] {b0, b1, b2, b3};
|
||||
else if (b1 != 0) return new byte[] {b1, b2, b3};
|
||||
else if (b2 != 0) return new byte[] {b2, b3};
|
||||
else return new byte[] {b3};
|
||||
}
|
||||
public static boolean ToBoolOr(byte[] raw, boolean or) {
|
||||
return BryLni.Eq(raw, BoolUtl.TrueBry) ? true : or;
|
||||
}
|
||||
public static boolean ToBoolByInt(byte[] ary) {
|
||||
int rv = BryUtl.ToIntOr(ary, 0, ary.length, IntUtl.MinValue, BoolUtl.Y, null);
|
||||
switch (rv) {
|
||||
case 0: return false;
|
||||
case 1: return true;
|
||||
default: throw ErrUtl.NewArgs("could not parse to boolean int", "val", StringUtl.NewU8(ary));
|
||||
}
|
||||
}
|
||||
public static int ToInt(byte[] ary) {return BryUtl.ToIntOrFail(ary, 0, ary.length);}
|
||||
public static int ToIntOrFail(byte[] ary, int bgn, int end) {
|
||||
int rv = BryUtl.ToIntOr(ary, bgn, end, IntUtl.MinValue, BoolUtl.Y, null);
|
||||
if (rv == IntUtl.MinValue) throw ErrUtl.NewArgs("could not parse to int", "val", StringUtl.NewU8(ary, bgn, end));
|
||||
return rv;
|
||||
}
|
||||
public static int ToIntOrNeg1(byte[] ary) {return BryUtl.ToIntOr(ary, 0 , ary.length, -1, BoolUtl.Y, null);}
|
||||
public static int ToIntOr(byte[] ary, int or) {return BryUtl.ToIntOr(ary, 0 , ary.length, or, BoolUtl.Y, null);}
|
||||
public static int ToIntOr(byte[] ary, int bgn, int end, int or) {return BryUtl.ToIntOr(ary, bgn , end , or, BoolUtl.Y, null);}
|
||||
public static int ToIntOrStrict(byte[] ary, int or) {return BryUtl.ToIntOr(ary, 0 , ary.length, or, BoolUtl.N, null);}
|
||||
private static int ToIntOr(byte[] ary, int bgn, int end, int or, boolean sign_is_valid, byte[] ignore_ary) {
|
||||
if ( ary == null
|
||||
|| end == bgn // null-len
|
||||
) return or;
|
||||
int rv = 0, multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
rv += multiple * (b - AsciiByte.Num0);
|
||||
multiple *= 10;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
return i == bgn && sign_is_valid ? rv * -1 : or;
|
||||
case AsciiByte.Plus:
|
||||
return i == bgn && sign_is_valid ? rv : or;
|
||||
default:
|
||||
boolean invalid = true;
|
||||
if (ignore_ary != null) {
|
||||
int ignore_ary_len = ignore_ary.length;
|
||||
for (int j = 0; j < ignore_ary_len; j++) {
|
||||
if (b == ignore_ary[j]) {
|
||||
invalid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid) return or;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int ToIntOrTrimWs(byte[] ary, int bgn, int end, int or) { // NOTE: same as To_int_or, except trims ws at bgn / end; DATE:2014-02-09
|
||||
if (end == bgn) return or; // null len
|
||||
int rv = 0, multiple = 1;
|
||||
boolean numbers_seen = false, ws_seen = false;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
rv += multiple * (b - AsciiByte.Num0);
|
||||
multiple *= 10;
|
||||
if (ws_seen) // "number ws number" pattern; invalid ws in middle; see tests
|
||||
return or;
|
||||
numbers_seen = true;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
return i == bgn ? rv * -1 : or;
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
if (numbers_seen)
|
||||
ws_seen = true;
|
||||
break;
|
||||
default: return or;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int ToIntOrLax(byte[] ary, int bgn, int end, int or) {
|
||||
if (end == bgn) return or; // null-len
|
||||
int end_num = end;
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte b = ary[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
if (i != bgn) {
|
||||
end_num = i;
|
||||
i = end;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
end_num = i;
|
||||
i = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BryUtl.ToIntOr(ary, bgn, end_num, or);
|
||||
}
|
||||
public static long ToLongOr(byte[] ary, long or) {return BryUtl.ToLongOr(ary, null, 0, ary.length, or);}
|
||||
public static long ToLongOr(byte[] ary, byte[] ignore_ary, int bgn, int end, long or) {
|
||||
if ( ary == null
|
||||
|| end == bgn // null-len
|
||||
) return or;
|
||||
long rv = 0, multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
|
||||
byte b = ary[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
rv += multiple * (b - AsciiByte.Num0);
|
||||
multiple *= 10;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
return i == bgn ? rv * -1 : or;
|
||||
case AsciiByte.Plus:
|
||||
return i == bgn ? rv : or;
|
||||
default:
|
||||
boolean invalid = true;
|
||||
if (ignore_ary != null) {
|
||||
int ignore_ary_len = ignore_ary.length;
|
||||
for (int j = 0; j < ignore_ary_len; j++) {
|
||||
if (b == ignore_ary[j]) {
|
||||
invalid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid) return or;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static double ToDouble(byte[] ary, int bgn, int end) {return DoubleUtl.Parse(StringUtl.NewU8(ary, bgn, end));}
|
||||
public static double ToDoubleOr(byte[] bry, double or) {return DoubleUtl.ParseOr(StringUtl.NewU8(bry, 0, bry.length), or);}
|
||||
public static double ToDoubleOr(byte[] ary, int bgn, int end, double or) {return DoubleUtl.ParseOr(StringUtl.NewU8(ary, bgn, end), or);}
|
||||
public static byte[][] AryAdd(byte[][] lhs, byte[][] rhs) {
|
||||
int lhs_len = lhs.length, rhs_len = rhs.length;
|
||||
if (lhs_len == 0) return rhs;
|
||||
else if (rhs_len == 0) return lhs;
|
||||
else {
|
||||
byte[][] rv = new byte[lhs_len + rhs_len][];
|
||||
for (int i = 0; i < lhs_len; i++)
|
||||
rv[i] = lhs[i];
|
||||
for (int i = 0; i < rhs_len; i++)
|
||||
rv[i + lhs_len] = rhs[i];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
public static int TrimEndPos(byte[] src, int end) {
|
||||
for (int i = end - 1; i > -1; i--) {
|
||||
switch (src[i]) {
|
||||
case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr: case AsciiByte.Space:
|
||||
break;
|
||||
default:
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public static void Clear(byte[] bry) {
|
||||
int len = bry.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
bry[i] = ByteUtl.Zero;
|
||||
}
|
||||
public static byte[] ToA7Bry(int val, int pad_len) {return BryUtl.ToA7Bry(val, null, 0, pad_len);}
|
||||
public static byte[] ToA7Bry(int val, byte[] ary, int aryPos, int pad_len) {
|
||||
int neg = 0;
|
||||
if (val < 0) {
|
||||
val *= -1;
|
||||
neg = 1;
|
||||
}
|
||||
int digits = val == 0 ? 0 : MathUtl.Log10(val);
|
||||
digits += 1; // digits = log + 1; EX: Log(1-9) = 0, Log(10-99) = 1
|
||||
int ary_len = digits + neg, aryBgn = aryPos, pad = 0;
|
||||
if (ary_len < pad_len) { // padding specified
|
||||
pad = pad_len - ary_len;
|
||||
ary_len = pad_len;
|
||||
}
|
||||
if (ary == null) ary = new byte[ary_len];
|
||||
long factor = 1; // factor needs to be long to handle 1 billion (for which factor would be 10 billion)
|
||||
for (int i = 0; i < digits; i++) // calc maxFactor
|
||||
factor *= 10;
|
||||
if (neg == 1) ary[0] = ByteNegSign;
|
||||
|
||||
for (int i = 0; i < pad; i++) // fill ary with pad
|
||||
ary[i + aryBgn] = AsciiByte.ToA7Str(0);
|
||||
aryBgn += pad; // advance aryBgn by pad
|
||||
for (int i = neg; i < ary_len - pad; i++) {
|
||||
int denominator = (int)(factor / 10); // cache denominator to check for divide by 0
|
||||
int digit = denominator == 0 ? 0 : (int)((val % factor) / denominator);
|
||||
ary[aryBgn + i] = AsciiByte.ToA7Str(digit);
|
||||
factor /= 10;
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
public static GfoDecimal ToDecimal(byte[] ary, int bgn, int end) {return GfoDecimalUtl.Parse(StringUtl.NewU8(ary, bgn, end));}
|
||||
public static boolean Has(byte[] src, byte[] lkp) {return BryFind.FindFwd(src, lkp) != BryFind.NotFound;}
|
||||
public static byte[] ReplaceOne(byte[] orig, byte[] find, byte[] repl) {
|
||||
// find val
|
||||
int orig_len = orig.length;
|
||||
int find_pos = BryFind.Find(orig, find, 0, orig_len, true);
|
||||
if (find_pos == BryFind.NotFound) return orig; // nothing found; exit
|
||||
|
||||
// do copy
|
||||
int find_len = find.length, repl_len = repl.length;
|
||||
int rv_len = orig_len + repl_len - find_len;
|
||||
byte[] rv = new byte[rv_len];
|
||||
CopyTo(orig, 0 , find_pos, rv, 0 ); // copy orig before repl
|
||||
CopyTo(repl, 0 , repl_len, rv, find_pos ); // copy repl
|
||||
CopyTo(orig, find_pos + find_len, orig_len, rv, find_pos + repl_len); // copy orig after repl
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
60
baselib/src/gplx/types/basics/utls/ByteUtl.java
Normal file
60
baselib/src/gplx/types/basics/utls/ByteUtl.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class ByteUtl {
|
||||
public static final String ClsValName = "byte";
|
||||
public static final Class<?> ClsRefType = Byte.class;
|
||||
public static final byte Zero = 0, MinValue = Byte.MIN_VALUE, MaxValue127 = 127;
|
||||
public static byte Cast(Object o) {try {return (Byte)o;} catch (Exception e) {throw ErrUtl.NewCast(byte.class, o);}}
|
||||
public static byte ByInt(int v) {return v > 127 ? (byte)(v - 256) : (byte)v;} // PERF?: (byte)(v & 0xff)
|
||||
public static int ToInt(byte v) {return v < 0 ? (int)v + 256 : v;}
|
||||
public static String ToStr(byte v) {return new Byte(v).toString();}
|
||||
public static byte[] ToBry(byte v) {return new byte[] {v};}
|
||||
public static byte Parse(String raw) {return Byte.parseByte(raw);}
|
||||
public static byte ParseOr(String raw, byte or) {
|
||||
try {
|
||||
return raw == null
|
||||
? or
|
||||
: ByteUtl.Parse(raw);
|
||||
}
|
||||
catch (Exception e) {return or;}
|
||||
}
|
||||
public static boolean EqAny(byte v, byte... ary) {
|
||||
for (byte itm : ary)
|
||||
if (v == itm) return true;
|
||||
return false;
|
||||
}
|
||||
public static boolean EqAll(byte v, byte... ary) {
|
||||
for (byte itm : ary)
|
||||
if (v != itm) return false;
|
||||
return true;
|
||||
}
|
||||
public static int Compare(byte lhs, byte rhs) {
|
||||
if (lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if (lhs < rhs) return CompareAbleUtl.Less;
|
||||
else return CompareAbleUtl.More;
|
||||
}
|
||||
public static byte[] AryByInts(int... ary) {
|
||||
int ary_len = ary.length;
|
||||
byte[] rv = new byte[ary_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
rv[i] = ByteUtl.ByInt(ary[i]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
73
baselib/src/gplx/types/basics/utls/CharUtl.java
Normal file
73
baselib/src/gplx/types/basics/utls/CharUtl.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class CharUtl {
|
||||
public static final String ClsValName = "char";
|
||||
public static final Class<?> ClsRefType = Character.class;
|
||||
public static final char Null = '\0';
|
||||
public static final char NewLine = '\n';
|
||||
public static boolean IsLetterEnglish(char c) {
|
||||
switch (c) {
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static boolean IsLetterLowerEnglish(char c) {
|
||||
switch (c) {
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static boolean IsNumber(char c) {
|
||||
switch (c) {
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static boolean IsWhitespace(char c) {
|
||||
switch (c) {
|
||||
case ' ': case '\t': case '\n': case '\r': return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
public static boolean In(char match, char... ary) {
|
||||
for (char itm : ary)
|
||||
if (itm == match) return true;
|
||||
return false;
|
||||
}
|
||||
public static int ToDigitOr(char c, int or) {
|
||||
switch (c) {
|
||||
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
|
||||
case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
|
||||
default: return or;
|
||||
}
|
||||
}
|
||||
public static int ToInt(char c) {return (int)c;}
|
||||
public static String ToStr(char[] ary, int pos, int length) {return new String(ary, pos, length);}
|
||||
public static String ToStr(int b) {return CharUtl.ToStr((char)b);}
|
||||
public static String ToStr(char c) {return String.valueOf(c);}
|
||||
public static char ByInt(int i) {return (char)i;}
|
||||
public static char Cast(Object o) {try {return (Character)o;} catch(Exception e) {throw ErrUtl.NewCast(char.class, o);}}
|
||||
public static char Parse(String raw) {try {return raw.charAt(0);} catch(Exception exc) {throw ErrUtl.NewParse(char.class, raw);}}
|
||||
}
|
||||
21
baselib/src/gplx/types/basics/utls/ClassLni.java
Normal file
21
baselib/src/gplx/types/basics/utls/ClassLni.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package gplx.types.basics.utls;
|
||||
public class ClassLni {
|
||||
public static final boolean IsArray(Class<?> t) {return t.isArray();}
|
||||
public static final boolean IsAssignableFromByObj(Object o, Class<?> generic) {return o == null ? false : IsAssignableFrom(generic, o.getClass());}
|
||||
public static final boolean IsAssignableFrom(Class<?> generic, Class<?> specific) {return generic.isAssignableFrom(specific);}
|
||||
public static final Class<?> TypeByObj(Object o) {return o.getClass();}
|
||||
public static final String NameByObj(Object obj) {return obj == null ? StringLni.NullMark : Name(TypeByObj(obj));}
|
||||
public static final String Name(Class<?> type) {return type.getName();}
|
||||
public static final String CanonicalNameByObj(Object o) {return CanonicalName(o.getClass());}
|
||||
public static final String CanonicalName(Class<?> type) {return type.getCanonicalName();}
|
||||
public static final String SimpleNameByObj(Object obj) {return obj == null ? StringLni.NullMark : TypeByObj(obj).getSimpleName();}
|
||||
public static final boolean EqByObj(Class<?> lhsType, Object rhsObj) {
|
||||
Class<?> rhsType = rhsObj == null ? null : TypeByObj(rhsObj);
|
||||
return Eq(lhsType, rhsType);
|
||||
}
|
||||
public static final 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
public class CharUtl {
|
||||
public static final String ClsValName = "char";
|
||||
public static final Class<?> ClsRefType = Character.class;
|
||||
package gplx.types.basics.utls;
|
||||
public class ClassUtl extends ClassLni {
|
||||
}
|
||||
@@ -13,11 +13,17 @@ 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;
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class DoubleUtl {
|
||||
public static final String ClsValName = "double";
|
||||
public static final Class<?> ClsRefType = Double.class;
|
||||
|
||||
public static final double MinValue = Double.MIN_VALUE;
|
||||
public static final double NaN = Double.NaN;
|
||||
public static final double InfinityPos = Double.POSITIVE_INFINITY;
|
||||
public static final byte[] NaNBry = BryUtl.NewA7("NaN");
|
||||
public static final byte[] InfinityPosBry = BryUtl.NewA7("INF");
|
||||
public static String ToStrByPrintF(double val) {
|
||||
// call sprintf-like format; EX:"sprintf((s), "%.14g", (n));"
|
||||
return TrimZeroes(String.format("%.14g", val));
|
||||
@@ -108,4 +114,30 @@ public class DoubleUtl {
|
||||
}
|
||||
return valStr;
|
||||
}
|
||||
public static double Cast(Object o) {try {return (Double)o;} catch(Exception e) {throw ErrUtl.NewCast(double.class, o);}}
|
||||
public static double Parse(String raw) {try {return Double.parseDouble(raw);} catch(Exception e) {throw ErrUtl.NewParse(double.class, raw);}}
|
||||
public static double ParseOr(String raw, double v) {try {return Double.parseDouble(raw);} catch(Exception e) {return v;}}
|
||||
public static double CastOrParse(Object v) {
|
||||
try {String s = StringUtl.CastOrNull(v); return s == null ? DoubleUtl.Cast(v) : DoubleUtl.Parse(s);}
|
||||
catch (Exception e) {throw ErrUtl.NewCast(double.class, v);}
|
||||
}
|
||||
public static boolean IsNaN(double v) {return Double.isNaN(v);}
|
||||
public static String ToStr(double v) {
|
||||
int vInt = (int)v;
|
||||
return v - vInt == 0 ? IntUtl.ToStr(vInt) : Double.toString(v);
|
||||
}
|
||||
public static String ToStrLoose(double v) {
|
||||
int vInt = (int)v;
|
||||
return v == vInt
|
||||
// convert to int, and call print String to eliminate any trailing decimal places
|
||||
? IntUtl.ToStr(vInt)
|
||||
// DATE:2014-07-29; calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d
|
||||
// DATE:2020-08-12; calling ToStrByPrintF b/c better at removing trailing 0s; ISSUE#:697;
|
||||
: DoubleUtl.ToStrByPrintF(v);
|
||||
}
|
||||
public static int Compare(double lhs, double rhs) {
|
||||
if (lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if (lhs < rhs) return CompareAbleUtl.Less;
|
||||
else return CompareAbleUtl.More;
|
||||
}
|
||||
}
|
||||
40
baselib/src/gplx/types/basics/utls/ErrLni.java
Normal file
40
baselib/src/gplx/types/basics/utls/ErrLni.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.errs.Err;
|
||||
public class ErrLni {
|
||||
public static Err NewMsg(String msg) {return new Err("GENERAL", msg);}
|
||||
public static final String Message(Throwable e) {
|
||||
return Error.class.isAssignableFrom(e.getClass())
|
||||
? e.toString() // NOTE: java.lang.Error returns null for "getMessage()"; return "toString()" instead
|
||||
: e.getMessage();
|
||||
}
|
||||
public static final String Trace(Throwable e) {
|
||||
StackTraceElement[] ary = e.getStackTrace();
|
||||
String rv = "";
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) rv += "\n";
|
||||
rv += ary[i].toString();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
// private static String Trace_to_str(boolean is_gplx, boolean called_by_log, int ignore_lines, String trace) {
|
||||
// if (trace == null) return ""; // WORKAROUND:.NET: StackTrace is only available when error is thrown; can't do "Console.Write(new Exception().StackTrace);
|
||||
// String[] lines = StringUtl.SplitLang(trace, '\n'); int lines_len = lines.length;
|
||||
// int line_bgn = 0;
|
||||
// if (is_gplx) { // remove ErrUtl.NewArgs lines from trace for gplx exceptions
|
||||
// for (int i = 0; i < lines_len; ++i) {
|
||||
// String line = lines[i];
|
||||
// if (StringUtl.HasAtBgn(line, "gplx.Err_.new")) continue; // ignore trace frames with "gplx.Err_.new"; EX: throw Err_.new_unimplemented
|
||||
// line_bgn = i + ignore_lines;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // concat lines
|
||||
// String rv = "";
|
||||
// String line_bgn_dlm = called_by_log ? "\t " : "\n "; // "\n " indents
|
||||
// for (int i = line_bgn; i < lines_len; ++i)
|
||||
// rv += line_bgn_dlm + lines[i];
|
||||
// return rv;
|
||||
// }
|
||||
//
|
||||
}
|
||||
41
baselib/src/gplx/types/basics/utls/FloatUtl.java
Normal file
41
baselib/src/gplx/types/basics/utls/FloatUtl.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.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class FloatUtl {
|
||||
public static final String ClsValName = "float";
|
||||
public static final Class<?> ClsRefType = Float.class;
|
||||
public static final float NaN = Float.NaN;
|
||||
public static boolean IsNaN(float v) {return Float.isNaN(v);}
|
||||
public static float Cast(Object obj) {try {return (Float)obj;} catch(Exception exc) {throw ErrUtl.NewCast(float.class, obj);}}
|
||||
public static float Parse(String raw) {try {return Float.parseFloat(raw);} catch(Exception exc) {throw ErrUtl.NewParse(float.class, raw);}}
|
||||
public static int Compare(float lhs, float rhs) {
|
||||
if ( lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if ( lhs < rhs) return CompareAbleUtl.Less;
|
||||
else /*lhs > rhs*/ return CompareAbleUtl.More;
|
||||
}
|
||||
public static String ToStr(float v) {
|
||||
int vAsInt = (int)v;
|
||||
return v - vAsInt == 0 ? IntUtl.ToStr(vAsInt) : Float.toString(v);
|
||||
}
|
||||
public static float Div(int val, int divisor) {return (float)val / (float)divisor;}
|
||||
public static float Div(long val, long divisor) {return (float)val / (float)divisor;}
|
||||
public static int RoundUp(float val) {
|
||||
int rv = (int)val;
|
||||
return (rv == val) ? rv : rv + 1;
|
||||
}
|
||||
}
|
||||
54
baselib/src/gplx/types/basics/utls/IntLni.java
Normal file
54
baselib/src/gplx/types/basics/utls/IntLni.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package gplx.types.basics.utls;
|
||||
public class IntLni {
|
||||
public static final int
|
||||
MinValue = Integer.MIN_VALUE,
|
||||
MaxValue = Integer.MAX_VALUE,
|
||||
MaxValue31 = 2147483647,
|
||||
Neg1 = -1,
|
||||
Null = 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)
|
||||
Zero = 0;
|
||||
|
||||
public static String ToStr(int v) {return new Integer(v).toString();}
|
||||
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
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
176
baselib/src/gplx/types/basics/utls/IntUtl.java
Normal file
176
baselib/src/gplx/types/basics/utls/IntUtl.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
public class IntUtl extends IntLni {
|
||||
public static final String ClsValName = "int";
|
||||
public static final Class<?> ClsRefType = Integer.class;
|
||||
|
||||
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 int CastOr(Object obj, int or) {try {return (Integer)obj;} catch(Exception e) {return or;}}
|
||||
public static int CastOrParse(Object v) {
|
||||
try {
|
||||
String s = StringUtl.CastOrNull(v);
|
||||
return s == null ? Cast(v) : IntUtl.Parse(s);
|
||||
}
|
||||
catch (Exception e) {throw ErrUtl.NewCast(int.class, v);}
|
||||
}
|
||||
public static int Parse(String raw) {try {return Integer.parseInt(raw);} catch(Exception e) {throw ErrUtl.NewParse(int.class, raw);}}
|
||||
public static int ByHexBry(byte[] src) {return IntUtl.ByHexBry(src, 0, src.length);}
|
||||
public static int ByHexBry(byte[] src, int bgn, int end) {
|
||||
int rv = 0; int factor = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) {
|
||||
int val = IntUtl.ByHexByte(src[i]);
|
||||
rv += (val * factor);
|
||||
factor *= 16;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int ByHexByte(byte b) {
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
return b - AsciiByte.Num0;
|
||||
case AsciiByte.Ltr_A: case AsciiByte.Ltr_B: case AsciiByte.Ltr_C: case AsciiByte.Ltr_D: case AsciiByte.Ltr_E: case AsciiByte.Ltr_F:
|
||||
return b - AsciiByte.Ltr_A + 10;
|
||||
case AsciiByte.Ltr_a: case AsciiByte.Ltr_b: case AsciiByte.Ltr_c: case AsciiByte.Ltr_d: case AsciiByte.Ltr_e: case AsciiByte.Ltr_f:
|
||||
return b - AsciiByte.Ltr_a + 10;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
public static byte[] ToBry(int v) {return BryUtl.NewA7(ToStr(v));}
|
||||
public static String ToStrFmt(int v, String fmt) {return new java.text.DecimalFormat(fmt).format(v);}
|
||||
public static String ToStrPadBgnSpace(int val, int reqd_len) {return IntUtl.ToStrPad(val, reqd_len, BoolUtl.Y, AsciiByte.Space);} // EX: 1, 3 returns " 1"
|
||||
public static String ToStrPadBgnZero(int val, int reqd_len) {return IntUtl.ToStrPad(val, reqd_len, BoolUtl.Y, AsciiByte.Num0);} // EX: 1, 3 returns "001"
|
||||
private static String ToStrPad(int val, int reqd_len, boolean bgn, byte pad_chr) {
|
||||
// get val_len and pad_len; exit early, if no padding needed
|
||||
int val_len = CountDigits(val);
|
||||
int pad_len = reqd_len - val_len;
|
||||
if (pad_len < 0)
|
||||
return ToStr(val);
|
||||
|
||||
// padding needed
|
||||
GfoStringBldr bldr = new GfoStringBldr();
|
||||
|
||||
// handle negative numbers; EX: -1 -> "-001", not "00-1"
|
||||
if (val < 0) {
|
||||
bldr.AddChar('-');
|
||||
val *= -1;
|
||||
--val_len;
|
||||
}
|
||||
|
||||
// build outpt
|
||||
if (!bgn)
|
||||
bldr.AddIntFixed(val, val_len);
|
||||
bldr.AddCharRepeat((char)pad_chr, pad_len);
|
||||
if (bgn)
|
||||
bldr.AddIntFixed(val, val_len);
|
||||
|
||||
return bldr.ToStr();
|
||||
}
|
||||
public static String ToStrHex(int v) {return IntUtl.ToStrHex(BoolUtl.Y, BoolUtl.Y, v);}
|
||||
public static String ToStrHex(boolean zero_pad, boolean upper, int v) {
|
||||
String rv = Integer.toHexString(v);
|
||||
int rvLen = StringUtl.Len(rv);
|
||||
if (zero_pad && rvLen < 8) rv = StringUtl.Repeat("0", 8 - rvLen) + rv;
|
||||
return upper ? StringUtl.Upper(rv) : rv;
|
||||
}
|
||||
public static int Compare(int lhs, int rhs) {
|
||||
if (lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if (lhs < rhs) return CompareAbleUtl.Less;
|
||||
else return CompareAbleUtl.More;
|
||||
}
|
||||
public static boolean In(int v, int comp0, int comp1) {return v == comp0 || v == comp1;}
|
||||
public static boolean In(int v, int... ary) {
|
||||
for (int itm : ary)
|
||||
if (v == itm) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int[] Log10Vals = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, IntUtl.MaxValue};
|
||||
public static int Log10ValsLen = 11;
|
||||
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;
|
||||
}
|
||||
public static boolean RangeCheck(int v, int max) {return v >= 0 && v < max;}
|
||||
public static void RangeCheckOrFailList(int v, int max, String s) {if (v < 0 || v >= max) throw ErrUtl.NewFmt("bounds check failed; msg={0} v={1} min={2} max={3}", s, v, 0, max - 1);}
|
||||
public static boolean BoundsChk(int bgn, int end, int len) {return bgn > -1 && end < len;}
|
||||
public static int BoundEnd(int v, int end) {return v >= end ? end - 1 : v;}
|
||||
public static int Min(int lhs, int rhs) {return lhs < rhs ? lhs : rhs;}
|
||||
public static int Max(int lhs, int rhs) {return lhs > rhs ? lhs : rhs;}
|
||||
public static int MinMany(int... ary) {
|
||||
int len = ary.length;
|
||||
if (len == 0) throw ErrUtl.NewMsg("Min_many requires at least 1 value");
|
||||
boolean init = true;
|
||||
int min = MinValue;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int val = ary[i];
|
||||
if (init) {
|
||||
min = val;
|
||||
init = false;
|
||||
}
|
||||
else {
|
||||
if (val < min)
|
||||
min = val;
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
public static int SubtractLong(long lhs, long rhs) {return (int)(lhs - rhs);}
|
||||
public static int Div(int v, float divisor) {return (int)((float)v / divisor);}
|
||||
public static int DivAndRoundUp(int v, int divisor) {
|
||||
int whole = v / divisor;
|
||||
int partial = v % divisor == 0 ? 0 : 1;
|
||||
return whole + partial;
|
||||
}
|
||||
public static int Mult(int v, float multiplier) {
|
||||
float product = ((float)v * multiplier); // WORKAROUND (DotNet): (int)((float)v * multiplier) returns 0 for 100 and .01f
|
||||
return (int)product;
|
||||
}
|
||||
}
|
||||
108
baselib/src/gplx/types/basics/utls/LongUtl.java
Normal file
108
baselib/src/gplx/types/basics/utls/LongUtl.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class LongUtl {
|
||||
public static final String ClsValName = "long";
|
||||
public static final Class<?> ClsRefType = Long.class;
|
||||
public static final int Log10AryLen = 21;
|
||||
public static final long
|
||||
MinValue = Long.MIN_VALUE;
|
||||
public static final long MaxValue = Long.MAX_VALUE
|
||||
;
|
||||
public static long[] Log10Ary = new long[]
|
||||
{ 1, 10, 100, 1000, 10000
|
||||
, 100000, 1000000, 10000000, 100000000, 1000000000
|
||||
, LongUtl.Pow(10, 10), LongUtl.Pow(10, 11), LongUtl.Pow(10, 12), LongUtl.Pow(10, 13), LongUtl.Pow(10, 14)
|
||||
, LongUtl.Pow(10, 15), LongUtl.Pow(10, 16), LongUtl.Pow(10, 17), LongUtl.Pow(10, 18), LongUtl.Pow(10, 19)
|
||||
, LongUtl.MaxValue
|
||||
};
|
||||
public static long Cast(Object obj) {try {return (Long)obj;} catch(Exception e) {throw ErrUtl.NewCast(long.class, obj);}}
|
||||
public static String ToStr(long v) {return new Long(v).toString();}
|
||||
public static long Parse(String raw) {try {return Long.parseLong(raw);} catch(Exception e) {throw ErrUtl.NewParse(long.class, raw);}}
|
||||
public static String ToStrPadBgn(long v, int reqdPlaces) {return StringUtl.Pad(ToStr(v), reqdPlaces, "0", true);} // ex: 1, 3 returns 001
|
||||
public static long ParseOr(String raw, long or) {
|
||||
if (raw == null) return or;
|
||||
try {
|
||||
int rawLen = StringUtl.Len(raw);
|
||||
if (raw == null || rawLen == 0) return or;
|
||||
long rv = 0, factor = 1; int tmp = 0;
|
||||
for (int i = rawLen; i > 0; i--) {
|
||||
tmp = CharUtl.ToDigitOr(StringUtl.CharAt(raw, i - 1), IntUtl.MinValue);
|
||||
if (tmp == IntUtl.MinValue) return or;
|
||||
rv += (tmp * factor);
|
||||
factor *= 10;
|
||||
}
|
||||
return rv;
|
||||
} catch (Exception e) {return or;}
|
||||
}
|
||||
public static int Compare(long lhs, long rhs) {
|
||||
if (lhs == rhs) return CompareAbleUtl.Same;
|
||||
else if (lhs < rhs) return CompareAbleUtl.Less;
|
||||
else return CompareAbleUtl.More;
|
||||
}
|
||||
private static int FindIdx(long[] ary, long find_val) {
|
||||
int ary_len = ary.length;
|
||||
int adj = 1;
|
||||
int prv_pos = 0;
|
||||
int prv_len = ary_len;
|
||||
int cur_len = 0;
|
||||
int cur_idx = 0;
|
||||
long cur_val = 0;
|
||||
while (true) {
|
||||
cur_len = prv_len / 2;
|
||||
if (prv_len % 2 == 1) ++cur_len;
|
||||
cur_idx = prv_pos + (cur_len * adj);
|
||||
if (cur_idx < 0) cur_idx = 0;
|
||||
else if (cur_idx >= ary_len) cur_idx = ary_len - 1;
|
||||
cur_val = ary[cur_idx];
|
||||
if (find_val < cur_val) adj = -1;
|
||||
else if (find_val > cur_val) adj = 1;
|
||||
else if (find_val == cur_val) return cur_idx;
|
||||
if (cur_len == 1) {
|
||||
if (adj == -1 && cur_idx > 0)
|
||||
return --cur_idx;
|
||||
return cur_idx;
|
||||
}
|
||||
prv_len = cur_len;
|
||||
prv_pos = cur_idx;
|
||||
}
|
||||
}
|
||||
public static int DigitCount(long v) {
|
||||
int adj = IntUtl.Base1;
|
||||
if (v < 0) {
|
||||
if (v == LongUtl.MinValue) return 19; // NOTE: LongUtl.Min_value * -1 = LongUtl.Min_value
|
||||
v *= -1;
|
||||
++adj;
|
||||
}
|
||||
return LongUtl.FindIdx(Log10Ary, v) + adj;
|
||||
}
|
||||
public static long Pow(int val, int exp) {
|
||||
long rv = val;
|
||||
for (int i = 1; i < exp; i++)
|
||||
rv *= val;
|
||||
return rv;
|
||||
}
|
||||
public static long IntMerge(int hi, int lo) {return (long)hi << 32 | (lo & 0xFFFFFFFFL);}
|
||||
public static int IntSplitLo(long v) {return (int)(v);}
|
||||
public static int IntSplitHi(long v) {return (int)(v >> 32);}
|
||||
}
|
||||
/* alternate for Int_merge; does not work in java
|
||||
public static long MergeInts(int lo, int hi) {return (uint)(hi << 32) | (lo & 0xffffffff);}
|
||||
public static int SplitLo(long v) {return (int)(((ulong)v & 0x00000000ffffffff));}
|
||||
public static int SplitHi(long v) {return (int)(((ulong)v & 0xffffffff00000000)) >> 32;}
|
||||
*/
|
||||
69
baselib/src/gplx/types/basics/utls/MathUtl.java
Normal file
69
baselib/src/gplx/types/basics/utls/MathUtl.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
public class MathUtl {
|
||||
public static int Min(int val0, int val1) {return val0 < val1 ? val0 : val1;}
|
||||
public static int Max(int val0, int val1) {return val0 > val1 ? val0 : val1;}
|
||||
public static int Abs(int val) {return val > 0 ? val : val * -1;}
|
||||
public static long Abs(long val) {return val > 0 ? val : val * -1;}
|
||||
public static float Abs(float val) {return val > 0 ? val : val * -1;}
|
||||
public static double AbsAsDouble(double val) {return val > 0 ? val : val * -1;}
|
||||
public static int Trunc(double v) {return (int)v;}
|
||||
public static double Round(double v, int places) {return java.math.BigDecimal.valueOf(v).setScale(places, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();}
|
||||
public static double Ceil(double v) {return Math.ceil(v);}
|
||||
public static int CeilAsInt(double v) {return (int)Ceil(v);}
|
||||
public static double Floor(double v) {return Math.floor(v);}
|
||||
public static int FloorAsInt(double v) {return (int)Floor(v);}
|
||||
public static int DivSafeAsInt(int val, int divisor) {return divisor == 0 ? 0 : val / divisor;}
|
||||
public static long DivSafeAsLong(long val, long divisor) {return divisor == 0 ? 0 : val / divisor;}
|
||||
public static double DivSafeAsDouble(double val, double divisor) {return divisor == 0 ? 0 : val / divisor;}
|
||||
public static double Pow(double val, double exponent) {return Math.pow(val, exponent);}
|
||||
public static int PowAsInt(int val, int exponent) {return (int)Math.pow(val, exponent);}
|
||||
public static double Exp(double v) {return Math.exp(v);}
|
||||
public static double Sqrt(double v) {return Math.sqrt(v);}
|
||||
public static double Log(double v) {return Math.log(v);}
|
||||
public static int Log10(int val) {
|
||||
if (val <= 0) return IntUtl.MinValue;
|
||||
int rv = -1, baseVal = 10;
|
||||
while (val != 0) {
|
||||
val = (val / baseVal);
|
||||
rv++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static double Sin(double v) {return Math.sin(v);}
|
||||
public static double Cos(double v) {return Math.cos(v);}
|
||||
public static double Tan(double v) {return Math.tan(v);}
|
||||
public static double Asin(double v) {return Math.asin(v);}
|
||||
public static double Acos(double v) {return Math.acos(v);}
|
||||
public static double Atan(double v) {return Math.atan(v);}
|
||||
public static int[] Base2Ary(int v, int max) {
|
||||
int[] idxs = new int[32];
|
||||
int cur = v, mult = max, idx = 0;
|
||||
while (mult > 0) {
|
||||
int tmp = cur / mult;
|
||||
if (tmp >= 1) {
|
||||
idxs[idx++] = mult;
|
||||
cur -= mult;
|
||||
}
|
||||
mult /= 2;
|
||||
}
|
||||
int[] rv = new int[idx];
|
||||
for (int i = 0; i < idx; i++)
|
||||
rv[i] = idxs[idx - i - 1];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
19
baselib/src/gplx/types/basics/utls/ObjectLni.java
Normal file
19
baselib/src/gplx/types/basics/utls/ObjectLni.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package gplx.types.basics.utls;
|
||||
public class ObjectLni {
|
||||
public static final String ClsValName = "Object";
|
||||
public static final Object[] AryEmpty = new Object[0];
|
||||
public static final byte[] NullBry = BryLni.NewA7("null");
|
||||
|
||||
public static boolean Eq(Object lhs, Object rhs) {
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
else return lhs.equals(rhs);
|
||||
}
|
||||
public static final String ToStrOrNullMark(Object v) {return v == null ? StringLni.NullMark : ToStr(v);}
|
||||
public static final String ToStr(Object v) {
|
||||
Class<?> c = v.getClass();
|
||||
if (ClassLni.Eq(c, String.class)) return (String)v;
|
||||
else if (ClassLni.Eq(c, byte[].class)) return StringLni.NewByBry((byte[])v);
|
||||
else return v.toString();
|
||||
}
|
||||
}
|
||||
43
baselib/src/gplx/types/basics/utls/ObjectUtl.java
Normal file
43
baselib/src/gplx/types/basics/utls/ObjectUtl.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.types.basics.utls;
|
||||
public class ObjectUtl extends ObjectLni {
|
||||
public static Object[] Ary(Object... ary) {return ary;}
|
||||
public static Object[] AryAdd(Object[] lhs, Object[] rhs) {
|
||||
int lhsLen = lhs.length, rhsLen = rhs.length;
|
||||
if (lhsLen == 0) return rhs;
|
||||
else if (rhsLen == 0) return lhs;
|
||||
int rvLen = lhsLen + rhsLen;
|
||||
Object[] rv = new Object[rvLen];
|
||||
for (int i = 0; i < lhsLen; ++i)
|
||||
rv[i] = lhs[i];
|
||||
for (int i = lhsLen; i < rvLen; ++i)
|
||||
rv[i] = rhs[i - lhsLen];
|
||||
return rv;
|
||||
}
|
||||
public static String ToStrOr(Object v, String or) {return v == null ? or : ToStr(v);}
|
||||
public static String ToStrOrNull(Object v) {return v == null ? null : ToStr(v);}
|
||||
public static String ToStrOrEmpty(Object v) {return v == null ? StringUtl.Empty : ToStr(v);}
|
||||
public static String ToStrLooseOr(Object v, String or) { // tries to pretty-print doubles; also standardizes true/false; DATE:2014-07-14
|
||||
if (v == null) return null;
|
||||
Class<?> c = ClassUtl.TypeByObj(v);
|
||||
if (ClassUtl.Eq(c, StringUtl.ClsRefType)) return (String)v;
|
||||
else if (ClassUtl.Eq(c, BryUtl.ClsRefType)) return StringUtl.NewU8((byte[])v);
|
||||
else if (ClassUtl.Eq(c, BoolUtl.ClsRefType)) return BoolUtl.Cast(v) ? BoolUtl.TrueStr : BoolUtl.FalseStr; // always return "true" / "false"
|
||||
else if (ClassUtl.Eq(c, DoubleUtl.ClsRefType)) return DoubleUtl.ToStrLoose(DoubleUtl.Cast(v));
|
||||
else return v.toString();
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,10 @@ 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;
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class ShortUtl {
|
||||
public static final String ClsValName = "short";
|
||||
public static final Class<?> ClsRefType = Short.class;
|
||||
public static short Cast(Object obj) {try {return (Short)obj;} catch(Exception exc) {throw ErrUtl.NewCast(short.class, obj);}}
|
||||
}
|
||||
61
baselib/src/gplx/types/basics/utls/StringFormatLni.java
Normal file
61
baselib/src/gplx/types/basics/utls/StringFormatLni.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package gplx.types.basics.utls;
|
||||
import gplx.types.basics.strings.bfrs.StringBuilderLni;
|
||||
public class StringFormatLni {
|
||||
// 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) {
|
||||
// init vars
|
||||
int argsLen = args.length;
|
||||
if (argsLen == 0) return fmt; // nothing to format
|
||||
int fmtLen = StringLni.Len(fmt);
|
||||
|
||||
// loop vars
|
||||
int pos = 0; String argIdxStr = ""; boolean insideBrackets = false;
|
||||
StringBuilderLni bfr = new StringBuilderLni();
|
||||
while (pos < fmtLen) { // loop over every char; NOTE: UT8-SAFE b/c only checking for "{"; "}"
|
||||
char c = StringLni.CharAt(fmt, pos);
|
||||
if (insideBrackets) {
|
||||
if (c == FormatItmLhs) { // first FormatItmLhs is fake; add FormatItmLhs and whatever is in argIdxStr
|
||||
bfr.LniAddChar(FormatItmLhs);
|
||||
bfr.LniAdd(argIdxStr);
|
||||
argIdxStr = "";
|
||||
}
|
||||
else if (c == FormatItmRhs) { // itm completed
|
||||
int argsIdx = IntLni.ParseOr(argIdxStr, IntLni.MinValue);
|
||||
String itm = argsIdx != IntLni.MinValue && IntLni.Between(argsIdx, 0, argsLen - 1) // check (a) argsIdx is num; (b) argsIdx is in bounds
|
||||
? ObjectLni.ToStrOrNullMark(args[argsIdx]) // valid; add itm
|
||||
: FormatItmLhs + argIdxStr + FormatItmRhs; // not valid; just add String
|
||||
bfr.LniAdd(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.LniAddChar(c);
|
||||
else {
|
||||
char next = StringLni.CharAt(fmt, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
bfr.LniAddChar(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
insideBrackets = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.LniAddChar(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (StringLni.Len(argIdxStr) > 0) { // unclosed bracket; add FormatItmLhs and whatever is in argIdxStr; ex: "{0"
|
||||
bfr.LniAddChar(FormatItmLhs);
|
||||
bfr.LniAdd(argIdxStr);
|
||||
}
|
||||
return bfr.ToStr();
|
||||
}
|
||||
}
|
||||
64
baselib/src/gplx/types/basics/utls/StringLni.java
Normal file
64
baselib/src/gplx/types/basics/utls/StringLni.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package gplx.types.basics.utls;
|
||||
import java.util.Objects;
|
||||
public class StringLni {
|
||||
public static final Class<?> ClsRefType = String.class;
|
||||
public static final String ClsValName = "string";
|
||||
public static final int FindNone = -1;
|
||||
public static final int PosNeg1 = -1;
|
||||
public static final String
|
||||
Empty = "",
|
||||
Tab = "\t",
|
||||
Nl = "\n",
|
||||
CrLf = "\r\n",
|
||||
NullMark = "<<NULL>>";
|
||||
|
||||
public static final String[] AryEmpty = new String[0];
|
||||
public static final boolean Eq(String lhs, String rhs) {return Objects.equals(lhs, rhs);}
|
||||
public static final boolean EqNot(String lhs, String rhs) {return !Objects.equals(lhs, rhs);}
|
||||
public static final int Len(String s) {return s.length();}
|
||||
public static final boolean IsNullOrEmpty(String s) {return s == null || s.length() == 0;}
|
||||
public static final boolean IsNotNullOrEmpty(String s) {return s != null && s.length() > 0;}
|
||||
public static final boolean Has(String s, String find) {return s.indexOf(find) != FindNone;}
|
||||
public static final boolean HasAtBgn(String s, String v) {return s.startsWith(v);}
|
||||
public static final boolean HasAtEnd(String s, String v) {return s.endsWith(v);}
|
||||
public static final char CharAt(String s, int i) {return s.charAt(i);}
|
||||
public static final int CodePointAt(String s, int i) {return s.codePointAt(i);}
|
||||
public static final int FindFwd(String s, String find) {return s.indexOf(find);}
|
||||
public static final int FindFwd(String s, String find, int pos) {return s.indexOf(find, pos);}
|
||||
public static final int FindBwd(String s, String find) {return s.lastIndexOf(find);}
|
||||
public static final int FindBwd(String s, String find, int pos) {return s.lastIndexOf(find, pos);}
|
||||
public static final String Cast(Object v) {return (String)v;}
|
||||
public static final String CastOrNull(Object obj) {return obj instanceof String ? (String)obj : null;}
|
||||
public static final String Lower(String s) {return s.toLowerCase();}
|
||||
public static final String Upper(String s) {return s.toUpperCase();}
|
||||
public static final String CaseNormalize(boolean caseMatch, String s) {return caseMatch ? s : Lower(s);}
|
||||
public static final String Trim(String s) {return s.trim();}
|
||||
public static final String Mid(String s, int bgn) {return s.substring(bgn);}
|
||||
public static final String MidByLen(String s, int bgn, int len) {return s.substring(bgn, bgn + len);}
|
||||
public static final String Replace(String s, String find, String repl) {return s.replace(find, repl);}
|
||||
public static final String NewByBry(byte[] v) {return v == null ? null : new String(v);}
|
||||
public static final char[] ToCharAry(String s) {return s.toCharArray();}
|
||||
public static final String NewA7(byte[] v) {return v == null ? null : NewA7(v, 0, v.length);}
|
||||
public static final String NewA7(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "ASCII");
|
||||
}
|
||||
catch (Exception e) {throw ErrLni.NewMsg("unsupported encoding; bgn=" + bgn + " end=" + end);}
|
||||
}
|
||||
public static final String NewU8ByLen(byte[] v, int bgn, int len) {
|
||||
int vLen = v.length;
|
||||
if (bgn + len > vLen) len = vLen - bgn;
|
||||
return NewU8(v, bgn, bgn + len);
|
||||
}
|
||||
public static final String NewU8(byte[] v) {return v == null ? null : NewU8(v, 0, v.length);}
|
||||
public static final String NewU8(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
? null
|
||||
: new String(v, bgn, end - bgn, "UTF-8");
|
||||
}
|
||||
catch (Exception e) {throw ErrLni.NewMsg("unsupported encoding; bgn=" + bgn + " end=" + end);}
|
||||
}
|
||||
}
|
||||
329
baselib/src/gplx/types/basics/utls/StringUtl.java
Normal file
329
baselib/src/gplx/types/basics/utls/StringUtl.java
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
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.types.basics.utls;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.commons.lists.GfoListBase;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class StringUtl extends StringLni {
|
||||
public static boolean EqAny(String lhs, String... rhsAry) {
|
||||
for (int i = 0; i < rhsAry.length; i++)
|
||||
if (Eq(lhs, rhsAry[i])) return true;
|
||||
return false;
|
||||
}
|
||||
public static boolean In(String s, String... ary) {
|
||||
for (String itm : ary)
|
||||
if (Eq(s, itm)) return true;
|
||||
return false;
|
||||
}
|
||||
public static int Compare(String lhs, String rhs) {
|
||||
int compare = lhs.compareTo(rhs); // NOTE: should this do null check?
|
||||
// NOTE: need to do explicit comparison b/c String.compare returns magnitude of difference; "k".compareTo("a") == 10
|
||||
if (compare == CompareAbleUtl.Same) return CompareAbleUtl.Same;
|
||||
else if (compare < CompareAbleUtl.Same) return CompareAbleUtl.Less;
|
||||
else /* (compare > CompareAbleUtl.Same) */ return CompareAbleUtl.More;
|
||||
}
|
||||
public static int CompareIgnoreCase(String lhs, String rhs) {
|
||||
if (lhs == null && rhs != null) return CompareAbleUtl.Less;
|
||||
else if (lhs != null && rhs == null) return CompareAbleUtl.More;
|
||||
else if (lhs == null && rhs == null) return CompareAbleUtl.Same;
|
||||
else return lhs.compareToIgnoreCase(rhs);
|
||||
}
|
||||
public static int Count(String s, String part) {
|
||||
int count = 0, pos = -1; // -1 b/c first pass must be 0 (see pos + 1 below)
|
||||
do {
|
||||
pos = FindFwd(s, part, pos + 1);
|
||||
if (pos == FindNone) break;
|
||||
count++;
|
||||
} while (true);
|
||||
return count;
|
||||
}
|
||||
public static String LowerFirst(String s) {
|
||||
int len = Len(s); if (len == 0) return Empty;
|
||||
String char0 = Lower(MidByLen(s, 0, 1));
|
||||
return len == 1 ? char0 : char0 + Mid(s, 1);
|
||||
}
|
||||
public static String UpperFirst(String s) {
|
||||
int len = Len(s); if (len == 0) return Empty;
|
||||
String char0 = Upper(MidByLen(s, 0, 1));
|
||||
return len == 1 ? char0 : char0 + Mid(s, 1);
|
||||
}
|
||||
public static String Repeat(String s, int count) {
|
||||
if (count < 0) throw ErrUtl.NewArgs("count cannot be negative", "count", count, "s", s);
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (int i = 0; i < count; i++)
|
||||
sb.Add(s);
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String PadBgn(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, true);}
|
||||
public static String PadEnd(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, false);}
|
||||
public static String Pad(String s, int totalLen, String pad, boolean bgn) {
|
||||
int sLen = Len(s);
|
||||
int padLen = totalLen - sLen; if (padLen < 0) return s;
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
if (!bgn) sb.Add(s);
|
||||
for (int i = 0; i < padLen; i++)
|
||||
sb.Add(pad);
|
||||
if (bgn) sb.Add(s);
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String Mid(String s, int bgn, int end) {
|
||||
try {return MidByLen(s, bgn, end - bgn);}
|
||||
catch (Exception e) {
|
||||
int len = s == null ? 0 : Len(s);
|
||||
String msg = "";
|
||||
if (s == null) msg = "s is null";
|
||||
else if (bgn > end) msg = "@bgn > @end";
|
||||
else if (bgn < 0 || bgn >= len) msg = "@bgn is invalid";
|
||||
else if (end < 0 || end > len) msg = "@end is invalid";
|
||||
throw ErrUtl.NewArgs(msg, "s", s, "bgn", bgn, "end", end, "len", len);
|
||||
}
|
||||
}
|
||||
public static String MidByLenSafe(String s, int bgn, int len) {
|
||||
if (bgn + len >= Len(s)) len = Len(s) - bgn;
|
||||
return MidByLen(s, bgn, len);
|
||||
}
|
||||
public static String GetStrBefore(String s, String spr) {
|
||||
int sprPos = FindFwd(s, spr); if (sprPos == FindNone) throw ErrUtl.NewArgs("could not find spr", "s", s, "spr", spr);
|
||||
return Mid(s, 0, sprPos);
|
||||
}
|
||||
public static String GetStrAfter(String s, String spr) {
|
||||
int sprPos = FindFwd(s, spr); if (sprPos == FindNone) throw ErrUtl.NewArgs("could not find spr", "s", s, "spr", spr);
|
||||
return Mid(s, sprPos + 1);
|
||||
}
|
||||
public static String ExtractAfterBwd(String src, String dlm) {
|
||||
int dlm_pos = FindBwd(src, dlm); if (dlm_pos == FindNone) return Empty;
|
||||
int src_len = Len(src); if (dlm_pos == src_len - 1) return Empty;
|
||||
return Mid(src, dlm_pos + 1, src_len);
|
||||
}
|
||||
public static String LimitToFirst(String s, int len) {
|
||||
if (len < 0) throw ErrUtl.NewFmt("len cannot be < 0; len={0}", len);
|
||||
int sLen = Len(s); if (len > sLen) return s;
|
||||
return MidByLen(s, 0, len);
|
||||
}
|
||||
public static String DelBgn(String s, int count) {
|
||||
if (count < 0) throw ErrUtl.NewFmt("count cannot be < 0; count={0}", count);
|
||||
if (s == null) throw ErrUtl.NewNull("s");
|
||||
int len = Len(s); if (count > len) throw ErrUtl.NewArgs("count cannot be > @len", "count", count, "len", len);
|
||||
return Mid(s, count);
|
||||
}
|
||||
public static String DelEnd(String s, int count) {
|
||||
if (count < 0) throw ErrUtl.NewFmt("len cannot be < 0; len={0}", count);
|
||||
if (s == null) throw ErrUtl.NewNull("s");
|
||||
int len = Len(s); if (count > len) throw ErrUtl.NewArgs("count cannot be > len", "count", count, "len", len);
|
||||
return MidByLen(s, 0, len + -count);
|
||||
}
|
||||
public static String DelEndIf(String s, String find) {
|
||||
if (s == null) throw ErrUtl.NewNull("s");
|
||||
if (find == null) throw ErrUtl.NewNull("find");
|
||||
return HasAtEnd(s, find) ? MidByLen(s, 0, Len(s) - Len(find)) : s;
|
||||
}
|
||||
public static String Insert(String s, int pos, String toInsert) {
|
||||
if (pos < 0 || pos >= Len(s)) throw ErrUtl.NewArgs("insert failed; pos invalid", "pos", pos, "s", s, "toInsert", toInsert);
|
||||
return s.substring(0, pos) + toInsert + s.substring(pos);
|
||||
}
|
||||
public static String FormatOrEmptyStrIfNull(String fmt, Object arg) {return arg == null ? "" : Format(fmt, arg);}
|
||||
public static String Format(String fmt, Object... args) {return StringFormatLni.Format(fmt, args);}
|
||||
public static String Concat(char... ary) {return new String(ary);}
|
||||
public static String Concat(String s1, String s2, String s3) {return s1 + s2 + s3;}
|
||||
public static String Concat(String... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (String val : ary)
|
||||
sb.Add(val);
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatObjs(Object... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (Object val : ary)
|
||||
sb.AddObj(val);
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatWithObj(String spr, Object... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int len = ArrayUtl.Len(ary);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) sb.Add(spr);
|
||||
Object val = ary[i];
|
||||
sb.AddObj(ObjectUtl.ToStrOrEmpty(val));
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatWith(String spr, String... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i != 0) sb.Add(spr);
|
||||
sb.Add(ary[i]);
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatLinesNl(String... values) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (String val : values)
|
||||
sb.Add(val).Add("\n");
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatLinesNlSkipLast(String... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int ary_len = ary.length; int ary_end = ary_len - 1;
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
sb.Add(ary[i]);
|
||||
if (i != ary_end) sb.Add("\n");
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatLinesCrlf(String... values) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (String val : values)
|
||||
sb.Add(val).Add(CrLf);
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String ConcatLinesCrlfSkipLast(String... values) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (String val : values) {
|
||||
if (sb.Len() != 0) sb.Add(CrLf);
|
||||
sb.Add(val);
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String[] Ary(String... ary) {return ary;}
|
||||
public static String[] Ary(byte[]... ary) {
|
||||
if (ary == null) return AryEmpty;
|
||||
int ary_len = ary.length;
|
||||
String[] rv = new String[ary_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
byte[] itm = ary[i];
|
||||
rv[i] = itm == null ? null : NewU8(itm);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static String[] AryWoNull(String... ary) {
|
||||
GfoListBase<String> list = new GfoListBase<>();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
String itm = ary[i];
|
||||
if (itm == null) continue;
|
||||
list.Add(itm);
|
||||
}
|
||||
return list.ToAry(String.class);
|
||||
}
|
||||
public static String AryToStr(String... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (String s : ary)
|
||||
sb.Add(s).Add(";");
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static String[] AryAdd(String[]... arys) {
|
||||
if (arys == null) return AryEmpty;
|
||||
int arys_len = arys.length;
|
||||
int rv_len = 0;
|
||||
for (int i = 0; i < arys_len; i++) {
|
||||
String[] ary = arys[i];
|
||||
rv_len += ary.length;
|
||||
}
|
||||
int rv_idx = 0;
|
||||
String[] rv = new String[rv_len];
|
||||
for (int i = 0; i < arys_len; i++) {
|
||||
String[] ary = arys[i];
|
||||
int ary_len = ary.length;
|
||||
for (int j = 0; j < ary_len; j++)
|
||||
rv[rv_idx++] = ary[j];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static String[] AryFlatten(String[][] src_ary) {
|
||||
int trg_len = 0;
|
||||
int src_len = ArrayUtl.Len(src_ary);
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
String[] itm = src_ary[i];
|
||||
if (itm != null) trg_len += ArrayUtl.Len(itm);
|
||||
}
|
||||
String[] trg_ary = new String[trg_len];
|
||||
trg_len = 0;
|
||||
for (int i = 0; i < src_len; i++) {
|
||||
String[] itm = src_ary[i];
|
||||
if (itm == null) continue;
|
||||
int itm_len = ArrayUtl.Len(itm);
|
||||
for (int j = 0; j < itm_len; j++)
|
||||
trg_ary[trg_len++] = itm[j];
|
||||
}
|
||||
return trg_ary;
|
||||
}
|
||||
public static String[] Split(String raw, char dlm) {return Split(raw, dlm, false);}
|
||||
public static String[] Split(String raw, char dlm, boolean addEmptyIfDlmIsLast) {
|
||||
GfoListBase<String> list = new GfoListBase<>();
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int rawLen = Len(raw); char c = '\0';
|
||||
for (int i = 0; i < rawLen; i++) {
|
||||
c = CharAt(raw, i);
|
||||
if (c == dlm) {
|
||||
if (!addEmptyIfDlmIsLast && sb.Len() == 0 && i == rawLen - 1) {}
|
||||
else list.Add(sb.ToStrAndClear());
|
||||
}
|
||||
else
|
||||
sb.AddChar(c);
|
||||
}
|
||||
if (sb.Len() > 0)
|
||||
list.Add(sb.ToStrAndClear());
|
||||
return list.ToAry(String.class);
|
||||
}
|
||||
public static String[] Split(String s, String separator) {return SplitDo(s, separator, false);}
|
||||
public static String[] SplitLinesNl(String s) {return Split(s, Nl);}
|
||||
public static String[] SplitLinesCrLf(String s) {return Split(s, CrLf);}
|
||||
public static String[] SplitLinesAny(String s) {return SplitDo(s, Nl, true);}
|
||||
public static String[] SplitLang(String s, char c) {return s.split(Character.toString(c));}
|
||||
private static String[] SplitDo(String raw, String spr, boolean skipChar13) {
|
||||
if ( Eq(raw, "") // "".Split('a') return array with one member: ""
|
||||
|| Eq(spr, "")) // "a".Split('\0') returns array with one member: "a"
|
||||
return new String[] {raw};
|
||||
GfoListBase<String> list = new GfoListBase<>();
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int i = 0, sprPos = 0; boolean sprMatched = false; char spr0 = CharAt(spr, 0);
|
||||
int textLength = Len(raw); int sprLength = Len(spr);
|
||||
while (true) {
|
||||
if (sprMatched
|
||||
|| i == textLength) { // last pass; add whatever's in sb to list
|
||||
list.Add(sb.ToStrAndClear());
|
||||
if (sprMatched && i == textLength) list.Add(""); // if raw ends with spr and last pass, add emptyString as last
|
||||
sprMatched = false;
|
||||
}
|
||||
if (i == textLength) break;
|
||||
char c = CharAt(raw, i);
|
||||
if (skipChar13 && c == (char)13) {i++; continue;}
|
||||
if (c == spr0) { // matches first char of spr
|
||||
sprPos = 1;
|
||||
while (true) {
|
||||
if (sprPos == sprLength) { // made it to end, must be match
|
||||
sprMatched = true;
|
||||
break;
|
||||
}
|
||||
if (i + sprPos == textLength) break; // ran out of raw; handles partial match at end of String; ab+, +-
|
||||
if (CharAt(raw, i + sprPos) != CharAt(spr, sprPos)) break; // no match
|
||||
sprPos++;
|
||||
}
|
||||
if (!sprMatched) // add partial match to sb
|
||||
sb.Add(MidByLen(raw, i, sprPos));
|
||||
i += sprPos;
|
||||
}
|
||||
else { // no spr match; just add char, increment pos
|
||||
sb.AddChar(c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return list.ToAry(String.class);
|
||||
}
|
||||
public static String NewCharAry(char[] ary, int bgn, int len) {return new String(ary, bgn, len);}
|
||||
}
|
||||
@@ -13,17 +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.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;
|
||||
package gplx.types.basics.utls;
|
||||
public class TypeIds {
|
||||
public static final int // SERIALIZABLE.N
|
||||
IdObj = 0,
|
||||
@@ -41,23 +31,22 @@ public class TypeIds {
|
||||
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;
|
||||
if (ClassUtl.Eq(type, IntUtl.ClsRefType)) return IdInt;
|
||||
else if (ClassUtl.Eq(type, StringUtl.ClsRefType)) return IdStr;
|
||||
else if (ClassUtl.Eq(type, BryUtl.ClsRefType)) return IdBry;
|
||||
else if (ClassUtl.Eq(type, BoolUtl.ClsRefType)) return IdBool;
|
||||
else if (ClassUtl.Eq(type, ByteUtl.ClsRefType)) return IdByte;
|
||||
else if (ClassUtl.Eq(type, LongUtl.ClsRefType)) return IdLong;
|
||||
else if (ClassUtl.Eq(type, DoubleUtl.ClsRefType)) return IdDouble;
|
||||
else if (ClassUtl.Eq(type, FloatUtl.ClsRefType)) return IdFloat;
|
||||
else if (ClassUtl.Eq(type, ShortUtl.ClsRefType)) return IdShort;
|
||||
else if (ClassUtl.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;
|
||||
33
baselib/src/gplx/types/basics/wrappers/BoolRef.java
Normal file
33
baselib/src/gplx/types/basics/wrappers/BoolRef.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.basics.utls.BoolUtl;
|
||||
public class BoolRef {
|
||||
private BoolRef(boolean val) {
|
||||
this.val = val;
|
||||
}
|
||||
public boolean Val() {return val;} private boolean val;
|
||||
public boolean ValY() {return val;}
|
||||
public boolean ValN() {return !val;}
|
||||
public BoolRef ValSetY() {val = true; return this;}
|
||||
public BoolRef ValSetN() {val = false; return this;}
|
||||
public BoolRef ValSet(boolean v) {val = v; return this;}
|
||||
@Override public String toString() {return BoolUtl.ToStrLower(val);}
|
||||
|
||||
public static BoolRef NewN() {return New(false);}
|
||||
public static BoolRef NewY() {return New(true);}
|
||||
public static BoolRef New(boolean val) {return new BoolRef(val);}
|
||||
}
|
||||
24
baselib/src/gplx/types/basics/wrappers/BoolVal.java
Normal file
24
baselib/src/gplx/types/basics/wrappers/BoolVal.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
public class BoolVal {
|
||||
private BoolVal(int v) {val = v;} private final int val;
|
||||
public boolean Val() {return val == 1;}
|
||||
public static final BoolVal
|
||||
Null = new BoolVal(-1),
|
||||
False = new BoolVal( 0),
|
||||
True = new BoolVal( 1);
|
||||
}
|
||||
28
baselib/src/gplx/types/basics/wrappers/ByteRef.java
Normal file
28
baselib/src/gplx/types/basics/wrappers/ByteRef.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
public class ByteRef {
|
||||
private ByteRef(byte val) {this.val = val;}
|
||||
public byte Val() {return val;} private byte val;
|
||||
public ByteRef ValSet(byte v) {val = v; return this;}
|
||||
@Override public int hashCode() {return val;}
|
||||
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((ByteRef)obj).Val();}
|
||||
@Override public String toString() {return IntUtl.ToStr(val);}
|
||||
public static ByteRef NewZero() {return New(ByteUtl.Zero);}
|
||||
public static ByteRef New(byte val) {return new ByteRef(val);}
|
||||
}
|
||||
25
baselib/src/gplx/types/basics/wrappers/ByteVal.java
Normal file
25
baselib/src/gplx/types/basics/wrappers/ByteVal.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.basics.utls.ByteUtl;
|
||||
public class ByteVal {
|
||||
private ByteVal(byte val) {this.val = val;}
|
||||
public byte Val() {return val;} private byte val;
|
||||
@Override public String toString() {return ByteUtl.ToStr(val);}
|
||||
@Override public int hashCode() {return val;}
|
||||
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((ByteVal)obj).Val();}
|
||||
public static ByteVal New(byte val) {return new ByteVal(val);}
|
||||
}
|
||||
27
baselib/src/gplx/types/basics/wrappers/DoubleVal.java
Normal file
27
baselib/src/gplx/types/basics/wrappers/DoubleVal.java
Normal file
@@ -0,0 +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.types.basics.wrappers;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.basics.utls.DoubleUtl;
|
||||
public class DoubleVal implements CompareAble<DoubleVal> {
|
||||
private DoubleVal(double val) {this.val = val;}
|
||||
public double Val() {return val;} private final double val;
|
||||
@Override public String toString() {return DoubleUtl.ToStr(val);}
|
||||
@Override public int hashCode() {return (int)val;}
|
||||
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((DoubleVal)obj).Val();}
|
||||
@Override public int compareTo(DoubleVal comp) {return DoubleUtl.Compare(val, comp.val);}
|
||||
public static DoubleVal New(double val) {return new DoubleVal(val);}
|
||||
}
|
||||
34
baselib/src/gplx/types/basics/wrappers/IntRef.java
Normal file
34
baselib/src/gplx/types/basics/wrappers/IntRef.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
public class IntRef {
|
||||
private IntRef(int val) {this.val = val;}
|
||||
public int Val() {return val;} public IntRef ValSet(int v) {val = v; return this;} private int val;
|
||||
public int ValAddOne() {val++; return val;}
|
||||
public int ValAddPost() {return val++;}
|
||||
public int ValAdd(int v) {val += v; return val;}
|
||||
public IntRef ValSetZero() {val = 0; return this;}
|
||||
public IntRef ValSetNeg1() {val = -1; return this;}
|
||||
|
||||
@Override public String toString() {return IntUtl.ToStr(val);}
|
||||
@Override public int hashCode() {return val;}
|
||||
@Override public boolean equals(Object obj) {return val == ((IntRef)obj).Val();}
|
||||
|
||||
public static IntRef NewNeg1() {return new IntRef(-1);}
|
||||
public static IntRef NewZero() {return new IntRef(0);}
|
||||
public static IntRef New(int val) {return new IntRef(val);}
|
||||
}
|
||||
26
baselib/src/gplx/types/basics/wrappers/IntVal.java
Normal file
26
baselib/src/gplx/types/basics/wrappers/IntVal.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
public class IntVal implements CompareAble<IntVal> {
|
||||
public IntVal(int val) {this.val = val;}
|
||||
public int Val() {return val;} private final int val;
|
||||
@Override public String toString() {return IntUtl.ToStr(val);}
|
||||
@Override public int hashCode() {return val;}
|
||||
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((IntVal)obj).Val();}
|
||||
@Override public int compareTo(IntVal v) {return IntUtl.Compare(val, v.val);}
|
||||
}
|
||||
21
baselib/src/gplx/types/basics/wrappers/ObjRef.java
Normal file
21
baselib/src/gplx/types/basics/wrappers/ObjRef.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
public class ObjRef {
|
||||
public Object Val() {return val;} public ObjRef ValSet(Object v) {val = v; return this;} private Object val;
|
||||
@Override public String toString() {return ObjectUtl.ToStrOrNull(val);}
|
||||
}
|
||||
26
baselib/src/gplx/types/basics/wrappers/StringRef.java
Normal file
26
baselib/src/gplx/types/basics/wrappers/StringRef.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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.types.basics.wrappers;
|
||||
public class StringRef {
|
||||
private StringRef(String val) {this.val = val;}
|
||||
public String Val() {return val;} public StringRef ValSet(String v) {val = v; return this;} private String val;
|
||||
public StringRef ValSetNull() {return ValSet(null);}
|
||||
@Override public String toString() {return val;}
|
||||
|
||||
public static StringRef NewEmpty() {return New("");}
|
||||
public static StringRef NewNull() {return New(null);}
|
||||
public static StringRef New(String val) {return new StringRef(val);}
|
||||
}
|
||||
27
baselib/src/gplx/types/basics/wrappers/StringVal.java
Normal file
27
baselib/src/gplx/types/basics/wrappers/StringVal.java
Normal file
@@ -0,0 +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.types.basics.wrappers;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
public class StringVal implements CompareAble<StringVal> {
|
||||
private StringVal(String val) {this.val = val;}
|
||||
public String Val() {return val;} private final String val;
|
||||
@Override public String toString() {return val;}
|
||||
@Override public int compareTo(StringVal comp) {
|
||||
return StringUtl.Compare(val, comp.val);
|
||||
}
|
||||
public static StringVal New(String val) {return new StringVal(val);}
|
||||
}
|
||||
159
baselib/src/gplx/types/commons/GfoDate.java
Normal file
159
baselib/src/gplx/types/commons/GfoDate.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
public class GfoDate implements CompareAble<GfoDate> {
|
||||
GfoDate(Calendar under) {this.under = under;}
|
||||
GfoDate(int year, int month, int day, int hour, int minute, int second, int frac) {
|
||||
this.under = NewCalendar(year, month, day, hour, minute, second, frac, IntUtl.MinValue, null);
|
||||
}
|
||||
GfoDate(int year, int month, int day, int hour, int minute, int second, int frac, int tzOffset, byte[] tzAbrv) {
|
||||
this.under = NewCalendar(year, month, day, hour, minute, second, frac, tzOffset, tzAbrv);
|
||||
}
|
||||
private Calendar NewCalendar(int year, int month, int day, int hour, int minute, int second, int frac, int tzOffset, byte[] tzAbrv) {
|
||||
GregorianCalendar calendar = new GregorianCalendar(year, month - MonthBase0Adj, day, hour, minute, second);
|
||||
calendar.set(Calendar.MILLISECOND, frac);
|
||||
|
||||
if (tzOffset == IntUtl.MinValue) {
|
||||
return calendar;
|
||||
}
|
||||
else {
|
||||
long msFromEpochGmt = calendar.getTime().getTime();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(msFromEpochGmt - tzOffset * 1000);
|
||||
return cal;
|
||||
}
|
||||
}
|
||||
public Calendar UnderCalendar() {return under;} private final Calendar under;
|
||||
public int Year() {return under.get(Calendar.YEAR);}
|
||||
public int Month() {return under.get(Calendar.MONTH) + MonthBase0Adj;}
|
||||
public int Day() {return under.get(Calendar.DAY_OF_MONTH);}
|
||||
public int Hour() {return under.get(Calendar.HOUR_OF_DAY);}
|
||||
public int Minute() {return under.get(Calendar.MINUTE);}
|
||||
public int Second() {return under.get(Calendar.SECOND);}
|
||||
public int Frac() {return under.get(Calendar.MILLISECOND);}
|
||||
public int DayOfWeek() {return under.get(Calendar.DAY_OF_WEEK) - WeekBase0Adj;}
|
||||
public int DayOfYear() {return under.get(Calendar.DAY_OF_YEAR);}
|
||||
public int WeekOfYear() {return under.get(Calendar.WEEK_OF_YEAR);}
|
||||
public String TimezoneId() {
|
||||
return "UTC"; // under.getTimeZone().getID(); // NOTE: timezone is always UTC, unless overridden by tests
|
||||
}
|
||||
public static int TimezoneOffsetTest = IntUtl.MinValue;
|
||||
public int TimezoneOffset() {
|
||||
return TimezoneOffsetTest == IntUtl.MinValue // Timezone_offset_test not overridden
|
||||
? 0
|
||||
: TimezoneOffsetTest;
|
||||
}
|
||||
public long TimestampUnix() {
|
||||
long offsetFromUTC = under.getTimeZone().getOffset(0);
|
||||
boolean dst = TimeZone.getDefault().inDaylightTime(under.getTime());
|
||||
long dstAdj = dst ? 3600000 : 0;
|
||||
return (under.getTimeInMillis() + offsetFromUTC + dstAdj) / 1000;
|
||||
}
|
||||
public int Segment(int idx) {
|
||||
switch (idx) {
|
||||
case GfoDateUtl.SegIdxYear: return this.Year();
|
||||
case GfoDateUtl.SegIdxMonth: return this.Month();
|
||||
case GfoDateUtl.SegIdxDay: return this.Day();
|
||||
case GfoDateUtl.SegIdxHour: return this.Hour();
|
||||
case GfoDateUtl.SegIdxMinute: return this.Minute();
|
||||
case GfoDateUtl.SegIdxSecond: return this.Second();
|
||||
case GfoDateUtl.SegIdxFrac: return this.Frac();
|
||||
case GfoDateUtl.SegIdxDayOfWeek: return this.DayOfWeek();
|
||||
case GfoDateUtl.SegIdxWeekOfYear: return this.WeekOfYear();
|
||||
case GfoDateUtl.SegIdxDayOfYear: return this.DayOfYear();
|
||||
default: throw ErrUtl.NewUnhandled(idx);
|
||||
}
|
||||
}
|
||||
public GfoDate AddFrac(int val) {return Add(Calendar.MILLISECOND, val);}
|
||||
public GfoDate AddSecond(int val) {return Add(Calendar.SECOND, val);}
|
||||
public GfoDate AddMinute(int val) {return Add(Calendar.MINUTE, val);}
|
||||
public GfoDate AddHour(int val) {return Add(Calendar.HOUR, val);}
|
||||
public GfoDate AddDay(int val) {return Add(Calendar.DAY_OF_MONTH, val);}
|
||||
public GfoDate AddMonth(int val) {return Add(Calendar.MONTH, val);}
|
||||
public GfoDate AddYear(int val) {return Add(Calendar.YEAR, val);}
|
||||
private GfoDate Add(int fld, int val) {
|
||||
Calendar clone = (Calendar)under.clone();
|
||||
clone.add(fld, val);
|
||||
return new GfoDate(clone);
|
||||
}
|
||||
public int DiffDays(GfoDate prv) {
|
||||
long diff = this.under.getTimeInMillis() - prv.under.getTimeInMillis();
|
||||
return (int)(diff / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
public GfoTimeSpan Diff(GfoDate prv) {
|
||||
long diff = this.under.getTimeInMillis() - prv.under.getTimeInMillis();
|
||||
return GfoTimeSpanUtl.NewFracs(diff);
|
||||
}
|
||||
public GfoDate ToUtc() {return ToDate(true);}
|
||||
public GfoDate ToLocal() {return ToDate(false);}
|
||||
private GfoDate ToDate(boolean isUtc) {
|
||||
java.util.Date date = under.getTime();
|
||||
java.util.TimeZone tz = under.getTimeZone();
|
||||
long msFromEpochGmt = date.getTime();
|
||||
int offsetFromUTC = tz.getOffset(msFromEpochGmt);
|
||||
Calendar gmtCal = Calendar.getInstance();
|
||||
int offset = isUtc ? -offsetFromUTC : offsetFromUTC;
|
||||
gmtCal.setTimeInMillis(msFromEpochGmt + offset);
|
||||
return new GfoDate(gmtCal);
|
||||
}
|
||||
public int[] ToSegAry() {
|
||||
int[] rv = new int[7];
|
||||
rv[GfoDateUtl.SegIdxYear] = this.Year();
|
||||
rv[GfoDateUtl.SegIdxMonth] = this.Month();
|
||||
rv[GfoDateUtl.SegIdxDay] = this.Day();
|
||||
rv[GfoDateUtl.SegIdxHour] = this.Hour();
|
||||
rv[GfoDateUtl.SegIdxMinute] = this.Minute();
|
||||
rv[GfoDateUtl.SegIdxSecond] = this.Second();
|
||||
rv[GfoDateUtl.SegIdxFrac] = this.Frac();
|
||||
return rv;
|
||||
}
|
||||
public String ToStrGplx() {return ToStrFmt("yyyyMMdd_HHmmss.fff");}
|
||||
public String ToStrGplxLong() {return ToStrFmt("yyyy-MM-dd HH:mm:ss.fff");}
|
||||
public String ToStrFmt_HHmmss() {return ToStrFmt("HH:mm:ss");}
|
||||
public String ToStrFmt_HHmm() {return ToStrFmt("HH:mm");}
|
||||
public String ToStrFmt_yyyyMMdd() {return ToStrFmt("yyyy-MM-dd");}
|
||||
public String ToStrFmt_yyyyMMdd_HHmmss() {return ToStrFmt("yyyyMMdd_HHmmss");}
|
||||
public String ToStrFmt_yyyyMMdd_HHmmss_fff() {return ToStrFmt("yyyyMMdd_HHmmss.fff");}
|
||||
public String ToStrFmt_yyyy_MM_dd_HH_mm() {return ToStrFmt("yyyy-MM-dd HH:mm");}
|
||||
public String ToStrFmt_yyyy_MM_dd_HH_mm_ss() {return ToStrFmt("yyyy-MM-dd HH:mm:ss");}
|
||||
public String ToStrFmtIso8561() {return ToStrFmt("yyyy-MM-dd HH:mm:ss");}
|
||||
public String ToStrFmtIso8561WithTz() {return ToStrFmt("yyyy-MM-dd'T'HH:mm:ss'Z'");}
|
||||
public String ToStrFmt(String fmt) {
|
||||
fmt = fmt.replace("f", "S");
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
|
||||
return sdf.format(under.getTime());
|
||||
}
|
||||
public String ToStrTz() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("Z");
|
||||
String timeZone = sdf.format(under.getTime());
|
||||
return StringUtl.Mid(timeZone, 0, 3) + ":" + StringUtl.Mid(timeZone, 3, StringUtl.Len(timeZone));
|
||||
}
|
||||
public boolean Eq(GfoDate v) {GfoDate comp = v; return ObjectUtl.Eq(under.getTimeInMillis(), comp.under.getTimeInMillis());}
|
||||
@Override public int compareTo(GfoDate comp) {return under.compareTo(comp.under);}
|
||||
@Override public String toString() {return ToStrGplxLong();}
|
||||
private static final int
|
||||
MonthBase0Adj = 1,
|
||||
WeekBase0Adj = 1; // -1 : Base0; NOTE: dotnet/php is also Sunday=0
|
||||
}
|
||||
40
baselib/src/gplx/types/commons/GfoDateNow.java
Normal file
40
baselib/src/gplx/types/commons/GfoDateNow.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import java.util.GregorianCalendar;
|
||||
public class GfoDateNow {
|
||||
private static final GfoDate dflt = GfoDateUtl.ParseGplx("2001-01-01 00:00:00.000");
|
||||
public static GfoDate DfltAddMin(int v) {return dflt.AddMinute(v);}
|
||||
public static void AutoincrementSetN() {autoincrement = false;} private static boolean autoincrement = true;
|
||||
public static void ManualSet(GfoDate v) {manual = v;} private static GfoDate manual;
|
||||
public static void ManualSetY() {manual = dflt;}
|
||||
public static void ManualSetN() {
|
||||
manual = null;
|
||||
autoincrement = true;
|
||||
}
|
||||
public static void ManualSetAndFreeze(GfoDate v) {
|
||||
manual = v;
|
||||
autoincrement = false;
|
||||
}
|
||||
public static GfoDate Get() {
|
||||
if (manual == null)
|
||||
return new GfoDate(new GregorianCalendar());
|
||||
GfoDate rv = manual;
|
||||
if (autoincrement) manual = rv.AddMinute(1); // simulate passage of time by increasing manual by 1 minute with each call
|
||||
return rv;
|
||||
}
|
||||
public static GfoDate GetForce() {return new GfoDate(new GregorianCalendar());} // ignore manual and force get of real time
|
||||
}
|
||||
76
baselib/src/gplx/types/commons/GfoDateParser.java
Normal file
76
baselib/src/gplx/types/commons/GfoDateParser.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
public class GfoDateParser {
|
||||
private static int[] MaxLens = new int[]
|
||||
{ 4 // y
|
||||
, 2 // M
|
||||
, 2 // d
|
||||
, 2 // H
|
||||
, 2 // m
|
||||
, 2 // s
|
||||
, 3 // S (fracs)
|
||||
, 0 // (TimeZone)
|
||||
};
|
||||
private final IntBldr intBldr = new IntBldr(4);
|
||||
public int[] ParseIso8651Like(String raw_str) {
|
||||
int[] tmpRv = new int[7];
|
||||
ParseIso8651Like(tmpRv, raw_str);
|
||||
return tmpRv;
|
||||
}
|
||||
public void ParseIso8651Like(int[] rv, String rawStr) {
|
||||
byte[] rawBry = BryUtl.NewU8(rawStr);
|
||||
ParseIso8651Like(rv, rawBry, 0, rawBry.length);
|
||||
}
|
||||
public void ParseIso8651Like(int[] rv, byte[] src, int bgn, int end) {
|
||||
/*
|
||||
1981-04-05T14:30:30.000-05:00 ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
|
||||
1981.04.05 14.30.30.000-05.00 ISO 8601 loose
|
||||
99991231_235959.999 gplx
|
||||
yyyy-MM-ddTHH:mm:ss.fffzzzz Format String
|
||||
*/
|
||||
// clear array
|
||||
int rvLen = rv.length;
|
||||
for (int i = 0; i < rvLen; i++)
|
||||
rv[i] = 0;
|
||||
|
||||
int pos = bgn, rvIdx = 0, intLen = 0, maxLen = MaxLens[rvIdx];
|
||||
while (true) {
|
||||
int intVal = -1;
|
||||
byte b = pos < end ? src[pos] : AsciiByte.Null;
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
intVal = b - AsciiByte.Num0; // convert ascii to val; EX: 49 -> 1
|
||||
intLen = intBldr.Add(intVal);
|
||||
break;
|
||||
}
|
||||
if ( (intVal == -1 && intLen > 0) // char is not number && number exists (ignore consecutive delimiters: EX: "1981 01")
|
||||
|| intLen == maxLen) { // maxLen reached; necessary for gplxFormat
|
||||
rv[rvIdx++] = intBldr.ToIntAndClear();
|
||||
if (rvIdx == 7) // past frac; break;
|
||||
break;
|
||||
intLen = 0;
|
||||
maxLen = MaxLens[rvIdx];
|
||||
}
|
||||
if (pos == end)
|
||||
break;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
118
baselib/src/gplx/types/commons/GfoDateUtl.java
Normal file
118
baselib/src/gplx/types/commons/GfoDateUtl.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
public class GfoDateUtl {
|
||||
public static final String ClsRefName = "Date";
|
||||
public static final Class<?> ClsRefType = GfoDate.class;
|
||||
public static final GfoDate
|
||||
MinValue = new GfoDate( 1, 1, 1, 0, 0, 0, 0),
|
||||
MaxValue = new GfoDate(9999, 12, 31, 23, 59, 59, 999);
|
||||
private static int [] DaysInMonthAry = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
public static int DaysInMonth(int year, int month) {
|
||||
int rv = DaysInMonthAry[month - IntUtl.Base1];
|
||||
if (rv == 28 && IsLeapYear(year)) rv = 29;
|
||||
return rv;
|
||||
}
|
||||
public static boolean IsLeapYear(int year) {
|
||||
if (year % 4 != 0) return false;
|
||||
else if (year % 400 == 0) return true;
|
||||
else if (year % 100 == 0) return false;
|
||||
else return true;
|
||||
}
|
||||
public static GfoDate New(int year, int month, int day, int hour, int minute, int second, int frac) {return new GfoDate(year, month, day, hour, minute, second, frac);}
|
||||
public static GfoDate NewBySegs(int[] ary) {
|
||||
int ary_len = ary.length;
|
||||
int y = ary_len > 0 ? ary[0] : 1;
|
||||
int M = ary_len > 1 ? ary[1] : 1;
|
||||
int d = ary_len > 2 ? ary[2] : 1;
|
||||
int h = ary_len > 3 ? ary[3] : 0;
|
||||
int m = ary_len > 4 ? ary[4] : 0;
|
||||
int s = ary_len > 5 ? ary[5] : 0;
|
||||
int f = ary_len > 6 ? ary[6] : 0;
|
||||
return new GfoDate(y, M, d, h, m, s, f);
|
||||
}
|
||||
public static GfoDate NewDateByBits(int y, int m, int d, int h, int i, int s, int us, int tzOffset, byte[] tzAbrv) {
|
||||
return new GfoDate(y, m, d, h, i, s, us/1000, tzOffset, tzAbrv);
|
||||
}
|
||||
public static GfoDate NewByCalendar(GregorianCalendar v) {return new GfoDate(v);}
|
||||
public static GfoDate NewUnixtimeUtcSeconds(long v) {return NewUnixtimeUtcMs(v * 1000);}
|
||||
public static GfoDate NewUnixtimeUtcMs(long v) {return NewUnixtimeLclMs(v).ToUtc();}
|
||||
public static GfoDate NewUnixtimeLclMs(long v) {
|
||||
GregorianCalendar c = new GregorianCalendar();
|
||||
c.setTimeInMillis(v);
|
||||
return new GfoDate(c);
|
||||
}
|
||||
public static GfoDate NewByDb(Object v) {
|
||||
if (v instanceof String) {
|
||||
return GfoDateUtl.ParseIso8561((String)v);
|
||||
}
|
||||
Timestamp ts = (Timestamp)v;
|
||||
Calendar gc = Calendar.getInstance();
|
||||
gc.setTimeInMillis(ts.getTime());
|
||||
return new GfoDate(gc);
|
||||
}
|
||||
public static GfoDate Parse(String raw) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat();
|
||||
Date d;
|
||||
try {d = sdf.parse(raw);}
|
||||
catch (ParseException e) {throw ErrUtl.NewArgs("failed to parse to DateAdp", "raw", raw);}
|
||||
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
|
||||
cal.setTime(d);
|
||||
return NewByCalendar(cal);
|
||||
}
|
||||
public static GfoDate ParseFmtOr(String raw, String fmt, GfoDate or) {
|
||||
try {return ParseFmt(raw, fmt);}
|
||||
catch (Exception e) {return or;}
|
||||
}
|
||||
public static GfoDate ParseFmt(String raw, String fmt) {
|
||||
fmt = fmt.replace('t', 'a'); // AM/PM
|
||||
fmt = fmt.replace('f', 'S'); // milliseconds
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(fmt, Locale.US);
|
||||
Date d = null;
|
||||
try {d = sdf.parse(raw);}
|
||||
catch (ParseException e) {throw ErrUtl.NewArgs("failed to parse to DateAdp", "raw", raw, "fmt", fmt);}
|
||||
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
|
||||
cal.setTime(d);
|
||||
return NewByCalendar(cal);
|
||||
}
|
||||
public static GfoDate ParseIso8561Or(String raw, GfoDate or) {
|
||||
try {return ParseIso8561(raw);}
|
||||
catch (Exception e) {return or;}
|
||||
}
|
||||
public static GfoDate ParseGplx(String raw) {return ParseIso8561(raw);} // NOTE: for now, same as ParseIso8561
|
||||
public static GfoDate ParseIso8561(String raw) {
|
||||
GfoDateParser dateParser = new GfoDateParser();
|
||||
int[] ary = dateParser.ParseIso8651Like(raw);
|
||||
if (ary[1] < 1 || ary[1] > 12) return GfoDateUtl.MinValue; // guard against invalid month
|
||||
if (ary[2] < 1 || ary[2] > 31) return GfoDateUtl.MinValue; // guard against invalid day
|
||||
return new GfoDate(ary[0], ary[1], ary[2], ary[3], ary[4], ary[5], ary[6]);
|
||||
}
|
||||
public static final int
|
||||
SegIdxYear = 0, SegIdxMonth = 1, SegIdxDay = 2, SegIdxHour = 3, SegIdxMinute = 4, SegIdxSecond = 5,
|
||||
SegIdxFrac = 6, SegIdxDayOfWeek = 7, SegIdxWeekOfYear = 8, SegIdxDayOfYear = 9, SegIdxTz = 10, SegIdxMaxLen = 11;
|
||||
public static final String
|
||||
FmtIso8561DateTime = "yyyy-MM-dd HH:mm:ss",
|
||||
Fmt_yyyyMMdd = "yyyyMMdd";
|
||||
}
|
||||
95
baselib/src/gplx/types/commons/GfoDecimal.java
Normal file
95
baselib/src/gplx/types/commons/GfoDecimal.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.basics.utls.MathUtl;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
public class GfoDecimal implements CompareAble<GfoDecimal> {
|
||||
private final BigDecimal under;
|
||||
GfoDecimal(BigDecimal v) {this.under = v;}
|
||||
GfoDecimal(int v) {this.under = new BigDecimal(v);}
|
||||
public Object Under() {return under;}
|
||||
public BigDecimal UnderAsNative() {return under;}
|
||||
public int Frac1000() {return (int)(under.movePointRight(3).floatValue() % 1000);}
|
||||
public GfoDecimal Floor() {return GfoDecimalUtl.NewByInt(this.ToInt());}
|
||||
public GfoDecimal Add(GfoDecimal v) {return new GfoDecimal(under.add(v.under, GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Subtract(GfoDecimal v) {return new GfoDecimal(under.subtract(v.under, GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Multiply(GfoDecimal v) {return new GfoDecimal(under.multiply(v.under));}
|
||||
public GfoDecimal Multiply(long v) {return new GfoDecimal(under.multiply(new BigDecimal(v)));}
|
||||
public GfoDecimal Divide(GfoDecimal v) {return new GfoDecimal(under.divide(v.under, GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Mod(GfoDecimal v) {return new GfoDecimal(under.remainder(v.under, GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Abs() {return new GfoDecimal(under.abs(GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Pow(int v) {return new GfoDecimal(under.pow(v, GfoDecimalUtl.ContextGfoDefault));}
|
||||
public GfoDecimal Sqrt() {return new GfoDecimal(new BigDecimal(MathUtl.Sqrt(under.doubleValue())));}
|
||||
public GfoDecimal Truncate() {return new GfoDecimal(under.intValue());}
|
||||
public GfoDecimal RoundNative(int v) {return new GfoDecimal(under.setScale(v, RoundingMode.HALF_UP));}
|
||||
public GfoDecimal Round(int v) {
|
||||
BigDecimal new_val = null;
|
||||
if (v > 0) {
|
||||
new_val = under.setScale(v, RoundingMode.HALF_UP);
|
||||
}
|
||||
else {
|
||||
int actl_places = under.precision() - under.scale();
|
||||
int reqd_places = -v;
|
||||
if (reqd_places < actl_places)
|
||||
new_val = under.round(new java.math.MathContext(actl_places - reqd_places, RoundingMode.HALF_UP));
|
||||
else if (reqd_places == actl_places) {
|
||||
int base_10 = (int)MathUtl.Pow(10, reqd_places - 1);
|
||||
if (under.intValue() / base_10 < 5)
|
||||
new_val = BigDecimal.ZERO;
|
||||
else
|
||||
new_val = new BigDecimal(MathUtl.Pow(10, reqd_places));
|
||||
}
|
||||
else
|
||||
new_val = BigDecimal.ZERO;
|
||||
}
|
||||
return new GfoDecimal(new_val);
|
||||
}
|
||||
public GfoDecimal RoundToDefaultPrecision() {return new GfoDecimal(under.round(GfoDecimalUtl.ContextGfoDefault));}
|
||||
public boolean CompGte(GfoDecimal v) {return under.doubleValue() >= v.under.doubleValue();}
|
||||
public boolean CompLte(GfoDecimal v) {return under.doubleValue() <= v.under.doubleValue();}
|
||||
public boolean CompLte(int v) {return under.doubleValue() <= v;}
|
||||
public boolean CompGt(GfoDecimal v) {return under.doubleValue() > v.under.doubleValue();}
|
||||
public boolean CompGt(int v) {return under.doubleValue() > v;}
|
||||
public boolean CompLt(GfoDecimal v) {return under.doubleValue() < v.under.doubleValue();}
|
||||
public boolean CompLt(int v) {return under.doubleValue() < v;}
|
||||
public boolean Eq(GfoDecimal v) {return v.under.doubleValue() == under.doubleValue();}
|
||||
public boolean Eq(int v) {return under.doubleValue() == v;}
|
||||
public int ToInt() {return (int)under.doubleValue();}
|
||||
public long ToLong() {return (long)under.doubleValue();}
|
||||
public long ToLongMult1000() {return under.movePointRight(3).longValue();}
|
||||
public double ToDouble() {return under.doubleValue();}
|
||||
public String ToStr(String fmt) {return new DecimalFormat(fmt).format(under);}
|
||||
public String ToStr() {
|
||||
BigDecimal tmp = under;
|
||||
int tmp_scale = tmp.scale();
|
||||
if (tmp_scale <= -14) // NOTE: if large number, call .toString which will return exponential notaion (1E##) instead of literal (1000....); 14 matches MW code; DATE:2015-04-10
|
||||
return tmp.toString();
|
||||
|
||||
if (tmp_scale > 14) // NOTE: if small number, round down to remove excessive zeroes; 14 matches PHP/C# values more closely; RoundingMode.Down for same reason; see E, Pi tests
|
||||
tmp = tmp.setScale(14, RoundingMode.DOWN);
|
||||
return tmp
|
||||
.stripTrailingZeros() // NOTE: stripTrailingZeros for exp tests; EX: 120.0 -> 120; 0.01200000000000 -> .012
|
||||
.toPlainString(); // NOTE: toPlainString b/c stripTrailingZeros now converts 120 to 1.2E+2 (and any other value that is a multiple of 10)
|
||||
}
|
||||
@Override public int compareTo(GfoDecimal comp) {return under.compareTo(comp.under);}
|
||||
@Override public String toString() {return under.toString();}
|
||||
@Override public boolean equals(Object obj) {GfoDecimal comp = (GfoDecimal)obj; return ObjectUtl.Eq(under, comp.under);}
|
||||
@Override public int hashCode() {return under.hashCode();}
|
||||
}
|
||||
88
baselib/src/gplx/types/commons/GfoDecimalUtl.java
Normal file
88
baselib/src/gplx/types/commons/GfoDecimalUtl.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.types.commons;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.basics.utls.FloatUtl;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
public class GfoDecimalUtl {
|
||||
public static final String Cls_val_name = "decimal";
|
||||
public static final Class<?> Cls_ref_type = GfoDecimal.class;
|
||||
public static final GfoDecimal
|
||||
Zero = new GfoDecimal(0),
|
||||
One = new GfoDecimal(1),
|
||||
Neg1 = new GfoDecimal(-1),
|
||||
E = NewByDouble(Math.E),
|
||||
PI = NewByDouble(Math.PI);
|
||||
public static GfoDecimal CastOrNull(Object obj) {return obj instanceof GfoDecimal ? (GfoDecimal)obj : null;}
|
||||
public static GfoDecimal NewByBase1000(long v) {return NewByDivide(v, 1000);}
|
||||
public static GfoDecimal NewByParts1000(long num, int frc) {return NewByDivide((num * (1000)) + frc, 1000);}
|
||||
public static GfoDecimal NewByDivideSafe(long lhs, long rhs) {return rhs == 0 ? Zero : NewByDivide(lhs, rhs);}
|
||||
public static GfoDecimal NewByDivide(long lhs, long rhs) {
|
||||
return new GfoDecimal(new BigDecimal(lhs).divide(new BigDecimal(rhs), ContextGfoDefault));
|
||||
}
|
||||
public static GfoDecimal NewByInt(int v) {return new GfoDecimal(new BigDecimal(v));}
|
||||
public static GfoDecimal NewByLong(long v) {return new GfoDecimal(new BigDecimal(v));}
|
||||
public static GfoDecimal NewByFloat(float v) {return new GfoDecimal(new BigDecimal(v));}
|
||||
public static GfoDecimal NewByDouble(double v) {return new GfoDecimal(new BigDecimal(v));}
|
||||
public static GfoDecimal NewByDoubleThruStr(double v) {return new GfoDecimal(BigDecimal.valueOf(v));}
|
||||
public static GfoDecimal NewDb(Object v) {return new GfoDecimal((BigDecimal)v);}
|
||||
public static GfoDecimal NewByPow10(int v) {return new GfoDecimal(new BigDecimal(1).scaleByPowerOfTen(v));}
|
||||
public static GfoDecimal NewByParts(long num, int frc) {
|
||||
int pow10 = ToPow10(frc);
|
||||
return NewByDivide((num * (pow10)) + frc, pow10);
|
||||
}
|
||||
private static int ToPow10(int v) {
|
||||
if (v > -1 && v < 10) return 10;
|
||||
else if (v > 9 && v < 100) return 100;
|
||||
else if (v > 99 && v < 1000) return 1000;
|
||||
else if (v > 999 && v < 10000) return 10000;
|
||||
else if (v > 9999 && v < 100000) return 100000;
|
||||
else if (v > 99999 && v < 1000000) return 1000000;
|
||||
else if (v > 999999 && v < 10000000) return 10000000;
|
||||
else if (v > 9999999 && v < 100000000) return 100000000;
|
||||
else if (v > 99999999 && v < 1000000000) return 1000000000;
|
||||
else throw ErrUtl.NewArgs("value must be between 0 and 1 billion", "v", v);
|
||||
}
|
||||
public static GfoDecimal Parse(String raw) {
|
||||
try {
|
||||
DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US); // always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
|
||||
nf.setParseBigDecimal(true);
|
||||
// 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
|
||||
if (raw.contains("e")) {
|
||||
raw = raw.replace("e", "E");
|
||||
}
|
||||
// 2021-02-13|ISSUE#:838|Parse '.' as '0.'; PAGE:en.w:2019_FIVB_Volleyball_Women%27s_Challenger_Cup#Pool_A
|
||||
if (raw.startsWith(".")) {
|
||||
raw = "0" + raw;
|
||||
}
|
||||
BigDecimal bd = (BigDecimal)nf.parse(raw);
|
||||
return new GfoDecimal(bd);
|
||||
} catch (ParseException e) {
|
||||
throw ErrUtl.NewArgs("Decimal_adp_", "parse to decimal failed", "raw", raw);
|
||||
}
|
||||
}
|
||||
public static String CalcPctStr(long dividend, long divisor, String fmt) {
|
||||
if (divisor == 0) return "%ERR";
|
||||
return GfoDecimalUtl.NewByFloat(FloatUtl.Div(dividend, divisor) * 100).ToStr(fmt) + "%";
|
||||
}
|
||||
public static final MathContext ContextGfoDefault = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31
|
||||
}
|
||||
22
baselib/src/gplx/types/commons/GfoGuid.java
Normal file
22
baselib/src/gplx/types/commons/GfoGuid.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import java.util.UUID;
|
||||
public class GfoGuid {
|
||||
public GfoGuid(UUID guid) {this.guid = guid;} private final UUID guid;
|
||||
public String ToStr() {return guid.toString();}
|
||||
@Override public String toString() {return guid.toString();}
|
||||
}
|
||||
23
baselib/src/gplx/types/commons/GfoGuidUtl.java
Normal file
23
baselib/src/gplx/types/commons/GfoGuidUtl.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
public class GfoGuidUtl {
|
||||
public static final String Cls_ref_name = "Guid";
|
||||
public static final GfoGuid Empty = Parse("00000000-0000-0000-0000-000000000000");
|
||||
public static String NewAsstr() {return New().ToStr();}
|
||||
public static GfoGuid New() {return new GfoGuid(java.util.UUID.randomUUID());}
|
||||
public static GfoGuid Parse(String s) {return new GfoGuid(java.util.UUID.fromString(s));}
|
||||
}
|
||||
@@ -13,7 +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;
|
||||
package gplx.types.commons;
|
||||
public class GfoKeyVal<K, V> {
|
||||
public GfoKeyVal(K key, V val) {
|
||||
this.key = key;
|
||||
22
baselib/src/gplx/types/commons/GfoRandom.java
Normal file
22
baselib/src/gplx/types/commons/GfoRandom.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import java.util.Random;
|
||||
public class GfoRandom {
|
||||
private final Random under;
|
||||
public GfoRandom(Random v) {this.under = v;}
|
||||
public int Next(int max) {return under.nextInt(max);}
|
||||
}
|
||||
@@ -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;
|
||||
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);
|
||||
package gplx.types.commons;
|
||||
import java.util.Random;
|
||||
public class GfoRandomUtl {
|
||||
public static GfoRandom New() {
|
||||
Random random = new Random(System.currentTimeMillis());
|
||||
return new GfoRandom(random);
|
||||
}
|
||||
}
|
||||
79
baselib/src/gplx/types/commons/GfoTimeSpan.java
Normal file
79
baselib/src/gplx/types/commons/GfoTimeSpan.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.commons.lists.CompareAble;
|
||||
import gplx.types.commons.lists.CompareAbleUtl;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
public class GfoTimeSpan implements CompareAble<GfoTimeSpan> {
|
||||
public GfoTimeSpan(long fracs) {this.fracs = fracs;}
|
||||
public long Fracs() {return fracs;} private final long fracs;
|
||||
public int FracsAsInt() {return (int)fracs;}
|
||||
public GfoDecimal TotalDays() {return GfoDecimalUtl.NewByDivide(fracs, GfoTimeSpanUtl.Divisors[GfoTimeSpanUtl.Idx_Hour] * 24);}
|
||||
public GfoDecimal TotalHours() {return GfoDecimalUtl.NewByDivide(fracs, GfoTimeSpanUtl.Divisors[GfoTimeSpanUtl.Idx_Hour]);}
|
||||
public GfoDecimal TotalMins() {return GfoDecimalUtl.NewByDivide(fracs, GfoTimeSpanUtl.Divisors[GfoTimeSpanUtl.Idx_Min]);}
|
||||
public GfoDecimal TotalSecs() {return GfoDecimalUtl.NewByDivide(fracs, GfoTimeSpanUtl.Divisors[GfoTimeSpanUtl.Idx_Sec]);}
|
||||
public int[] Units() {return GfoTimeSpanUtl.SplitLong(fracs, GfoTimeSpanUtl.Divisors);}
|
||||
public GfoTimeSpan Add(GfoTimeSpan val) {return new GfoTimeSpan(fracs + val.fracs);}
|
||||
public GfoTimeSpan AddFracs(long val) {return new GfoTimeSpan(fracs + val);}
|
||||
public GfoTimeSpan AddUnit(int idx, int val) {
|
||||
int[] units = GfoTimeSpanUtl.SplitLong(fracs, GfoTimeSpanUtl.Divisors);
|
||||
units[idx] += val;
|
||||
int sign = fracs >= 0 ? 1 : -1;
|
||||
long rv = sign * GfoTimeSpanUtl.MergeLong(units, GfoTimeSpanUtl.Divisors);
|
||||
return GfoTimeSpanUtl.NewFracs(rv);
|
||||
}
|
||||
public GfoTimeSpan Subtract(GfoTimeSpan val) {return new GfoTimeSpan(fracs - val.fracs);}
|
||||
public boolean Eq(Object o) {
|
||||
GfoTimeSpan comp = (GfoTimeSpan)o; if (comp == null) return false;
|
||||
return fracs == comp.fracs;
|
||||
}
|
||||
public String ToStr() {return GfoTimeSpanUtl.ToStr(fracs, GfoTimeSpanUtl.Fmt_Default);}
|
||||
public String ToStr(String format) {return GfoTimeSpanUtl.ToStr(fracs, format);}
|
||||
public String ToStrUiAbrv() {
|
||||
if (fracs == 0) return "0" + UnitAbbrv(0);
|
||||
int[] units = Units();
|
||||
boolean started = false;
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
for (int i = units.length - 1; i > -1; i--) {
|
||||
int unit = units[i];
|
||||
if (!started) {
|
||||
if (unit == 0)
|
||||
continue;
|
||||
else
|
||||
started = true;
|
||||
}
|
||||
if (sb.Len() != 0) sb.Add(" ");
|
||||
sb.AddObj(unit).Add(UnitAbbrv(i));
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
private String UnitAbbrv(int i) {
|
||||
switch (i) {
|
||||
case 0: return "f";
|
||||
case 1: return "s";
|
||||
case 2: return "m";
|
||||
case 3: return "h";
|
||||
default: return "unknown:<" + IntUtl.ToStr(i) + ">";
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int compareTo(GfoTimeSpan comp) {return CompareAbleUtl.Compare_obj(fracs, comp.fracs);}
|
||||
@Override public String toString() {return ToStr(GfoTimeSpanUtl.Fmt_Default);}
|
||||
@Override public boolean equals(Object obj) {GfoTimeSpan comp = (GfoTimeSpan)obj; return ObjectUtl.Eq(fracs, comp.fracs);}
|
||||
@Override public int hashCode() {return new Long(fracs).hashCode();}
|
||||
}
|
||||
161
baselib/src/gplx/types/commons/GfoTimeSpanUtl.java
Normal file
161
baselib/src/gplx/types/commons/GfoTimeSpanUtl.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.basics.utls.ArrayUtl;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.basics.utls.IntUtl;
|
||||
import gplx.types.basics.utls.LongUtl;
|
||||
import gplx.types.basics.utls.MathUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
public class GfoTimeSpanUtl {
|
||||
public static final GfoTimeSpan
|
||||
Zero = new GfoTimeSpan(0),
|
||||
Null = new GfoTimeSpan(-1);
|
||||
public static final long ParseNull = LongUtl.MinValue;
|
||||
public static GfoTimeSpan NewFracs(long val) {return new GfoTimeSpan(val);}
|
||||
public static GfoTimeSpan NewSeconds(double seconds) {
|
||||
long fracs = (long)(seconds * Divisors[Idx_Sec]);
|
||||
return new GfoTimeSpan(fracs);
|
||||
}
|
||||
public static GfoTimeSpan NewSeconds(GfoDecimal seconds) {return new GfoTimeSpan(seconds.ToLongMult1000());}
|
||||
public static GfoTimeSpan Parse(String raw) {
|
||||
byte[] bry = BryUtl.NewU8(raw);
|
||||
long fracs = ParseToFracs(bry, 0, bry.length, false);
|
||||
return fracs == ParseNull ? null : GfoTimeSpanUtl.NewFracs(fracs);
|
||||
}
|
||||
public static long ParseToFracs(byte[] raw, int bgn, int end, boolean fail_if_ws) {
|
||||
int sign = 1, val_f = 0, val_s = 0, val_m = 0, val_h = 0, colon_pos = 0, unit_val = 0, unit_multiple = 1;
|
||||
for (int i = end - 1; i >= bgn; i--) { // start from end; fracs should be lowest unit
|
||||
byte b = raw[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
int unit_digit = AsciiByte.ToA7Int(b);
|
||||
unit_val = (unit_multiple == 1) ? unit_digit : unit_val + (unit_digit * unit_multiple);
|
||||
switch (colon_pos) {
|
||||
case 0: val_s = unit_val; break;
|
||||
case 1: val_m = unit_val; break;
|
||||
case 2: val_h = unit_val; break;
|
||||
default: return ParseNull; // only hour:minute:second supported for ':' separator; ':' count should be <= 2
|
||||
}
|
||||
unit_multiple *= 10;
|
||||
break;
|
||||
case AsciiByte.Dot:
|
||||
double factor = (double)1000 / (double)unit_multiple; // factor is necessary to handle non-standard decimals; ex: .1 -> 100; .00199 -> .001
|
||||
val_f = (int)((double)val_s * factor); // move val_s unit_val to val_f; logic is indirect, b/c of differing inputs: "123" means 123 seconds; ".123" means 123 fractionals
|
||||
val_s = 0;
|
||||
unit_multiple = 1;
|
||||
break;
|
||||
case AsciiByte.Colon:
|
||||
colon_pos++;
|
||||
unit_multiple = 1;
|
||||
break;
|
||||
case AsciiByte.Dash:
|
||||
if (i == 0 && unit_val > 0) // only if first char && unit_val > 0
|
||||
sign = -1;
|
||||
break;
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
if (fail_if_ws) return ParseNull;
|
||||
break;
|
||||
default:
|
||||
return ParseNull; // invalid char; return null;
|
||||
}
|
||||
}
|
||||
return sign * (val_f + (val_s * Divisors[1]) + (val_m * Divisors[2]) + (val_h * Divisors[3]));
|
||||
}
|
||||
public static String ToStr(long frc, String fmt) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int[] units = SplitLong(frc, Divisors);
|
||||
|
||||
if (StringUtl.Eq(fmt, GfoTimeSpanUtl.Fmt_Short)) {
|
||||
for (int i = Idx_Hour; i > -1; i--) {
|
||||
int val = units[i];
|
||||
if (val == 0 && i == Idx_Hour) continue; // skip hour if 0; ex: 01:02, instead of 00:01:02
|
||||
if (i == Idx_Frac) continue; // skip frac b/c fmt is short
|
||||
if (sb.Len() > 0) // sb already has unit; add delimiter
|
||||
sb.Add(Sprs[i]);
|
||||
if (val < 10) // zeroPad
|
||||
sb.Add("0");
|
||||
sb.Add(IntUtl.ToStr(val));
|
||||
}
|
||||
return sb.ToStrAndClear();
|
||||
}
|
||||
boolean fmt_fracs = !StringUtl.Eq(fmt, GfoTimeSpanUtl.Fmt_NoFractionals);
|
||||
boolean fmt_padZeros = StringUtl.Eq(fmt, GfoTimeSpanUtl.Fmt_PadZeros);
|
||||
if (frc == 0) return fmt_padZeros ? "00:00:00.000" : "0";
|
||||
|
||||
int[] padZerosAry = ZeroPadding;
|
||||
boolean first = true;
|
||||
String dlm = "";
|
||||
int zeros = 0;
|
||||
if (frc < 0) sb.Add("-"); // negative sign
|
||||
for (int i = Idx_Hour; i > -1; i--) { // NOTE: "> Idx_Frac" b/c frc will be handled below
|
||||
int val = units[i];
|
||||
if (i == Idx_Frac // only write fracs...
|
||||
&& !(val == 0 && fmt_padZeros) // ... if val == 0 && fmt is PadZeros
|
||||
&& !(val != 0 && fmt_fracs) // ... or val != 0 && fmt is PadZeros or Default
|
||||
) continue;
|
||||
if (first && val == 0 && !fmt_padZeros) continue; // if first and val == 0, don't full pad (avoid "00:")
|
||||
zeros = first && !fmt_padZeros ? 1 : padZerosAry[i]; // if first, don't zero pad (avoid "01")
|
||||
dlm = first ? "" : Sprs[i]; // if first, don't use dlm (avoid ":01")
|
||||
sb.Add(dlm);
|
||||
sb.Add(IntUtl.ToStrPadBgnZero(val, zeros));
|
||||
first = false;
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
public static int[] SplitLong(long fracs, int[] divisors) {
|
||||
int divLength = ArrayUtl.Len(divisors);
|
||||
int[] rv = new int[divLength];
|
||||
long cur = MathUtl.Abs(fracs); // NOTE: Abs necessary for toStr; EX: -1234 -> 1234 -> -1s 234f
|
||||
for (int i = divLength - 1; i > -1; i--) {
|
||||
int divisor = divisors[i];
|
||||
long factor = cur / divisor;
|
||||
rv[i] = (int)factor;
|
||||
cur -= (factor * divisor);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static long MergeLong(int[] vals, int[] divisors) {
|
||||
long rv = 0; int valLength = ArrayUtl.Len(vals);
|
||||
for (int i = 0; i < valLength; i++) {
|
||||
rv += vals[i] * divisors[i];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final String
|
||||
Fmt_PadZeros = "00:00:00.000", // u,h00:m00:s00.f000
|
||||
Fmt_Short = "short", // u,h##:m#0:s00;
|
||||
Fmt_Default = "0.000", // v,#.000
|
||||
Fmt_NoFractionals = "0"; // v,#
|
||||
public static final int[] Divisors =
|
||||
{ 1 // 1 fracs
|
||||
, 1000 // 1,000 fracs in a second
|
||||
, 60000 // 60,000 fracs in a minute (60 seconds * 1,000)
|
||||
, 3600000 // 3,600,000 fracs in an hour (60 minutes * 60,000)
|
||||
};
|
||||
public static final String MajorDelimiter = ":";
|
||||
public static final int
|
||||
Idx_Frac = 0,
|
||||
Idx_Sec = 1,
|
||||
Idx_Min = 2,
|
||||
Idx_Hour = 3;
|
||||
private static int[] ZeroPadding = {3, 2, 2, 2,};
|
||||
private static String[] Sprs = {".", MajorDelimiter, MajorDelimiter, "",};
|
||||
public static final double RatioFracsToSecs = 1000;
|
||||
}
|
||||
64
baselib/src/gplx/types/commons/IntBldr.java
Normal file
64
baselib/src/gplx/types/commons/IntBldr.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package gplx.types.commons;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class IntBldr {
|
||||
private int[] digits;
|
||||
private int idx, digitsLen;
|
||||
private int sign = 1;
|
||||
public IntBldr(int digitsMax) {
|
||||
this.digits = new int[digitsMax];
|
||||
this.digitsLen = digitsMax;
|
||||
}
|
||||
public void Clear() {idx = 0; sign = 1;}
|
||||
public int Add(char c) {
|
||||
if (idx > digitsLen - 1) throw ErrUtl.NewArgs("index is out of bound", "idx", idx, "len", digitsLen);
|
||||
digits[idx++] = ToIntByChar(c);
|
||||
return idx;
|
||||
}
|
||||
public int Add(int i) {
|
||||
if (idx > digitsLen - 1) throw ErrUtl.NewArgs("index is out of bound", "idx", idx, "len", digitsLen);
|
||||
digits[idx++] = i;
|
||||
return idx;
|
||||
}
|
||||
public int ToInt() {
|
||||
int rv = 0, exponent = 1;
|
||||
for (int i = idx - 1; i > -1; i--) {
|
||||
int digit = digits[i];
|
||||
if (digit < 0) throw ErrUtl.NewArgs("invalid char", "char", (char)-digits[i], "ascii", -digits[i]);
|
||||
rv += digit * exponent;
|
||||
exponent *= 10;
|
||||
}
|
||||
return sign * rv;
|
||||
}
|
||||
public int ToIntAndClear() {
|
||||
int rv = ToInt();
|
||||
this.Clear();
|
||||
return rv;
|
||||
}
|
||||
public int Parse(String raw) {
|
||||
ParseStr(raw);
|
||||
try {return ToInt();}
|
||||
catch (Exception exc) {throw ErrUtl.NewParse(int.class, raw);}
|
||||
}
|
||||
public boolean ParseTry(String raw) {
|
||||
ParseStr(raw);
|
||||
for (int i = 0; i < idx; i++)
|
||||
if (digits[i] < 0) return false;
|
||||
return true;
|
||||
}
|
||||
private void ParseStr(String raw) {
|
||||
this.Clear();
|
||||
int rawLength = raw.length();
|
||||
for (int i = 0; i < rawLength; i++) {
|
||||
char c = raw.charAt(i);
|
||||
if (i == 0 && c == '-')
|
||||
sign = -1;
|
||||
else
|
||||
Add(c);
|
||||
}
|
||||
}
|
||||
private int ToIntByChar(char c) {
|
||||
if (c == '0') return 0; else if (c == '1') return 1; else if (c == '2') return 2; else if (c == '3') return 3; else if (c == '4') return 4;
|
||||
else if (c == '5') return 5; else if (c == '6') return 6; else if (c == '7') return 7; else if (c == '8') return 8; else if (c == '9') return 9;
|
||||
else return -(int)c; // error handling: don't throw error; store ascii value in digit and throw if needed
|
||||
}
|
||||
}
|
||||
40
baselib/src/gplx/types/commons/KeyVal.java
Normal file
40
baselib/src/gplx/types/commons/KeyVal.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.frameworks.objects.ToStrAble;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.basics.utls.TypeIds;
|
||||
public class KeyVal implements ToStrAble { // DEPRECATED
|
||||
public KeyVal(int keyTid, Object key, Object val) {this.keyTid = keyTid; this.key = key; this.val = val;}
|
||||
public int KeyTid() {return keyTid;} private int keyTid;
|
||||
public Object KeyAsObj() {return key;} private Object key;
|
||||
public KeyVal KeySet(Object v) {this.key = v; return this;}
|
||||
public String KeyToStr() {return ObjectUtl.ToStrOrNull(key);}
|
||||
public Object Val() {return val;} private Object val;
|
||||
public String ValToStrOrEmpty() {return ObjectUtl.ToStrOrEmpty(val);}
|
||||
public String ValToStrOrNull() {return ObjectUtl.ToStrOrNull(val);}
|
||||
public byte[] ValToBry() {return BryUtl.NewU8(ObjectUtl.ToStrOrNull(val));}
|
||||
public KeyVal ValSet(Object v) {this.val = v; return this;}
|
||||
public String ToStr() {return KeyToStr() + "=" + ObjectUtl.ToStrOrNullMark(val);}
|
||||
@Override public String toString() {return ToStr();}
|
||||
|
||||
public static KeyVal As(Object obj) {return obj instanceof KeyVal ? (KeyVal)obj : null;}
|
||||
public static KeyVal NewStr(String key) {return new KeyVal(TypeIds.IdStr, key, key);}
|
||||
public static KeyVal NewStr(String key, Object val) {return new KeyVal(TypeIds.IdStr, key, val);}
|
||||
public static KeyVal NewInt(int key, Object val) {return new KeyVal(TypeIds.IdInt, key, val);}
|
||||
public static KeyVal NewObj(Object key, Object val) {return new KeyVal(TypeIds.IdObj, key, val);}
|
||||
}
|
||||
42
baselib/src/gplx/types/commons/KeyValUtl.java
Normal file
42
baselib/src/gplx/types/commons/KeyValUtl.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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.types.commons;
|
||||
import gplx.types.basics.strings.bfrs.GfoStringBldr;
|
||||
import gplx.types.basics.utls.ClassUtl;
|
||||
import gplx.types.basics.utls.ObjectUtl;
|
||||
public class KeyValUtl {
|
||||
public static final KeyVal[] AryEmpty = new KeyVal[0];
|
||||
public static KeyVal[] Ary(KeyVal... ary) {return ary;}
|
||||
public static String AryToStr(KeyVal... ary) {
|
||||
GfoStringBldr sb = new GfoStringBldr();
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
KeyVal itm = ary[i];
|
||||
if (itm == null) {
|
||||
sb.Add("<<NULL>>");
|
||||
continue;
|
||||
}
|
||||
sb.Add(itm.KeyToStr()).Add("=");
|
||||
Object itm_val = itm.Val();
|
||||
if (ClassUtl.EqByObj(KeyVal[].class, itm_val))
|
||||
sb.Add(AryToStr((KeyVal[])itm_val));
|
||||
else
|
||||
sb.Add(ObjectUtl.ToStrOrNullMark(itm_val));
|
||||
sb.AddCharNl();
|
||||
}
|
||||
return sb.ToStr();
|
||||
}
|
||||
}
|
||||
@@ -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,6 +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.lists;
|
||||
public interface CompareAble extends Comparable {} // URL:/doc/gplx/CompareAble_.txt
|
||||
package gplx.types.commons.lists;
|
||||
public interface CompareAble<T> extends Comparable<T> {} // URL:/doc/gplx/CompareAble_.txt
|
||||
// public int compareTo(Object obj) {Type comp = (Type)obj; return prop.compareTo(comp.prop);}
|
||||
@@ -13,7 +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.lists;
|
||||
package gplx.types.commons.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));}
|
||||
@@ -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,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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
import java.util.Comparator;
|
||||
public interface ComparerAble extends Comparator {
|
||||
}
|
||||
@@ -1,61 +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];
|
||||
}
|
||||
}
|
||||
/*
|
||||
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.types.commons.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];
|
||||
}
|
||||
}
|
||||
@@ -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,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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
public class ComparerAbleUtl {
|
||||
public static int Compare(ComparerAble comparer, Object lhs, Object rhs) {return comparer.compare(lhs, rhs);}
|
||||
}
|
||||
@@ -13,6 +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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
public interface GfoComparator<T> extends java.util.Comparator<T> {
|
||||
}
|
||||
@@ -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.lists;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
package gplx.types.commons.lists;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -13,7 +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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
public interface GfoHashKeyFunc<K> {
|
||||
K ToHashKey();
|
||||
}
|
||||
@@ -13,9 +13,9 @@ 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.ErrUtl;
|
||||
package gplx.types.commons.lists;
|
||||
import gplx.types.commons.GfoKeyVal;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@@ -13,11 +13,10 @@ 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;
|
||||
|
||||
package gplx.types.commons.lists;
|
||||
import gplx.frameworks.events.GfoEvent;
|
||||
import gplx.frameworks.events.GfoEventOwner;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -35,15 +34,8 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
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;
|
||||
}
|
||||
@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);
|
||||
@@ -124,7 +116,12 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
rv[i] = list.get(i);
|
||||
return rv;
|
||||
}
|
||||
public String[] ToStringAry() {
|
||||
public E[] ToAryAndClear(Class<?> clz) {
|
||||
E[] ary = ToAry(clz);
|
||||
this.Clear();
|
||||
return ary;
|
||||
}
|
||||
public String[] ToAryStr() {
|
||||
int len = list.size();
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
@@ -132,11 +129,7 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
return rv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new GfoListBaseIterator(list);
|
||||
}
|
||||
|
||||
@Override public Iterator<E> iterator() {return new GfoListBaseIterator(list);}
|
||||
class GfoListBaseIterator implements Iterator<E> {
|
||||
private final List<E> list;
|
||||
private int curIdx;
|
||||
@@ -145,19 +138,9 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
this.list = list;
|
||||
this.len = list.size();
|
||||
}
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return curIdx < len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return (E)list.get(curIdx++);
|
||||
}
|
||||
@Override
|
||||
public void remove() {
|
||||
throw ErrUtl.NewUnimplemented();
|
||||
}
|
||||
@Override public boolean hasNext() {return curIdx < len;}
|
||||
@Override public E next() {return (E)list.get(curIdx++);}
|
||||
@Override public void remove() {throw ErrUtl.NewUnimplemented();}
|
||||
}
|
||||
|
||||
public static <E> GfoListBase<E> NewFromArray(E... array) {
|
||||
@@ -167,4 +150,5 @@ public class GfoListBase<E> implements Iterable<E>, GfoEventOwner {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static final int Base1 = 1;
|
||||
}
|
||||
@@ -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.lists;
|
||||
import gplx.objects.errs.ErrUtl;
|
||||
package gplx.types.commons.lists;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@@ -13,7 +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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
public class ItemsChangedArg<T> {
|
||||
public ItemsChangedArg(ItemsChangedType type, GfoListBase<T> itms) {
|
||||
this.type = type;
|
||||
@@ -13,7 +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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
public enum ItemsChangedType {
|
||||
Add,
|
||||
Del,
|
||||
@@ -13,7 +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.lists;
|
||||
package gplx.types.commons.lists;
|
||||
import java.util.List;
|
||||
public class ListUtil {
|
||||
public static byte[] ToArray(List<Byte> list) {
|
||||
381
baselib/src/gplx/types/custom/brys/BryFind.java
Normal file
381
baselib/src/gplx/types/custom/brys/BryFind.java
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
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.types.custom.brys;
|
||||
import gplx.types.basics.utls.BryLni;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
public class BryFind {
|
||||
public static final int NotFound = -1;
|
||||
public static int FindFwd(byte[] src, byte lkp) {return FindFwd(src, lkp, 0, src.length);}
|
||||
public static int FindFwd(byte[] src, byte lkp, int cur) {return FindFwd(src, lkp, cur, src.length);}
|
||||
public static int FindFwd(byte[] src, byte[] lkp) {return Find(src, lkp, 0 , src.length, true);}
|
||||
public static int FindFwd(byte[] src, byte[] lkp, int cur) {return Find(src, lkp, cur , src.length, true);}
|
||||
public static int FindFwd(byte[] src, byte[] lkp, int cur, int end) {return Find(src, lkp, cur , end, true);}
|
||||
public static int FindFwd(byte[] src, byte lkp, int cur, int end) {
|
||||
for (int i = cur; i < end; i++)
|
||||
if (src[i] == lkp) return i;
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindFwdOr(byte[] src, byte lkp, int cur, int end, int or) {
|
||||
int rv = FindFwd(src, lkp, cur, end);
|
||||
return rv == BryFind.NotFound ? or : rv;
|
||||
}
|
||||
public static int FindFwdOr(byte[] src, byte[] lkp, int cur, int end, int or) {
|
||||
int rv = FindFwd(src, lkp, cur, end);
|
||||
return rv == BryFind.NotFound ? or : rv;
|
||||
}
|
||||
public static int FindBwd(byte[] src, byte lkp) {return FindBwd(src, lkp, src.length, 0);}
|
||||
public static int FindBwd(byte[] src, byte lkp, int cur) {return FindBwd(src, lkp, cur , 0);}
|
||||
public static int FindBwd(byte[] src, byte lkp, int cur, int end) {
|
||||
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
|
||||
--end;
|
||||
for (int i = cur; i > end; i--)
|
||||
if (src[i] == lkp) return i;
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwdOr(byte[] src, byte lkp, int cur, int end, int or) {
|
||||
int rv = FindBwd(src, lkp, cur, end);
|
||||
return rv == BryFind.NotFound ? or : rv;
|
||||
}
|
||||
private static final int OffsetCompare = 1;// handle srcPos >= 1 -> srcPosChk > 0
|
||||
public static int Find(byte[] src, byte[] lkp, int src_bgn, int src_end, boolean fwd) {
|
||||
if (src_bgn < 0 || src.length == 0) return BryFind.NotFound;
|
||||
int dif, lkp_len = lkp.length, lkp_bgn, lkp_end, src_end_chk;
|
||||
if (fwd) {
|
||||
if (src_bgn > src_end) return BryFind.NotFound;
|
||||
dif = 1; lkp_bgn = 0; lkp_end = lkp_len; src_end_chk = src_end - OffsetCompare;
|
||||
}
|
||||
else {
|
||||
if (src_bgn < src_end) return BryFind.NotFound;
|
||||
dif = -1; lkp_bgn = lkp_len - 1; lkp_end = -1; src_end_chk = src.length - OffsetCompare; // src_end_chk needed when going bwd, b/c lkp_len may be > 1
|
||||
}
|
||||
while (src_bgn != src_end) { // while src is not done;
|
||||
int lkp_cur = lkp_bgn;
|
||||
while (lkp_cur != lkp_end) { // while lkp is not done
|
||||
int pos = src_bgn + lkp_cur;
|
||||
if ( pos > src_end_chk // outside bounds; occurs when lkp_len > 1
|
||||
|| src[pos] != lkp[lkp_cur]) // srcByte doesn't match lkpByte
|
||||
break;
|
||||
else
|
||||
lkp_cur += dif;
|
||||
}
|
||||
if (lkp_cur == lkp_end) return src_bgn; // lkp matches src; exit
|
||||
src_bgn += dif;
|
||||
}
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwd(byte[] src, byte[] lkp, int cur) {return FindBwd(src, lkp, cur , 0);}
|
||||
public static int FindBwd(byte[] src, byte[] lkp, int cur, int end) {
|
||||
if (cur < 1) return BryFind.NotFound;
|
||||
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
|
||||
--end;
|
||||
int src_len = src.length;
|
||||
int lkp_len = lkp.length;
|
||||
for (int i = cur; i > end; i--) {
|
||||
if (i + lkp_len > src_len) continue; // lkp too small for pos; EX: src=abcde; lkp=bcd; pos=4
|
||||
boolean match = true;
|
||||
for (int j = 0; j < lkp_len; j++) {
|
||||
if (lkp[j] != src[i + j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) return i;
|
||||
}
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwdLastWs(byte[] src, int cur) {
|
||||
if (cur < 1) return BryFind.NotFound;
|
||||
--cur;
|
||||
int rv = BryFind.NotFound;
|
||||
for (int i = cur; i > -1; i--) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
rv = i;
|
||||
break;
|
||||
default:
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int FindBwdWs(byte[] src, int cur, int end) {
|
||||
for (int i = cur; i > -1; --i) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwdNonWsOrNotFound(byte[] src, int cur, int end) { // get pos of 1st char that is not ws;
|
||||
if (cur >= src.length) return BryFind.NotFound;
|
||||
for (int i = cur; i >= end; i--) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
break;
|
||||
default:
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwdWhileSpaceOrTab(byte[] src, int cur, int end) { // get pos of 1st char that is not \t or \s
|
||||
if (cur < 0 || cur > src.length) return BryFind.NotFound;
|
||||
for (int i = cur - 1; i >= end; i--) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab:
|
||||
break;
|
||||
default:
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return BryFind.NotFound;
|
||||
}
|
||||
public static int FindBwdSkipWs(byte[] src, int end, int bgn) {
|
||||
int src_len = src.length;
|
||||
if (end == src_len) return end;
|
||||
if (end > src_len || end < 0) return BryFind.NotFound;
|
||||
int pos = end - 1; // start from end - 1; handles situations where len is passed in
|
||||
for (int i = pos; i >= bgn; --i) {
|
||||
switch (src[i]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
break;
|
||||
default:
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return bgn;
|
||||
}
|
||||
public static int FindBwdSkip(byte[] src, int end, int bgn, byte skip) {
|
||||
int src_len = src.length; // if (end == src_len) return end;
|
||||
if (end > src_len || end < 0) return BryFind.NotFound;
|
||||
int pos = end - 1; // start from end - 1; handles situations where len is passed in
|
||||
for (int i = pos; i >= bgn; --i) {
|
||||
if (src[i] != skip)
|
||||
return i + 1;
|
||||
}
|
||||
return bgn;
|
||||
}
|
||||
public static int FindBwdSkip(byte[] src, int end, int bgn, byte[] skip) {
|
||||
int src_len = src.length;
|
||||
if (end > src_len || end < 0) return BryFind.NotFound;
|
||||
int skip_len = skip.length;
|
||||
int pos = end - skip_len; // start from end - 1; handles situations where len is passed in
|
||||
for (int i = pos; i >= bgn; --i) {
|
||||
if (!BryLni.Eq(src, i, i + skip_len, skip))
|
||||
return i + skip_len;
|
||||
}
|
||||
return bgn;
|
||||
}
|
||||
public static int FindBwdWhile(byte[] src, int cur, int end, byte while_byte) {
|
||||
--cur;
|
||||
while (true) {
|
||||
if ( cur < end
|
||||
|| src[cur] != while_byte) return cur;
|
||||
--cur;
|
||||
}
|
||||
}
|
||||
public static int FindBwdWhileIn(byte[] src, int cur, int end, boolean[] while_ary) {
|
||||
while (true) {
|
||||
if (cur <= end || !while_ary[src[cur]]) return cur;
|
||||
cur--;
|
||||
}
|
||||
}
|
||||
public static int FindBwdWhileV2(byte[] src, int cur, int end, byte while_byte) {
|
||||
--cur;
|
||||
while (true) {
|
||||
if ( cur < end
|
||||
|| src[cur] != while_byte) return cur + 1;
|
||||
--cur;
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhile(byte[] src, int cur, int end, byte while_byte) {
|
||||
while (true) {
|
||||
if ( cur == end
|
||||
|| src[cur] != while_byte) return cur;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhile(byte[] src, int cur, int end, byte[] while_bry) {
|
||||
int while_len = while_bry.length;
|
||||
while (true) {
|
||||
if (cur == end) return cur;
|
||||
for (int i = 0; i < while_len; i++) {
|
||||
if (while_bry[i] != src[i + cur]) return cur;
|
||||
}
|
||||
cur += while_len;
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhileIn(byte[] src, int cur, int end, boolean[] while_ary) {
|
||||
while (cur < end) {
|
||||
if (cur == end || !while_ary[src[cur]]) return cur;
|
||||
cur++;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public static boolean[] FindFwdWhileInGen(byte... ary) {
|
||||
boolean[] rv = new boolean[256];
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[ary[i]] = true;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static int FindFwdUntil(byte[] src, int cur, int end, byte until_byte) {
|
||||
while (true) {
|
||||
if ( cur == end
|
||||
|| src[cur] == until_byte) return cur;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
public static int FindFwdUntilWs(byte[] src, int cur, int end) {
|
||||
while (true) {
|
||||
if (cur == end) return BryFind.NotFound;
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
return cur;
|
||||
default:
|
||||
++cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhileSpaceOrTab(byte[] src, int cur, int end) {
|
||||
while (true) {
|
||||
if (cur == end) return cur;
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: ++cur; break;
|
||||
default: return cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static int TrimFwdSpaceTab(byte[] src, int cur, int end) {
|
||||
while (true) {
|
||||
if (cur == end) return cur;
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: ++cur; break;
|
||||
default: return cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static int TrimBwdSpaceTab(byte[] src, int cur, int bgn) {
|
||||
while (true) {
|
||||
int prv_cur = cur - 1; // check byte before cur; EX: "a b " will have len of 4, and pass cur=4;
|
||||
if (prv_cur < bgn) return cur; // checking byte before prv; exit;
|
||||
switch (src[prv_cur]) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: --cur; break;
|
||||
default: return cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhileWs(byte[] src, int cur, int end) {
|
||||
while (true) {
|
||||
if (cur == end) return cur;
|
||||
try {
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Nl: case AsciiByte.Cr:
|
||||
case AsciiByte.Space: case AsciiByte.Tab: ++cur; break;
|
||||
default: return cur;
|
||||
}
|
||||
} catch (Exception e) {throw ErrUtl.NewArgs(e, "idx is invalid", "cur", cur, "src", src);}
|
||||
}
|
||||
}
|
||||
public static int FindFwdWhileLetter(byte[] src, int cur, int end) {
|
||||
while (cur < end) {
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Ltr_A: case AsciiByte.Ltr_B: case AsciiByte.Ltr_C: case AsciiByte.Ltr_D: case AsciiByte.Ltr_E:
|
||||
case AsciiByte.Ltr_F: case AsciiByte.Ltr_G: case AsciiByte.Ltr_H: case AsciiByte.Ltr_I: case AsciiByte.Ltr_J:
|
||||
case AsciiByte.Ltr_K: case AsciiByte.Ltr_L: case AsciiByte.Ltr_M: case AsciiByte.Ltr_N: case AsciiByte.Ltr_O:
|
||||
case AsciiByte.Ltr_P: case AsciiByte.Ltr_Q: case AsciiByte.Ltr_R: case AsciiByte.Ltr_S: case AsciiByte.Ltr_T:
|
||||
case AsciiByte.Ltr_U: case AsciiByte.Ltr_V: case AsciiByte.Ltr_W: case AsciiByte.Ltr_X: case AsciiByte.Ltr_Y: case AsciiByte.Ltr_Z:
|
||||
case AsciiByte.Ltr_a: case AsciiByte.Ltr_b: case AsciiByte.Ltr_c: case AsciiByte.Ltr_d: case AsciiByte.Ltr_e:
|
||||
case AsciiByte.Ltr_f: case AsciiByte.Ltr_g: case AsciiByte.Ltr_h: case AsciiByte.Ltr_i: case AsciiByte.Ltr_j:
|
||||
case AsciiByte.Ltr_k: case AsciiByte.Ltr_l: case AsciiByte.Ltr_m: case AsciiByte.Ltr_n: case AsciiByte.Ltr_o:
|
||||
case AsciiByte.Ltr_p: case AsciiByte.Ltr_q: case AsciiByte.Ltr_r: case AsciiByte.Ltr_s: case AsciiByte.Ltr_t:
|
||||
case AsciiByte.Ltr_u: case AsciiByte.Ltr_v: case AsciiByte.Ltr_w: case AsciiByte.Ltr_x: case AsciiByte.Ltr_y: case AsciiByte.Ltr_z:
|
||||
break;
|
||||
default:
|
||||
return cur;
|
||||
}
|
||||
++cur;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
public static int FindFwdWhileNum(byte[] src, int cur, int end) {
|
||||
while (cur < end) {
|
||||
if (!AsciiByte.IsNum(src[cur]))
|
||||
return cur;
|
||||
++cur;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
public static int FindFwdWhileNotWs(byte[] src, int cur, int end) {
|
||||
while (true) {
|
||||
if (cur == end) return cur;
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Space:
|
||||
case AsciiByte.Nl:
|
||||
case AsciiByte.Tab:
|
||||
case AsciiByte.Cr:
|
||||
++cur;
|
||||
break;
|
||||
default:
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static int FindBwdWhileAlphanum(byte[] src, int cur) {return FindBwdWhileAlphanum(src, cur, -1);}
|
||||
public static int FindBwdWhileAlphanum(byte[] src, int cur, int end) {
|
||||
--cur;
|
||||
while (cur > end) {
|
||||
switch (src[cur]) {
|
||||
case AsciiByte.Num0: case AsciiByte.Num1: case AsciiByte.Num2: case AsciiByte.Num3: case AsciiByte.Num4:
|
||||
case AsciiByte.Num5: case AsciiByte.Num6: case AsciiByte.Num7: case AsciiByte.Num8: case AsciiByte.Num9:
|
||||
case AsciiByte.Ltr_A: case AsciiByte.Ltr_B: case AsciiByte.Ltr_C: case AsciiByte.Ltr_D: case AsciiByte.Ltr_E:
|
||||
case AsciiByte.Ltr_F: case AsciiByte.Ltr_G: case AsciiByte.Ltr_H: case AsciiByte.Ltr_I: case AsciiByte.Ltr_J:
|
||||
case AsciiByte.Ltr_K: case AsciiByte.Ltr_L: case AsciiByte.Ltr_M: case AsciiByte.Ltr_N: case AsciiByte.Ltr_O:
|
||||
case AsciiByte.Ltr_P: case AsciiByte.Ltr_Q: case AsciiByte.Ltr_R: case AsciiByte.Ltr_S: case AsciiByte.Ltr_T:
|
||||
case AsciiByte.Ltr_U: case AsciiByte.Ltr_V: case AsciiByte.Ltr_W: case AsciiByte.Ltr_X: case AsciiByte.Ltr_Y: case AsciiByte.Ltr_Z:
|
||||
case AsciiByte.Ltr_a: case AsciiByte.Ltr_b: case AsciiByte.Ltr_c: case AsciiByte.Ltr_d: case AsciiByte.Ltr_e:
|
||||
case AsciiByte.Ltr_f: case AsciiByte.Ltr_g: case AsciiByte.Ltr_h: case AsciiByte.Ltr_i: case AsciiByte.Ltr_j:
|
||||
case AsciiByte.Ltr_k: case AsciiByte.Ltr_l: case AsciiByte.Ltr_m: case AsciiByte.Ltr_n: case AsciiByte.Ltr_o:
|
||||
case AsciiByte.Ltr_p: case AsciiByte.Ltr_q: case AsciiByte.Ltr_r: case AsciiByte.Ltr_s: case AsciiByte.Ltr_t:
|
||||
case AsciiByte.Ltr_u: case AsciiByte.Ltr_v: case AsciiByte.Ltr_w: case AsciiByte.Ltr_x: case AsciiByte.Ltr_y: case AsciiByte.Ltr_z:
|
||||
--cur;
|
||||
break;
|
||||
default:
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return 0; // always return a valid index
|
||||
}
|
||||
public static int MoveFwd(byte[] src, byte lkp, int cur, int end) {
|
||||
int rv = FindFwd(src, lkp, cur, src.length);
|
||||
return rv == BryFind.NotFound ? rv : rv + 1;
|
||||
}
|
||||
public static int MoveFwd(byte[] src, byte[] lkp, int cur) {return MoveFwd(src, lkp, cur, src.length);}
|
||||
public static int MoveFwd(byte[] src, byte[] lkp, int cur, int end) {
|
||||
int rv = FindFwd(src, lkp, cur, src.length);
|
||||
return rv == BryFind.NotFound ? rv : rv + lkp.length;
|
||||
}
|
||||
}
|
||||
177
baselib/src/gplx/types/custom/brys/BrySplit.java
Normal file
177
baselib/src/gplx/types/custom/brys/BrySplit.java
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
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.types.custom.brys;
|
||||
import gplx.types.commons.lists.GfoListBase;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.types.basics.utls.BryLni;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.errs.ErrUtl;
|
||||
public class BrySplit {
|
||||
private static final Object thread_lock = new Object();
|
||||
public static byte[][] Split(byte[] src, byte dlm) {return Split(src, dlm, false);}
|
||||
public static byte[][] Split(byte[] src, byte dlm, boolean trim) {return src == null ? BryUtl.AryEmpty : Split(src, 0, src.length, dlm, trim);}
|
||||
public static byte[][] Split(byte[] src, int bgn, int end, byte dlm, boolean trim) {
|
||||
synchronized (thread_lock) {
|
||||
BrySplitWkrAry wkr = BrySplitWkrAry.Instance;
|
||||
Split(src, bgn, end, dlm, trim, wkr);
|
||||
return wkr.ToAry();
|
||||
}
|
||||
}
|
||||
public static int Split(byte[] src, int src_bgn, int src_end, byte dlm, boolean trim, BrySplitWkr wkr) {
|
||||
if (src == null || src_end - src_bgn < 1) return 0;
|
||||
int pos = src_bgn;
|
||||
int itm_bgn = -1, itm_end = -1;
|
||||
int count = 0;
|
||||
while (true) {
|
||||
boolean pos_is_last = pos == src_end;
|
||||
byte b = pos_is_last ? dlm : src[pos];
|
||||
int nxt_pos = pos + 1;
|
||||
boolean process = true;
|
||||
switch (b) {
|
||||
case AsciiByte.Space: case AsciiByte.Tab: case AsciiByte.Nl: case AsciiByte.Cr: // ignore ws; assumes that flags have no ws (they are single char) and vnts have no ws (EX: zh-hans)
|
||||
if (trim && b != dlm) process = false; // b != dlm handles cases where ws is dlm, but trim is enabled; EX: " a \n b" -> "a", "b"
|
||||
break;
|
||||
}
|
||||
if (process) {
|
||||
if (b == dlm) {
|
||||
boolean reset = true;
|
||||
if (itm_bgn == -1) {
|
||||
if (pos_is_last) {} // skip dlm at bgn / end; EX: "a,"
|
||||
else {wkr.Split(src, pos, pos );} // else, process "empty" dlm; EX: ",a"
|
||||
}
|
||||
else {
|
||||
int rv = wkr.Split(src, itm_bgn, itm_end);
|
||||
switch (rv) {
|
||||
case Rv__ok: ++count; break;
|
||||
case Rv__extend: reset = false; break;
|
||||
case Rv__cancel: return count;
|
||||
default: throw ErrUtl.NewUnhandled(rv);
|
||||
}
|
||||
}
|
||||
if (reset) itm_bgn = itm_end = -1;
|
||||
}
|
||||
else {
|
||||
if (itm_bgn == -1) itm_bgn = pos;
|
||||
itm_end = nxt_pos;
|
||||
}
|
||||
}
|
||||
if (pos_is_last) break;
|
||||
pos = nxt_pos;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public static byte[][] Split(byte[] src, byte[] dlm) {return Split(src, 0, src.length, dlm);}
|
||||
public static byte[][] Split(byte[] src, int src_bgn, int src_end, byte[] dlm) {
|
||||
if (src == null) return BryUtl.AryEmpty;
|
||||
int src_len = src.length;
|
||||
if (src_len == 0) return BryUtl.AryEmpty;
|
||||
int cur_pos = src_bgn, dlm_len = dlm.length;
|
||||
GfoListBase<byte[]> rv = new GfoListBase<>();
|
||||
while (true) {
|
||||
int find_pos = BryFind.FindFwd(src, dlm, cur_pos);
|
||||
if (find_pos == BryFind.NotFound) {
|
||||
if (cur_pos >= src_end) break; // dlm is last sequence in src; do not create empty itm
|
||||
find_pos = src_end;
|
||||
}
|
||||
rv.Add(BryLni.Mid(src, cur_pos, find_pos));
|
||||
cur_pos = find_pos + dlm_len;
|
||||
if (cur_pos >= src_end) break;
|
||||
}
|
||||
return rv.ToAry(byte[].class);
|
||||
}
|
||||
public static byte[][] SplitLines(byte[] src) {
|
||||
if (BryUtl.IsNullOrEmpty(src)) return BryUtl.AryEmpty;
|
||||
int src_len = src.length, src_pos = 0, fld_bgn = 0;
|
||||
GfoListBase<byte[]> rv = new GfoListBase<>();
|
||||
while (true) {
|
||||
boolean last = src_pos == src_len;
|
||||
byte b = last ? AsciiByte.Nl : src[src_pos];
|
||||
int nxt_bgn = src_pos + 1;
|
||||
switch (b) {
|
||||
case AsciiByte.Cr:
|
||||
case AsciiByte.Nl:
|
||||
if ( b == AsciiByte.Cr // check for crlf
|
||||
&& nxt_bgn < src_len && src[nxt_bgn] == AsciiByte.Nl) {
|
||||
++nxt_bgn;
|
||||
}
|
||||
if (last && (src_pos - fld_bgn == 0)) {} // ignore trailing itms
|
||||
else
|
||||
rv.Add(BryLni.Mid(src, fld_bgn, src_pos));
|
||||
fld_bgn = nxt_bgn;
|
||||
break;
|
||||
}
|
||||
if (last) break;
|
||||
src_pos = nxt_bgn;
|
||||
}
|
||||
return rv.ToAry(byte[].class);
|
||||
}
|
||||
public static byte[][] SplitWithmax(byte[] src, byte dlm, int max) {
|
||||
byte[][] rv = new byte[max][];
|
||||
int src_len = src.length;
|
||||
int rv_idx = 0;
|
||||
int itm_bgn = 0;
|
||||
int src_pos = 0;
|
||||
while (true) {
|
||||
boolean is_last = src_pos == src_len;
|
||||
byte b = is_last ? dlm : src[src_pos];
|
||||
if (b == dlm) {
|
||||
rv[rv_idx++] = BryLni.Mid(src, itm_bgn, src_pos);
|
||||
itm_bgn = src_pos + 1;
|
||||
}
|
||||
if (is_last || rv_idx == max)
|
||||
break;
|
||||
else
|
||||
src_pos++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[][] SplitWs(byte[] src) {// REF.PHP: preg_split('/\s+/', $text)
|
||||
int len = src.length;
|
||||
if (len == 0) return BryUtl.AryEmpty;
|
||||
|
||||
GfoListBase<byte[]> list = new GfoListBase<>();
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
int bgn = BryFind.FindFwdWhileWs(src, pos, len);
|
||||
if (bgn == len) break; // EOS
|
||||
int end = BryFind.FindFwdUntilWs(src, bgn + 1, len);
|
||||
if (end == -1) end = len;
|
||||
list.Add(BryLni.Mid(src, bgn, end));
|
||||
pos = end + 1;
|
||||
if (pos >= len) break;
|
||||
}
|
||||
return list.ToAry(byte[].class);
|
||||
}
|
||||
|
||||
|
||||
public static final int Rv__ok = 0, Rv__extend = 1, Rv__cancel = 2;
|
||||
}
|
||||
class BrySplitWkrAry implements BrySplitWkr {
|
||||
private final GfoListBase<byte[]> list = new GfoListBase<>();
|
||||
public int Split(byte[] src, int itm_bgn, int itm_end) {
|
||||
synchronized (list) {
|
||||
byte[] bry = itm_end == itm_bgn ? BryUtl.Empty : BryLni.Mid(src, itm_bgn, itm_end);
|
||||
list.Add(bry);
|
||||
return BrySplit.Rv__ok;
|
||||
}
|
||||
}
|
||||
public byte[][] ToAry() {
|
||||
synchronized (list) {
|
||||
return list.ToAryAndClear(byte[].class);
|
||||
}
|
||||
}
|
||||
public static final BrySplitWkrAry Instance = new BrySplitWkrAry(); BrySplitWkrAry() {}
|
||||
}
|
||||
19
baselib/src/gplx/types/custom/brys/BrySplitWkr.java
Normal file
19
baselib/src/gplx/types/custom/brys/BrySplitWkr.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
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.types.custom.brys;
|
||||
public interface BrySplitWkr {
|
||||
int Split(byte[] src, int itm_bgn, int itm_end);
|
||||
}
|
||||
96
baselib/src/gplx/types/custom/brys/BrySplitWkrTest.java
Normal file
96
baselib/src/gplx/types/custom/brys/BrySplitWkrTest.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.types.custom.brys;
|
||||
import gplx.types.basics.utls.BryLni;
|
||||
import gplx.types.basics.utls.BryUtl;
|
||||
import gplx.types.commons.lists.GfoListBase;
|
||||
import gplx.types.basics.constants.AsciiByte;
|
||||
import gplx.frameworks.tests.GfoTstr;
|
||||
import gplx.types.basics.utls.BoolUtl;
|
||||
import gplx.types.basics.utls.StringUtl;
|
||||
import org.junit.Test;
|
||||
public class BrySplitWkrTest {
|
||||
private final BrySplitWkrTstr tstr = new BrySplitWkrTstr();
|
||||
@Test public void Split() {
|
||||
tstr.TestSplit("a" , AsciiByte.Pipe, BoolUtl.N, "a"); // no trim
|
||||
tstr.TestSplit("a|" , AsciiByte.Pipe, BoolUtl.N, "a");
|
||||
tstr.TestSplit("|a" , AsciiByte.Pipe, BoolUtl.N, "", "a");
|
||||
tstr.TestSplit("|" , AsciiByte.Pipe, BoolUtl.N, "");
|
||||
tstr.TestSplit("" , AsciiByte.Pipe, BoolUtl.N);
|
||||
tstr.TestSplit("a|b|c" , AsciiByte.Pipe, BoolUtl.N, "a", "b", "c");
|
||||
tstr.TestSplit(" a " , AsciiByte.Pipe, BoolUtl.Y, "a"); // trim
|
||||
tstr.TestSplit(" a |" , AsciiByte.Pipe, BoolUtl.Y, "a");
|
||||
tstr.TestSplit("| a " , AsciiByte.Pipe, BoolUtl.Y, "", "a");
|
||||
tstr.TestSplit(" | " , AsciiByte.Pipe, BoolUtl.Y, "");
|
||||
tstr.TestSplit(" " , AsciiByte.Pipe, BoolUtl.Y);
|
||||
tstr.TestSplit(" a | b | c " , AsciiByte.Pipe, BoolUtl.Y, "a", "b", "c");
|
||||
tstr.TestSplit(" a b | c d " , AsciiByte.Pipe, BoolUtl.Y, "a b", "c d");
|
||||
tstr.TestSplit(" a \n b " , AsciiByte.Nl , BoolUtl.N, " a ", " b "); // ws as dlm
|
||||
tstr.TestSplit(" a \n b " , AsciiByte.Nl , BoolUtl.Y, "a", "b"); // ws as dlm; trim
|
||||
tstr.TestSplit("a|extend|b" , AsciiByte.Pipe, BoolUtl.Y, "a", "extend|b"); // extend
|
||||
tstr.TestSplit("extend|a" , AsciiByte.Pipe, BoolUtl.Y, "extend|a"); // extend
|
||||
tstr.TestSplit("a|cancel|b" , AsciiByte.Pipe, BoolUtl.Y, "a"); // cancel
|
||||
}
|
||||
@Test public void SplitBry() {
|
||||
tstr.TestSplit("a|b|c|d" , 2, 6, "|", "b", "c");
|
||||
tstr.TestSplit("a|b|c|d" , 2, 4, "|", "b");
|
||||
}
|
||||
@Test public void Empty() {
|
||||
tstr.TestSplit("a\n\nb" , AsciiByte.Nl, BoolUtl.N, "a", "", "b");
|
||||
}
|
||||
@Test public void SplitWithMax() {
|
||||
tstr.TestSplitWithMax("a|b|c|d" , AsciiByte.Pipe, 2, "a", "b"); // max is less
|
||||
tstr.TestSplitWithMax("a" , AsciiByte.Pipe, 2, "a", null); // max is more
|
||||
tstr.TestSplitWithMax("|" , AsciiByte.Pipe, 2, "", ""); // empty itms
|
||||
}
|
||||
@Test public void SplitWs() {
|
||||
tstr.TestSplitWs("a b", "a", "b");
|
||||
tstr.TestSplitWs(" a ", "a");
|
||||
tstr.TestSplitWs(" abc def ", "abc", "def");
|
||||
}
|
||||
}
|
||||
class BrySplitWkrTstr {
|
||||
private final BrySplitWkrExample wkr = new BrySplitWkrExample();
|
||||
public void TestSplit(String raw_str, byte dlm, boolean trim, String... expd) {
|
||||
byte[] src = BryUtl.NewA7(raw_str);
|
||||
BrySplit.Split(src, 0, src.length, dlm, trim, wkr);
|
||||
byte[][] actl_ary = wkr.ToAry();
|
||||
GfoTstr.EqLines(expd, StringUtl.Ary(actl_ary));
|
||||
}
|
||||
public void TestSplit(String src, int src_bgn, int src_end, String dlm, String... expd) {
|
||||
GfoTstr.EqLines(BryUtl.Ary(expd), BrySplit.Split(BryUtl.NewU8(src), src_bgn, src_end, BryUtl.NewU8(dlm)));
|
||||
}
|
||||
public void TestSplitWithMax(String src, byte dlm, int max, String... expd) {
|
||||
GfoTstr.EqLines(expd, StringUtl.Ary(BrySplit.SplitWithmax(BryUtl.NewU8(src), dlm, max)));
|
||||
}
|
||||
public void TestSplitWs(String raw, String... expd) {
|
||||
byte[][] actl = BrySplit.SplitWs(BryUtl.NewU8(raw));
|
||||
GfoTstr.EqLines(BryUtl.Ary(expd), actl, raw);
|
||||
}
|
||||
}
|
||||
class BrySplitWkrExample implements BrySplitWkr {
|
||||
private final GfoListBase<byte[]> list = new GfoListBase<>();
|
||||
public int Split(byte[] src, int itm_bgn, int itm_end) {
|
||||
byte[] bry = itm_end == itm_bgn ? BryUtl.Empty : BryLni.Mid(src, itm_bgn, itm_end);
|
||||
if (BryLni.Eq(bry, BryUtl.NewA7("extend"))) return BrySplit.Rv__extend;
|
||||
else if (BryLni.Eq(bry, BryUtl.NewA7("cancel"))) return BrySplit.Rv__cancel;
|
||||
list.Add(bry);
|
||||
return BrySplit.Rv__ok;
|
||||
}
|
||||
public byte[][] ToAry() {
|
||||
return list.ToAryAndClear(byte[].class);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user