1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-10-27 20:34:16 +00:00
This commit is contained in:
gnosygnu 2014-06-30 00:04:32 -04:00
parent 85594d3cdd
commit bae88e739c
2482 changed files with 198730 additions and 0 deletions

31
100_core/.classpath Normal file
View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src_000_err"/>
<classpathentry kind="src" path="src_100_interface"/>
<classpathentry kind="src" path="src_110_primitive"/>
<classpathentry kind="src" path="src_120_basicDataType"/>
<classpathentry kind="src" path="src_130_crt"/>
<classpathentry kind="src" path="src_140_list"/>
<classpathentry kind="src" path="src_150_text"/>
<classpathentry kind="src" path="src_160_hash"/>
<classpathentry kind="src" path="src_200_io"/>
<classpathentry kind="src" path="src_210_env"/>
<classpathentry kind="src" path="src_220_console"/>
<classpathentry kind="src" path="src_300_classXtn"/>
<classpathentry kind="src" path="src_310_gfoNde"/>
<classpathentry kind="src" path="src_311_gfoObj"/>
<classpathentry kind="src" path="src_330_store"/>
<classpathentry kind="src" path="src_340_dsv"/>
<classpathentry kind="src" path="src_400_gfs"/>
<classpathentry kind="src" path="src_410_gfoCfg"/>
<classpathentry kind="src" path="src_420_usrMsg"/>
<classpathentry kind="src" path="src_800_tst"/>
<classpathentry kind="src" path="src_900_xml"/>
<classpathentry kind="src" path="tst"/>
<classpathentry kind="src" path="xtn"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="lib/commons-compress-1.5.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
100_core/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>100_core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Binary file not shown.

View File

@ -0,0 +1,115 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface String_bldr {
boolean Has_none();
boolean Has_some();
String_bldr Add_many(String... array);
String_bldr Add_fmt(String format, Object... args);
String_bldr Add_fmt_line(String format, Object... args);
String_bldr Add_kv(String hdr, String val);
String_bldr Add_kv_obj(String k, Object v);
String_bldr Add_char_pipe();
String_bldr Add_char_nl();
String_bldr Add_char_crlf();
String_bldr Add_str_w_crlf(String v);
String_bldr Add_spr_unless_first(String s, String spr, int i);
String_bldr Clear();
String XtoStrAndClear();
String XtoStr();
int Count();
String_bldr Add(byte[] v);
String_bldr Add(String s);
String_bldr Add(char c);
String_bldr Add(int i);
String_bldr Add_obj(Object o);
String_bldr Add_mid(char[] ary, int bgn, int count);
String_bldr Add_at(int idx, String s);
String_bldr Del(int bgn, int len);
}
abstract class String_bldr_base implements String_bldr {
public boolean Has_none() {return this.Count() == 0;}
public boolean Has_some() {return this.Count() > 0;}
public String_bldr Add_many(String... array) {for (String s : array) Add(s); return this;}
public String_bldr Add_fmt(String format, Object... args) {Add(String_.Format(format, args)); return this;}
public String_bldr Add_fmt_line(String format, Object... args) {Add_str_w_crlf(String_.Format(format, args)); return this;}
public String_bldr Add_kv_obj(String k, Object v) {
if (this.Count() != 0) this.Add(" ");
this.Add_fmt("{0}={1}", k, Object_.XtoStr_OrNullStr(v));
return this;
}
public String_bldr Add_char_pipe() {return Add("|");}
public String_bldr Add_char_nl() {Add(Op_sys.Lnx.Nl_str()); return this;}
public String_bldr Add_char_crlf() {Add(Op_sys.Wnt.Nl_str()); return this;}
public String_bldr Add_str_w_crlf(String line) {Add(line); Add(String_.CrLf); return this;}
public String_bldr Add_spr_unless_first(String s, String spr, int i) {
if (i != 0) Add(spr);
Add(s);
return this;
}
public String_bldr Add_kv(String hdr, String val) {
if (String_.Len_eq_0(val)) return this;
if (this.Count() != 0) this.Add(' ');
this.Add(hdr);
this.Add(val);
return this;
}
public String_bldr Clear() {Del(0, Count()); return this;}
public String XtoStrAndClear() {
String rv = XtoStr();
Clear();
return rv;
}
@Override public String toString() {return XtoStr();}
public abstract String XtoStr();
public abstract int Count();
public abstract String_bldr Add_at(int idx, String s);
public abstract String_bldr Add(byte[] v);
public abstract String_bldr Add(String s);
public abstract String_bldr Add(char c);
public abstract String_bldr Add(int i);
public abstract String_bldr Add_mid(char[] ary, int bgn, int count);
public abstract String_bldr Add_obj(Object o);
public abstract String_bldr Del(int bgn, int len);
}
class String_bldr_thread_single extends String_bldr_base {
private java.lang.StringBuilder sb = new java.lang.StringBuilder();
@Override public String XtoStr() {return sb.toString();}
@Override public int Count() {return sb.length();}
@Override public String_bldr Add_at(int idx, String s) {sb.insert(idx, s); return this;}
@Override public String_bldr Add(byte[] v) {sb.append(String_.new_utf8_(v)); return this;}
@Override public String_bldr Add(String s) {sb.append(s); return this;}
@Override public String_bldr Add(char c) {sb.append(c); return this;}
@Override public String_bldr Add(int i) {sb.append(i); return this;}
@Override public String_bldr Add_mid(char[] ary, int bgn, int count) {sb.append(ary, bgn, count); return this;}
@Override public String_bldr Add_obj(Object o) {sb.append(o); return this;}
@Override public String_bldr Del(int bgn, int len) {sb.delete(bgn, len); return this;}
}
class String_bldr_thread_multiple extends String_bldr_base {
private java.lang.StringBuffer sb = new java.lang.StringBuffer();
@Override public String XtoStr() {return sb.toString();}
@Override public int Count() {return sb.length();}
@Override public String_bldr Add_at(int idx, String s) {sb.insert(idx, s); return this;}
@Override public String_bldr Add(byte[] v) {sb.append(String_.new_utf8_(v)); return this;}
@Override public String_bldr Add(String s) {sb.append(s); return this;}
@Override public String_bldr Add(char c) {sb.append(c); return this;}
@Override public String_bldr Add(int i) {sb.append(i); return this;}
@Override public String_bldr Add_mid(char[] ary, int bgn, int count) {sb.append(ary, bgn, count); return this;}
@Override public String_bldr Add_obj(Object o) {sb.append(o); return this;}
@Override public String_bldr Del(int bgn, int len) {sb.delete(bgn, len); return this;}
}

View File

@ -0,0 +1,22 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class String_bldr_ {
public static String_bldr new_() {return new String_bldr_thread_single();}
public static String_bldr new_thread() {return new String_bldr_thread_multiple();}
}

View File

@ -0,0 +1,63 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Err extends RuntimeException {
@Override public String getMessage() {return Message_gplx();}
public String Key() {return key;} public Err Key_(String v) {key = v; return this;} private String key = "";
public String Hdr() {return hdr;} public Err Hdr_(String v) {hdr = v; return this;} private String hdr = "";
public ListAdp Args() {return args;} ListAdp args = ListAdp_.new_();
public Err Add(String k, Object o) {args.Add(KeyVal_.new_(k, o)); return this;}
@gplx.Internal protected ErrProcData Proc() {return proc;} ErrProcData proc = ErrProcData.Null;
public OrderedHash CallStack() {return callStack;} OrderedHash callStack = OrderedHash_.new_();
public int CallLevel() {return callLevel;} public Err CallLevel_(int val) {callLevel = val; return this;} public Err CallLevel_1_() {return CallLevel_(1);} int callLevel;
public Err Inner() {return inner;} Err inner;
@gplx.Internal protected static Err hdr_(String hdr) {
Err rv = new Err();
rv.hdr = hdr;
return rv;
} @gplx.Internal protected Err() {}
@gplx.Internal protected static Err exc_(Exception thrown, String hdr) {
Err rv = hdr_(hdr);
rv.inner = convert_(thrown);
for (int i = 0; i < rv.inner.callStack.Count(); i++) {
ErrProcData itm = (ErrProcData)rv.inner.callStack.FetchAt(i);
rv.callStack.Add(itm.Raw(), itm);
}
return rv;
}
@gplx.Internal protected static Err convert_(Exception thrown) {
Err rv = Err_.as_(thrown);
if (rv == null)
rv = Err_.new_key_(ClassAdp_.NameOf_obj(thrown), Err_.Message_lang(thrown));
CallStack_fill(rv, Err_.StackTrace_lang(rv));
return rv;
}
static void CallStack_fill(Err err, String stackTrace) {
ErrProcData[] ary = ErrProcData.parse_ary_(stackTrace); if (Array_.Len(ary) == 0) return; // no callStack; shouldn't happen, but don't throw error
err.proc = ary[0];
for (ErrProcData itm : ary) {
String key = itm.Raw();
if (err.callStack.Has(key)) continue;
err.callStack.Add(key, itm);
}
}
String Message_gplx() {
try {return Err_.Message_gplx(this);}
catch (Exception exc) {Err_.Noop(exc); return super.getMessage();}
}
}

View File

@ -0,0 +1,111 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class ErrMsgWtr {
public String Message_gplx(Exception thrown) {
Err err = Err.convert_(thrown); // convert thrown to Err to make rest of class easier
Err[] innerAry = InnerAsAry(err);
String_bldr sb = String_bldr_.new_();
WriteError(innerAry, sb, 0);
WriteInner(innerAry, sb);
WriteStack(innerAry, sb);
return sb.XtoStr();
}
public String Message_gplx_brief(Exception thrown) {
Err err = Err.convert_(thrown); // convert thrown to Err to make rest of proc easier
String_bldr sb = String_bldr_.new_();
sb.Add(err.Hdr());
if (err.Args().Count() > 0) sb.Add(" --");
for (Object kvo : err.Args()) {
KeyVal kv = (KeyVal)kvo;
String key = kv.Key(), val = kv.Val_to_str_or_empty();
sb.Add_fmt(" {0}='{1}'", key, val);
}
sb.Add_fmt(" [{0}]", err.Key());
return sb.XtoStr();
}
void WriteInner(Err[] errAry, String_bldr sb) {
int len = Array_.Len(errAry); if (len <= 1) return; // no inners; return;
for (int i = 1; i < len; i++)
WriteError(errAry, sb, i);
}
void WriteError(Err[] errAry, String_bldr sb, int i) {
Err err = errAry[i];
String msg = err.Hdr();
String typ = String_.Eq(err.Key(), "") ? "" : String_.Concat(" <", err.Key(), ">");
boolean onlyOne = errAry.length == 1;
String idxStr = onlyOne ? "" : Int_.XtoStr(i);
sb.Add(idxStr).Add("\t").Add(msg).Add(typ).Add_char_crlf(); // ex: " @count must be > 0 <gplx.arg>"
WriteKeyValAry(sb, err.Args());
sb.Add("\t").Add(err.Proc().SignatureRaw()).Add_char_crlf();
// WriteKeyValAry(sb, err.ProcArgs());
}
void WriteKeyValAry(String_bldr sb, ListAdp ary) {
// calc keyMax for valIndentLen
int keyMax = 0;
for (Object o : ary) {
KeyVal kv = (KeyVal)o;
int keyLen = String_.Len(kv.Key());
if (keyLen > keyMax) keyMax = keyLen + 1; // +1 to guarantee one space between key and val
}
if (keyMax < 8)keyMax = 8; // separate by at least 8 chars
for (Object o : ary) {
KeyVal kv = (KeyVal)o;
String key = kv.Key(); int keyLen = String_.Len(key);
String valIndent = String_.Repeat(" ", keyMax - keyLen);
sb.Add("\t\t@").Add(key).Add(valIndent).Add(kv.Val_to_str_or_empty()).Add_char_crlf();
}
}
void WriteStack(Err[] errAry, String_bldr sb) {
if (Env_.Mode_testing()) return; // only write stack when not testing
int len = Array_.Len(errAry); if (len == 0) return; // shouldn't happen, but don't want to throw err
Err first = errAry[0];
boolean onlyOne = len == 1;
sb.Add_str_w_crlf(String_.Repeat("-", 80));
ListAdp tmp = ListAdp_.new_();
OrderedHash callStack = first.CallStack(); int callStackCount = callStack.Count();
for (int i = 0; i < callStackCount ; i++) {
ErrProcData proc = (ErrProcData)callStack.FetchAt(i);
// get procIndex
int idx = -1;
for (int j = 0; j < len; j++) {
ErrProcData comp = errAry[j].Proc();
if (String_.Eq(proc.Raw(), comp.Raw())) {idx = j; break;}
}
String idxStr = onlyOne ? "" : Int_.XtoStr(idx);
String hdr = idx == -1 ? "\t" : idxStr + "\t";
String ideAddressSpr = String_.CrLf + "\t\t";
String ideAddress = String_.Eq(proc.IdeAddress(), "") ? "" : ideAddressSpr + proc.IdeAddress(); // NOTE: ideAddress will be blank in compiled mode
String msg = String_.Concat(hdr, proc.SignatureRaw(), ideAddress);
tmp.Add(msg);
}
tmp.Reverse();
for (Object o : tmp)
sb.Add_str_w_crlf((String)o);
}
static Err[] InnerAsAry(Err err) {
ListAdp errAry = ListAdp_.new_();
Err cur = Err_.as_(err);
while (cur != null) {
errAry.Add(cur);
cur = cur.Inner();
}
return (Err[])errAry.XtoAry(Err.class);
}
public static final ErrMsgWtr _ = new ErrMsgWtr(); ErrMsgWtr() {}
}

View File

@ -0,0 +1,67 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
class ErrProcData {
public String Raw() {return raw;} public ErrProcData Raw_(String val) {raw = val; return this;} private String raw = String_.Empty;
public String SignatureRaw() {return signatureRaw;} public ErrProcData SignatureRaw_(String val) {signatureRaw = val; return this;} private String signatureRaw = String_.Empty;
public String SourceFileRaw() {return sourceFileRaw;} public ErrProcData SourceFileRaw_(String val) {sourceFileRaw = val; return this;} private String sourceFileRaw = String_.Empty;
public int SourceLine() {return sourceLine;} public ErrProcData SourceLine_(int val) {sourceLine = val; return this;} int sourceLine;
public String IdeAddress() {return ideAddress;} public ErrProcData IdeAddress_(String val) {ideAddress = val; return this;} private String ideAddress = String_.Empty;
public static ErrProcData[] parse_ary_(String stackTrace) {
/*
.java
' at gplx.Err.new_(Err.java:92)
at gplx.Err.exc_(Err.java:43)
at gplx.Err_.err_(Err_.java:4)
at gplx._tst.Err__tst.RdrLoad(Err__tst.java:77)
at gplx._tst.Err__tst.MgrInit(Err__tst.java:76)'
.cs
' at gplx._tst.Err__tst.RdrLoad() in c:\000\200_dev\100.gplx\100.framework\100.core\gplx\tst\gplx\err__tst.cs:line 77
at gplx._tst.Err__tst.MgrInit(String s) in c:\000\200_dev\100.gplx\100.framework\100.core\gplx\tst\gplx\err__tst.cs:line 76'
*/
if (stackTrace == null) return new ErrProcData[0];
String[] lines = String_.SplitLines_any(stackTrace);
ListAdp list = ListAdp_.new_();
int len = Array_.Len(lines);
for (int i = 0; i < len; i++) {
ErrProcData md = ErrProcData.parse_(lines[i]);
if (md.SourceLine() == 0) break; // ASSUME: java code; not interested
if (String_.HasAtBgn(md.signatureRaw, "gplx.Err_") || String_.HasAtBgn(md.signatureRaw, "gplx.Err.")) continue; // java includes entire stackTrace from point of creation; only care about point of throw
list.Add(md);
}
return (ErrProcData[])list.XtoAry(ErrProcData.class);
}
public static ErrProcData parse_(String raw) {
ErrProcData rv = new ErrProcData().Raw_(raw);
// ex:'gplx.Err.new_(Err.java:92)'
int sigEnd = String_.FindFwd(raw, "("); if (sigEnd == String_.Find_none) return rv;
rv.signatureRaw = String_.Mid(raw, 0, sigEnd);
int filBgn = sigEnd + 1; // 1="("
int filEnd = String_.FindFwd(raw, ":", filBgn); if (filEnd == String_.Find_none) return rv;
rv.sourceFileRaw = String_.Mid(raw, filBgn, filEnd);
int linBgn = filEnd + 1; // 1=":"
int linEnd = String_.FindFwd(raw, ")", linBgn); if (linEnd == String_.Find_none) return rv;
String linRaw = String_.Mid(raw, linBgn, linEnd);
rv.sourceLine = Int_.parse_(linRaw);
rv.ideAddress = String_.Concat("(", rv.sourceFileRaw, ":", Int_.XtoStr(rv.sourceLine), ")");
return rv;
}
public static ErrProcData new_() {return new ErrProcData();} ErrProcData() {}
public static final ErrProcData Null = new ErrProcData();
}

View File

@ -0,0 +1,48 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class ErrProcData_tst {
@Test public void parse_() {
tst_parse_("gplx._tst.Err__tst.RdrLoad(MethodData_tst.java:1)"
, ErrProcData.new_()
.SignatureRaw_("gplx._tst.Err__tst.RdrLoad")
.SourceFileRaw_("MethodData_tst.java")
.SourceLine_(1)
.IdeAddress_("(MethodData_tst.java:1)")
);
}
@Test public void parse_ary_() {
String stackTrace = "";
try {ThrowException();} catch (Exception exc) {stackTrace = Err_.StackTrace_lang(exc);}
ErrProcData[] ary = ErrProcData.parse_ary_(stackTrace);
Tfds.Eq(2, Array_.Len(ary));
Tfds.Eq("gplx.ErrProcData_tst.ThrowException", ary[0].SignatureRaw());
Tfds.Eq("gplx.ErrProcData_tst.parse_ary_", ary[1].SignatureRaw());
}
Exception ThrowException() {
throw new RuntimeException("msg");
}
void tst_parse_(String raw, ErrProcData expd) {
ErrProcData actl = ErrProcData.parse_(raw);
Tfds.Eq(expd.SignatureRaw(), actl.SignatureRaw());
Tfds.Eq(expd.SourceFileRaw(), actl.SourceFileRaw());
Tfds.Eq(expd.SourceLine(), actl.SourceLine());
Tfds.Eq(expd.IdeAddress(), actl.IdeAddress());
}
}

View File

@ -0,0 +1,84 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Err_ { //_20110415
public static Err as_(Object obj) {return obj instanceof Err ? (Err)obj : null;}
public static Err new_(String fmt, Object... args) {return Err.hdr_(String_.Format(fmt, args));}
public static Err new_fmt_(String fmt, Object... args){return Err.hdr_(String_.Format(fmt, args));}
public static Err new_(String hdr) {return Err.hdr_(hdr);}
public static Err new_key_(String key, String hdr) {return Err.hdr_(hdr).Key_(key);}
public static Err err_key_(Exception exc, String key, String hdr) {return Err.exc_(exc, hdr).Key_(key);}
public static Err err_(Exception exc, String hdr) {return Err.exc_(exc, hdr);}
public static Err err_(Exception e, String fmt, Object... args) {return Err.exc_(e, String_.Format(fmt, args));}
public static Err cast_(Exception ignore, Class<?> t, Object o) {
String o_str = "";
try {o_str = Object_.XtoStr_OrNullStr(o);}
catch (Exception e) {Err_.Noop(e); o_str = "<ERROR>";}
return cast_manual_msg_(ignore, t, o_str);
}
public static Err cast_manual_msg_(Exception ignore, Class<?> t, String s) {
String msg = String_.Format("cast failed; type={0} obj={1}", ClassAdp_.NameOf_type(t), s);
return new_(msg);
}
public static void FailIfNotFound(int v, String m) {if (v == String_.Find_none) throw find_failed_(m);}
public static Err find_failed_(String find) {return Err.hdr_("find failed").Add("find", find);}
public static Err null_(String obj) {return Err.hdr_("null obj").Add("obj", obj);}
public static Err not_implemented_() {return not_implemented_msg_("method not implemented");}
public static Err not_implemented_msg_(String hdr) {return Err.hdr_(hdr);}
public static Err type_mismatch_exc_(Exception e, Class<?> t, Object o) {return type_mismatch_(t, o);} // NOTE: e passed to "soak" up variable for IDE
public static Err type_mismatch_(Class<?> t, Object o) {
return Err.hdr_("type mismatch")
.Add("expdType", ClassAdp_.FullNameOf_type(t))
.Add("actlType", ClassAdp_.NameOf_obj(o))
.Add("actlObj", Object_.XtoStr_OrNullStr(o))
;
}
public static Err missing_idx_(int idx, int len) {return Err.hdr_("index is out of bounds").Add("idx", idx).Add("len", len);}
public static Err missing_key_(String key) {return Err.hdr_("key not found").Add("key", key);}
public static Err unhandled(Object val) {return Err.hdr_("val is not in switch/if").Add("val", val);}
public static Err invalid_op_(String hdr) {return Err.hdr_(hdr);}
public static Err parse_type_(Class<?> c, String raw) {return parse_(ClassAdp_.FullNameOf_type(c), raw);}
public static Err parse_type_exc_(Exception e, Class<?> c, String raw) {return parse_(ClassAdp_.FullNameOf_type(c), raw).Add("e", Err_.Message_lang(e));}
public static Err parse_msg_(String type, String raw, String cause) {return parse_(type, raw).Add("cause", cause);}
public static Err parse_(String typeName, String raw) {return Err.hdr_("parse failed").Add("type", typeName).Add("raw", raw);}
public static final String op_canceled__const = "gplx.op_canceled";
public static Err op_canceled_usr_() {return Err_.new_key_(op_canceled__const, "canceled by usr");}
public static Err rethrow_(Exception exc) {return Err_.new_key_("rethrow", Err_.Message_lang(exc));} // NOTE: needed because throw exc does not work in java (exc must be RuntimeException, not Exception)
public static void Noop(Exception e) {}
public static String Message_lang(Exception e) {return e.getClass() + " " + e.getMessage();}
public static String Message_gplx(Exception e) {return ErrMsgWtr._.Message_gplx(e);}
public static String Message_gplx_brief(Exception e) {return ErrMsgWtr._.Message_gplx_brief(e);}
@gplx.Internal protected static String StackTrace_lang(Exception e) {
String_bldr sb = String_bldr_.new_();
StackTraceElement[] stackTraceAry = e.getStackTrace();
int len = stackTraceAry.length;
for (int i = 0; i < len; i++) {
if (i != 0) sb.Add_char_crlf();
sb.Add(stackTraceAry[i].toString());
}
return sb.XtoStr();
}
public static boolean MatchKey(Exception exc, String key) {
Err err = Err_.as_(exc); if (err == null) return false;
String msg = err.Key();
return String_.Has(msg, key);
}
}

View File

@ -0,0 +1,53 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Err_arg extends Err {
public String ArgName() {return argName;} private String argName;
public Object ArgValue() {return argValue;} Object argValue;
public static Err_arg null_(String argName) {
Err_arg rv = new Err_arg();
rv.Key_("gplx.arg").Hdr_("@" + rv.argName + " cannot be null");
rv.argName = argName;
return rv;
}
public static Err_arg cannotBe_(String msg, String argName, Object argValue) {
Err_arg rv = new Err_arg();
rv.Key_("gplx.arg");
rv.Hdr_("val cannot be " + msg);
rv.Add("key", argName);
rv.Add("val", argValue);
return rv;
}
public static Err_arg notFound_key_(String argName, Object argValue) {
Err_arg rv = new Err_arg();
rv.Key_("gplx.arg").Hdr_("arg not found").Add(argName, argValue);
rv.argName = argName;
rv.argValue = argValue;
return rv;
}
public static Err_arg outOfBounds_(String argName, int i, int count) {
Err_arg rv = new Err_arg();
rv.Key_("gplx.arg").Hdr_("arg out of bounds").Add("argName", argName).Add("argVal", i).Add("count", count);
rv.argName = argName;
rv.argValue = i;
return rv;
}
public static boolean ClassCheck(Exception e) {
return ClassAdp_.Eq_typeSafe(e, Err_arg.class);
}
}

View File

@ -0,0 +1,43 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Err_mgr {
Err_mgr(Gfo_msg_root msg_root) {this.msg_root = msg_root;} Gfo_msg_root msg_root;
public Err not_implemented_() {return Err_.new_(Msg_not_implemented.Gen_str_none());}
public Err unhandled_(Object obj) {return Err_.new_(Msg_unhandled.Gen_str_one(obj));}
public Err cast_(Exception e, Class<?> obj_class, Object obj) {return Err_.new_(Msg_cast.Gen_str_many(ClassAdp_.NameOf_type(obj_class), Object_.XtoStr_OrNullStr(obj)));}
public Err parse_(Class<?> type , byte[] raw) {return Err_.new_(Msg_parse.Gen_str_many(ClassAdp_.NameOf_type(type), String_.new_utf8_len_safe_(raw, 0, 255)));}
public Err parse_obj_(Object o , byte[] raw) {return Err_.new_(Msg_parse.Gen_str_many(ClassAdp_.NameOf_obj(o), String_.new_utf8_len_safe_(raw, 0, 255)));}
public Err parse_(String type_name, byte[] raw) {return Err_.new_(Msg_parse.Gen_str_many(type_name, String_.new_utf8_len_safe_(raw, 0, 255)));}
public Err parse_(String type_name, String raw) {return Err_.new_(Msg_parse.Gen_str_many(type_name, String_.MidByLenSafe(raw, 0, 255)));}
public Err fmt_auto_(String grp, String key, Object... vals) {return fmt_(grp, key, Bry_fmtr.New_fmt_str(key, vals), vals);}
public Err fmt_(String grp, String key, String fmt, Object... vals) {
Gfo_msg_data data = msg_root.Data_new_many(Gfo_msg_itm_.Cmd_fail, grp, key, fmt, vals);
return Err_.new_(data.Gen_str_ary());
}
public static final Err_mgr _ = new Err_mgr(Gfo_msg_root._);
static final Gfo_msg_grp GRP_OBJ = Gfo_msg_grp_.new_(Gfo_msg_grp_.Root_gplx, "Object");
static final Gfo_msg_itm
Msg_unhandled = Gfo_msg_itm_.new_fail_(GRP_OBJ, "unhandled" , "unhandled value: '~{0}'")
, Msg_cast = Gfo_msg_itm_.new_fail_(GRP_OBJ, "cast" , "cast failed; expd:'~{0}' actl:'~{1}'")
, Msg_generic = Gfo_msg_itm_.new_fail_(GRP_OBJ, "generic" , "generic error; expd:'~{0}' actl:'~{1}'")
, Msg_parse = Gfo_msg_itm_.new_fail_(GRP_OBJ, "parse" , "parse error; type:'~{0}' raw:'~{1}'")
, Msg_not_implemented = Gfo_msg_itm_.new_fail_(GRP_OBJ, "not_implemented" , "not implemented")
;
}

View File

@ -0,0 +1,34 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_data {
public int Uid() {return uid;} int uid = uid_next++;
public Gfo_msg_itm Item() {return item;} Gfo_msg_itm item;
public Object[] Vals() {return vals;} Object[] vals;
public byte[] Src_bry() {return src_bry;} private byte[] src_bry;
public int Src_bgn() {return src_bgn;} int src_bgn;
public int Src_end() {return src_end;} int src_end;
public Gfo_msg_data Ctor_val_many(Gfo_msg_itm item, Object[] vals) {this.item = item; this.vals = vals; return this;}
public Gfo_msg_data Ctor_src_many(Gfo_msg_itm item, byte[] src_bry, int src_bgn, int src_end, Object[] vals) {this.item = item; this.src_bry = src_bry; this.src_bgn = src_bgn; this.src_end = src_end; this.vals = vals; return this;}
public void Clear() {
item = null; vals = null; src_bry = null;
}
public String Gen_str_ary() {return item.Gen_str_ary(vals);}
static int uid_next = 0;
public static final Gfo_msg_data[] Ary_empty = new Gfo_msg_data[0];
}

View File

@ -0,0 +1,46 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_grp implements Gfo_msg_obj {
public Gfo_msg_grp(Gfo_msg_grp owner, int uid, byte[] key) {
this.owner = owner; this.uid = uid; this.key = key; this.key_str = String_.new_ascii_(key);
if (owner != null) {
owner.subs.Add(this);
path = Gfo_msg_grp_.Path(owner.path, key);
}
else
path = Bry_.Empty;
}
public void Subs_clear() {subs.Clear();}
public Gfo_msg_grp Owner() {return owner;} Gfo_msg_grp owner;
public int Uid() {return uid;} int uid;
public byte[] Key() {return key;} private byte[] key;
public String Key_str() {return key_str;} private String key_str;
public byte[] Path() {return path;} private byte[] path;
public String Path_str() {return String_.new_ascii_(path);}
public Gfo_msg_obj Subs_get_by_key(String sub_key) {
int subs_len = subs.Count();
for (int i = 0; i < subs_len; i++) {
Gfo_msg_obj sub = (Gfo_msg_obj)subs.FetchAt(i);
if (String_.Eq(sub_key, sub.Key_str())) return sub;
}
return null;
}
public void Subs_add(Gfo_msg_itm item) {subs.Add(item);}
ListAdp subs = ListAdp_.new_();
}

View File

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_grp_ {
public static final Gfo_msg_grp Root_gplx = new Gfo_msg_grp(null, Gfo_msg_grp_.Uid_next(), Bry_.new_ascii_("gplx"));
public static final Gfo_msg_grp Root = new Gfo_msg_grp(null, Gfo_msg_grp_.Uid_next(), Bry_.Empty);
public static Gfo_msg_grp prj_(String key) {return new Gfo_msg_grp(Root , Gfo_msg_grp_.Uid_next(), Bry_.new_ascii_(key));}
public static Gfo_msg_grp new_(Gfo_msg_grp owner, String key) {return new Gfo_msg_grp(owner , Gfo_msg_grp_.Uid_next(), Bry_.new_ascii_(key));}
public static int Uid_next() {return uid_next++;} static int uid_next = 0;
public static byte[] Path(byte[] owner_path, byte[] key) {
if (owner_path != Bry_.Empty) tmp_bfr.Add(owner_path).Add_byte(Byte_ascii.Dot); // only add "." if owner_path is available; prevents creating ".gplx"
return tmp_bfr.Add(key).XtoAryAndClear();
}
static Bry_bfr tmp_bfr = Bry_bfr.reset_(256);
}

View File

@ -0,0 +1,57 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_itm implements Gfo_msg_obj {
public Gfo_msg_itm(Gfo_msg_grp owner, int uid, byte cmd, byte[] key_bry, byte[] fmt, boolean add_to_owner) {
this.owner = owner; this.uid = uid; this.cmd = cmd; this.key_bry = key_bry; this.fmt = fmt;
this.key_str = String_.new_ascii_(key_bry);
this.path_bry = Gfo_msg_grp_.Path(owner.Path(), key_bry);
if (add_to_owner) owner.Subs_add(this);
}
public Gfo_msg_grp Owner() {return owner;} Gfo_msg_grp owner;
public int Uid() {return uid;} int uid;
public byte[] Path_bry() {return path_bry;} private byte[] path_bry;
public String Path_str() {return String_.new_utf8_(path_bry);}
public byte[] Key_bry() {return key_bry;} private byte[] key_bry;
public String Key_str() {return key_str;} private String key_str;
public Gfo_msg_obj Subs_get_by_key(String sub_key) {return null;}
public byte Cmd() {return cmd;} private byte cmd;
public byte[] Fmt() {return fmt;} private byte[] fmt;
public Bry_fmtr Fmtr() {if (fmtr == null) fmtr = Bry_fmtr.new_bry_(fmt).Compile(); return fmtr;} Bry_fmtr fmtr;
public String Gen_str_many(Object... vals) {return Gen_str_ary(vals);}
public String Gen_str_ary(Object[] vals) {
if (fmtr == null) fmtr = Bry_fmtr.new_bry_(fmt).Compile();
if (fmtr.Fmt_args_exist()) {
fmtr.Bld_bfr_many(tmp_bfr, vals);
return tmp_bfr.XtoStrAndClear();
}
else
return String_.new_utf8_(fmt);
}
public String Gen_str_one(Object val) {
if (fmtr == null) fmtr = Bry_fmtr.new_bry_(fmt).Compile();
if (fmtr.Fmt_args_exist()) {
fmtr.Bld_bfr_one(tmp_bfr, val);
return tmp_bfr.XtoStrAndClear();
}
else
return String_.new_utf8_(fmt);
}
public String Gen_str_none() {return key_str;}
static Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
}

View File

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_itm_ {
public static final byte Cmd_null = 0, Cmd_log = 1, Cmd_note = 2, Cmd_warn = 3, Cmd_stop = 4, Cmd_fail = 5;
public static final byte[][] CmdBry = new byte[][] {Bry_.new_ascii_("null"), Bry_.new_ascii_("log"), Bry_.new_ascii_("note"), Bry_.new_ascii_("warn"), Bry_.new_ascii_("stop"), Bry_.new_ascii_("fail")};
public static Gfo_msg_itm new_note_(Gfo_msg_grp owner, String key) {return new_(owner, Cmd_note, key, key);}
public static Gfo_msg_itm new_fail_(Gfo_msg_grp owner, String key, String fmt) {return new_(owner, Cmd_warn, key, fmt);}
public static Gfo_msg_itm new_warn_(Gfo_msg_grp owner, String key) {return new_(owner, Cmd_warn, key, key);}
public static Gfo_msg_itm new_warn_(Gfo_msg_grp owner, String key, String fmt) {return new_(owner, Cmd_warn, key, fmt);}
public static Gfo_msg_itm new_(Gfo_msg_grp owner, byte cmd, String key, String fmt) {return new Gfo_msg_itm(owner, Gfo_msg_grp_.Uid_next(), cmd, Bry_.new_ascii_(key), Bry_.new_ascii_(fmt), false);}
}

View File

@ -0,0 +1,54 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_log {
public Gfo_msg_log(String root_key) {root = new Gfo_msg_root(root_key);} Gfo_msg_root root;
public int Ary_len() {return ary_idx;}
public Gfo_msg_data Ary_get(int i) {return ary[i];}
public Gfo_msg_log Clear() {
for (int i = 0; i < ary_idx; i++)
ary[i].Clear();
ary_idx = 0;
return this;
}
public Gfo_msg_log Add_str_warn_key_none(String grp, String itm, byte[] src, int pos) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, null, src, pos, pos + 1, null);}
public Gfo_msg_log Add_str_warn_key_none(String grp, String itm, byte[] src, int bgn, int end) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, null, src, bgn, end, null);}
public Gfo_msg_log Add_str_warn_fmt_none(String grp, String itm, String fmt) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, fmt , Bry_.Empty, -1, -1, null);}
public Gfo_msg_log Add_str_warn_fmt_none(String grp, String itm, String fmt, byte[] src, int pos) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, fmt , src, pos, pos + 1, null);}
public Gfo_msg_log Add_str_warn_fmt_none(String grp, String itm, String fmt, byte[] src, int bgn, int end) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, fmt , src, bgn, end, null);}
public Gfo_msg_log Add_str_warn_fmt_many(String grp, String itm, String fmt, Object... vals) {return Add_str(Gfo_msg_itm_.Cmd_warn, grp, itm, fmt , Bry_.Empty, -1, -1, vals);}
Gfo_msg_log Add_str(byte cmd, String owner_key, String itm, String fmt, byte[] src, int bgn, int end, Object[] vals) {
if (ary_idx >= ary_max) ary_expand();
ary[ary_idx++] = root.Data_new_many(cmd, src, bgn, end, owner_key, itm, fmt, vals);
return this;
}
public Gfo_msg_log Add_itm_none(Gfo_msg_itm itm, byte[] src, int bgn, int end) {return Add_itm(itm, src, bgn, end, null);}
public Gfo_msg_log Add_itm_many(Gfo_msg_itm itm, byte[] src, int bgn, int end, Object... val_ary) {return Add_itm(itm, src, bgn, end, val_ary);}
Gfo_msg_log Add_itm(Gfo_msg_itm itm, byte[] src, int bgn, int end, Object[] vals) {
if (ary_idx >= ary_max) ary_expand();
ary[ary_idx++] = root.Data_new_many(itm, src, bgn, end, vals);
return this;
}
void ary_expand() {
int new_max = ary_max == 0 ? 2 : ary_max * 2;
ary = (Gfo_msg_data[])Array_.Expand(ary, new Gfo_msg_data[new_max], ary_max);
ary_max = new_max;
}
Gfo_msg_data[] ary = Gfo_msg_data.Ary_empty; int ary_idx, ary_max;
public static Gfo_msg_log Test() {return new Gfo_msg_log("test");}
}

View File

@ -0,0 +1,22 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface Gfo_msg_obj {
String Key_str();
Gfo_msg_obj Subs_get_by_key(String sub_key);
}

View File

@ -0,0 +1,80 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Gfo_msg_root {
public Gfo_msg_root(String root_key) {
this.root_key = root_key;
this.root = Gfo_msg_grp_.new_(Gfo_msg_grp_.Root, root_key);
} String root_key;
public void Data_ary_clear() {
for (int i = 0; i < data_ary_idx; i++)
data_ary[i].Clear();
data_ary_idx = 0;
}
public void Data_ary_len_(int v) {
data_ary_len = v;
data_ary = new Gfo_msg_data[data_ary_len];
for (int i = 0; i < data_ary_len; i++)
data_ary[i] = new Gfo_msg_data();
data_ary_idx = 0;
} int data_ary_len; int data_ary_idx; Gfo_msg_data[] data_ary;
public void Reset() {
root.Subs_clear();
owners.Clear();
uid_list_next = uid_item_next = 0;
Data_ary_clear();
}
public Gfo_msg_data Data_new_note_many(String owner_key, String key, String fmt, Object... vals) {return Data_new_many(Gfo_msg_itm_.Cmd_note, Bry_.Empty, -1, -1, owner_key, key, fmt, vals);}
public Gfo_msg_data Data_new_many(byte cmd, String owner_key, String key, String fmt, Object[] vals) {return Data_new_many(cmd, Bry_.Empty, -1, -1, owner_key, key, fmt, vals);}
public Gfo_msg_data Data_new_many(byte cmd, byte[] src, int bgn, int end, String owner_key, String key, String fmt, Object[] vals) {
Object owner_obj = owners.Fetch(owner_key);
Gfo_msg_grp owner = null;
if (owner_obj == null) {
owner = New_list_by_key(owner_key);
owners.Add(owner_key, owner);
}
else
owner = (Gfo_msg_grp)owner_obj;
Gfo_msg_itm itm = (Gfo_msg_itm)owner.Subs_get_by_key(key);
if (itm == null)
itm = new Gfo_msg_itm(owner, uid_item_next++, cmd, Bry_.new_utf8_(key), fmt == null ? Bry_.Empty : Bry_.new_ascii_(fmt), false);
return Data_new_many(itm, src, bgn, end, vals);
}
public Gfo_msg_data Data_new_many(Gfo_msg_itm itm, byte[] src, int bgn, int end, Object... vals) {return Data_get().Ctor_src_many(itm, src, bgn, end, vals);}
public Gfo_msg_data Data_get() {
return data_ary_idx < data_ary_len ? data_ary[data_ary_idx++] : new Gfo_msg_data();
}
Gfo_msg_grp New_list_by_key(String key) {
String[] segs = String_.Split(key, '.');
int segs_len = segs.length; int segs_last = segs_len - 1;
Gfo_msg_grp cur_list = root;
for (int i = 0; i < segs_last; i++) {
String seg = segs[i];
Gfo_msg_grp sub_list = (Gfo_msg_grp)cur_list.Subs_get_by_key(seg);
if (sub_list == null)
sub_list = new Gfo_msg_grp(cur_list, uid_list_next++, Bry_.new_ascii_(key));
cur_list = sub_list;
}
return cur_list;
}
Gfo_msg_grp root;
OrderedHash owners = OrderedHash_.new_();
int uid_list_next = 0;
int uid_item_next = 0;
public static final Gfo_msg_root _ = new Gfo_msg_root("gplx");
}

View File

@ -0,0 +1,62 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Gfo_msg_root_tst {
Gfo_msg_root_fxt fxt = new Gfo_msg_root_fxt();
@Before public void setup() {fxt.Reset();}
@Test public void Str() {
fxt.Clear().Expd_data_str_("failed a0 b0").Tst_data_new_many("proj.cls.proc", "err_0", "failed ~{0} ~{1}", "a0", "b0");
fxt.Clear().Expd_data_str_("failed a1 b1").Tst_data_new_many("proj.cls.proc", "err_0", "failed ~{0} ~{1}", "a1", "b1");
}
// @Test public void Item() { // DISABLED: no longer registering items with owner;
// fxt.Clear().Expd_item_uid_(0).Expd_item_fmtr_arg_exists_(Bool_.Y).Tst_data_new_many("proj.cls.proc", "err_0", "failed ~{0} ~{1}", "a0", "b0");
// fxt.Clear().Expd_item_uid_(1).Expd_item_fmtr_arg_exists_(Bool_.N).Tst_data_new_many("proj.cls.proc", "err_1", "failed");
// fxt.Clear().Expd_item_uid_(0).Tst_data_new_many("proj.cls.proc", "err_0", "failed ~{0} ~{1}", "a0", "b0"); // make sure item_uid stays the same
// }
@Test public void Cache() {
fxt.Mgr().Data_ary_len_(2);
fxt.Clear().Expd_data_uid_(0).Tst_data_new_many("x", "err_0", "a");
fxt.Clear().Expd_data_uid_(1).Tst_data_new_many("x", "err_0", "b");
fxt.Clear().Expd_data_uid_(2).Tst_data_new_many("x", "err_0", "a");
fxt.Mgr().Data_ary_clear();
fxt.Clear().Expd_data_uid_(0).Tst_data_new_many("x", "err_0", "a");
}
}
class Gfo_msg_root_fxt {
Gfo_msg_root root = new Gfo_msg_root("tst");
public Gfo_msg_root_fxt Reset() {root.Reset(); this.Clear(); return this;}
public Gfo_msg_root_fxt Clear() {
expd_item_uid = -1;
expd_item_fmtr_arg_exists = Bool_.__byte;
expd_data_uid = -1;
expd_data_str = null;
return this;
}
public Gfo_msg_root Mgr() {return root;}
public Gfo_msg_root_fxt Expd_data_uid_(int v) {this.expd_data_uid = v; return this;} int expd_data_uid;
public Gfo_msg_root_fxt Expd_data_str_(String v) {this.expd_data_str = v; return this;} private String expd_data_str;
public Gfo_msg_root_fxt Expd_item_uid_(int v) {this.expd_item_uid = v; return this;} int expd_item_uid;
public Gfo_msg_root_fxt Expd_item_fmtr_arg_exists_(boolean v) {this.expd_item_fmtr_arg_exists = v ? Bool_.Y_byte : Bool_.N_byte; return this;} private byte expd_item_fmtr_arg_exists;
public void Tst_data_new_many(String path, String key, String fmt, Object... vals) {
Gfo_msg_data data = root.Data_new_many(Gfo_msg_itm_.Cmd_note, path, key, fmt, vals);
if (expd_item_uid != -1) Tfds.Eq(expd_item_uid, data.Item().Uid());;
if (expd_item_fmtr_arg_exists != Bool_.__byte) Tfds.Eq(Bool_.int_(expd_item_fmtr_arg_exists), data.Item().Fmtr().Fmt_args_exist());
if (expd_data_str != null) Tfds.Eq(expd_data_str, data.Item().Gen_str_many(data.Vals()));
}
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface Cancelable {
boolean Canceled();
void Cancel();
void Cancel_reset();
}

View File

@ -0,0 +1,26 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Cancelable_ {
public static final Cancelable Never = new Cancelable_never();
}
class Cancelable_never implements Cancelable {
public boolean Canceled() {return false;}
public void Cancel() {}
public void Cancel_reset() {}
}

View File

@ -0,0 +1,20 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface CompareAble extends Comparable {} // URL:/doc/gplx/CompareAble_.txt
// public int compareTo(Object obj) {Type comp = (Type)obj; return prop.compareTo(comp.prop);}

View File

@ -0,0 +1,78 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import gplx.lists.*;
public class CompareAble_ {
public static Comparable as_(Object obj) {return obj instanceof Comparable ? (Comparable)obj : null;}
public static int Compare_obj(Object lhs, Object rhs) {return CompareComparables(as_(lhs), as_(rhs));}
public static int CompareComparables(Comparable lhs, Comparable rhs) {
if (lhs == null && rhs == null) return CompareAble_.Same;
else if (lhs == null) return CompareAble_.More;
else if (rhs == null) return CompareAble_.Less;
else return Compare(lhs, rhs);
}
public static boolean Is_more(Comparable lhs, Comparable rhs) {return Is(More, lhs, rhs);}
public static boolean Is_moreOrSame(Comparable lhs, Comparable rhs) {return Is(MoreOrSame, lhs, rhs);}
public static boolean Is_less(Comparable lhs, Comparable rhs) {return Is(Less, lhs, rhs);}
public static boolean Is_lessOrSame(Comparable lhs, Comparable rhs) {return Is(LessOrSame, lhs, rhs);}
public static boolean Is_same(Comparable lhs, Comparable rhs) {return Is(Same, lhs, rhs);}
public static boolean Is(int expt, Comparable lhs, Comparable rhs) {
int actl = CompareComparables(lhs, rhs);
if (actl == Same && expt % 2 == Same) // actl=Same and expt=(Same||MoreOrSame||LessOrSame)
return true;
else
return (actl * expt) > 0; // actl=More||Less; expd will match if on same side of 0 (ex: expt=Less; actl=Less; -1 * -1 = 1)
}
// public static int FindSlot(ComparerAble comparer, Object[] ary, Object itm) {return FindSlot(comparer, ary, itm, false);}
public static int FindSlot(ComparerAble comparer, Object[] ary, Object itm) {if (itm == null) throw Err_.null_("itm is null");
int aryLen = ary.length;
switch (aryLen) {
case 0: throw Err_.new_("ary cannot have 0 itms");
case 1: return 0;
}
int lo = -1, hi = aryLen - 1; // NOTE: -1 is necessary; see test
int curPos = (hi - lo) / 2;
int delta = 1;
while (true) {
Object curSeg = ary[curPos];
int comp = curSeg == null ? CompareAble_.More : comparer.compare(itm, curSeg); // nulls should only happen for lastAry
// if (dbg) {
// Tfds.Write(curPos, itm.toString(), comp, comp.toString(), curSeg.toString());
// }
if (comp == CompareAble_.Same) return curPos;
else if (comp > CompareAble_.Same) {lo = curPos; delta = 1;}
else if (comp < CompareAble_.Same) {hi = curPos; delta = -1;}
int dif = hi - lo;
if (dif == 1 || dif == 0) return hi; // NOTE: can be 0 when ary.length == 1 || 2; also, sometimes 0 in some situations
else curPos += (dif / 2) * delta;
}
}
public static int Compare(Comparable lhs, Comparable rhs) {return lhs.compareTo(rhs);}
public static final int
More = 1
, Less = -1
, Same = 0
, MoreOrSame = 2
, LessOrSame = -2
, ReverseMult = -1
, OffsetCompare = 1 // handle srcPos >= 1 -> srcPosChk > 0
;
public static int Multiplier(boolean v) {return v ? 1 : -1;}
}

View File

@ -0,0 +1,38 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
import gplx.lists.*;
public class CompareAble_tst implements ComparerAble {
@Test public void Basic() {
String[] slotAry = new String[] {"b", "e", "h"}; // 0=b 1=e 2=h
tst_FindSlot(slotAry, "f", "h"); // f -> 1 2 -> 2
tst_FindSlot(slotAry, "c", "e"); // c -> -1 1 -> 0 -> 0 1 -> 1
tst_FindSlot(slotAry, "a", "b"); // a -> -1 1 -> 0 -> -1 0 -> 0
}
@Test public void Null() {
String[] slotAry = new String[] {"b", "g", "l", "q", "v", null};
tst_FindSlot(slotAry, "a", "b");
tst_FindSlot(slotAry, "b", "b");
tst_FindSlot(slotAry, "c", "g");
tst_FindSlot(slotAry, "v", "v");
tst_FindSlot(slotAry, "w", null);
}
public int compare(Object lhsObj, Object rhsObj) {return CompareAble_.Compare_obj(lhsObj, rhsObj);}
void tst_FindSlot(String[] slotAry, String s, String expd) {Tfds.Eq(expd, slotAry[CompareAble_.FindSlot(this, slotAry, s)]);}
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface EqAble {
boolean Eq(Object comp);
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface InjectAble {
void Inject(Object owner);
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface NewAble {
Object NewByKey(Object o);
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface ParseAble {
Object ParseAsObj(String raw);
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class ParseAble_ {
public static final ParseAble Null = null;
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface RlsAble {
void Rls();
}

View File

@ -0,0 +1,22 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class RlsAble_ {
public static RlsAble as_(Object obj) {return obj instanceof RlsAble ? (RlsAble)obj : null;}
public static RlsAble cast_(Object obj) {try {return (RlsAble)obj;} catch(Exception exc) {throw Err_.type_mismatch_exc_(exc, RlsAble.class, obj);}}
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface SrlAble {
Object Srl(GfoMsg owner);
}

View File

@ -0,0 +1,64 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class SrlAble_ {
public static SrlAble as_(Object obj) {return obj instanceof SrlAble ? (SrlAble)obj : null;}
public static String XtoStr(GfoMsg owner) {
String_bldr sb = String_bldr_.new_();
XtoStr(owner, sb, 0, false);
return sb.XtoStr();
}
public static String XtoStr(Object o) {
SrlAble s = SrlAble_.as_(o); if (s == null) return Object_.XtoStr_OrNullStr(o);
GfoMsg m = GfoMsg_.new_parse_("root");
s.Srl(m);
return XtoStr(m);
}
static void XtoStr(GfoMsg owner, String_bldr sb, int depth, boolean indentOn) {
String indent = String_.Repeat(" ", depth * 4);
if (indentOn) sb.Add(indent);
sb.Add(owner.Key()).Add(":");
for (int i = 0; i < owner.Args_count(); i++) {
if (i != 0) sb.Add(" ");
KeyVal kv = owner.Args_getAt(i);
sb.Add(kv.Key()).Add("=").Add("'").Add(Object_.XtoStr_OrNullStr(kv.Val())).Add("'");
}
int subsCount = owner.Subs_count();
if (subsCount == 0) {
sb.Add(";");
return;
}
else if (subsCount == 1) {
sb.Add("{");
XtoStr(owner.Subs_getAt(0), sb, depth + 1, false);
sb.Add("}");
return;
}
else {
sb.Add("{");
if (subsCount > 1) sb.Add_char_crlf();
for (int i = 0; i < subsCount; i++) {
GfoMsg sub = owner.Subs_getAt(i);
XtoStr(sub, sb, depth + 1, true);
sb.Add_char_crlf();
}
sb.Add(indent);
sb.Add("}");
}
}
}

View File

@ -0,0 +1,66 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class SrlAble__tst {
@Test public void Basic() {
tst_Srl_
( GfoMsg_.new_cast_("itm").Add("key", "a").Add("val", 1)
, "itm:key='a' val='1';"
);
}
@Test public void Depth1_1() {
tst_Srl_
( GfoMsg_.new_cast_("itm").Add("key", "a").Add("val", 1).Subs_
( GfoMsg_.new_cast_("itm").Add("key", "aa").Add("val", 11)
)
, String_.Concat_lines_crlf_skipLast
( "itm:key='a' val='1'{itm:key='aa' val='11';}"
)
);
}
@Test public void Depth1_2() {
tst_Srl_
( GfoMsg_.new_cast_("itm").Add("key", "a").Add("val", 1).Subs_
( GfoMsg_.new_cast_("itm").Add("key", "aa").Add("val", 11)
, GfoMsg_.new_cast_("itm").Add("key", "ab").Add("val", 12)
)
, String_.Concat_lines_crlf_skipLast
( "itm:key='a' val='1'{"
, " itm:key='aa' val='11';"
, " itm:key='ab' val='12';"
, "}"
)
);
}
@Test public void Depth1_1_2() {
tst_Srl_
( GfoMsg_.new_cast_("itm").Add("key", "a").Add("val", 1).Subs_
( GfoMsg_.new_cast_("itm").Add("key", "aa").Add("val", 11).Subs_(
GfoMsg_.new_cast_("itm").Add("key", "aab").Add("val", 112)
)
)
, String_.Concat_lines_crlf_skipLast
( "itm:key='a' val='1'{itm:key='aa' val='11'{itm:key='aab' val='112';}}"
)
);
}
void tst_Srl_(GfoMsg m, String expd) {Tfds.Eq(expd, SrlAble_.XtoStr(m));}
}
//class SrlAble__tst

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface XtoStrAble {
String XtoStr();
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class XtoStrAble_ {
public static XtoStrAble as_(Object obj) {return obj instanceof XtoStrAble ? (XtoStrAble)obj : null;}
}

View File

@ -0,0 +1,95 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.lang.reflect.Array;
public class Array_ {
public static void Sort(Object[] obj) {ListAdp_Sorter.new_().Sort(obj, obj.length);}
public static void Sort(Object[] obj, gplx.lists.ComparerAble comparer) {ListAdp_Sorter.new_().Sort(obj, obj.length, true, comparer);}
public static ListAdp XtoList(Object ary) {
int aryLen = Array_.Len(ary);
ListAdp rv = ListAdp_.new_();
for (int i = 0; i < aryLen; i++)
rv.Add(Array_.Get(ary, i));
return rv;
}
public static Object[] Insert(Object[] cur, Object[] add, int addPos) {
int curLen = cur.length, addLen = add.length;
Object[] rv = (Object[])Array_.Create(Array_.ComponentType(cur), curLen + addLen);
for (int i = 0; i < addPos; i++) // copy old up to addPos
rv[i] = cur[i];
for (int i = 0; i < addLen; i++) // insert add
rv[i + addPos] = add[i];
for (int i = addPos; i < curLen; i++) // copy old after addPos
rv[i + addLen] = cur[i];
return rv;
}
public static Object[] ReplaceInsert(Object[] cur, Object[] add, int curReplacePos, int addInsertPos) {
int curLen = cur.length, addLen = add.length; int newLen = addLen - addInsertPos;
Object[] rv = (Object[])Array_.Create(Array_.ComponentType(cur), curLen + newLen);
for (int i = 0; i < curReplacePos; i++) // copy old up to curInsertPos; EX: curReplacePos=5, addInsertPos=2; copy up to element 3; 4, 5 are dropped
rv[i] = cur[i];
for (int i = 0; i < addLen; i++) // insert add
rv[i + curReplacePos] = add[i];
for (int i = curReplacePos + addInsertPos; i < curLen; i++) // copy old after curReplacePos
rv[i + newLen] = cur[i];
// tst_ReplaceInsert(ary_obj(0, 1, 4, 5) , ary_obj(1, 2, 3), 1, 1, ary_obj(0, 1, 2, 3, 4, 5));
// tst_ReplaceInsert(ary_obj(0, 1, 2, 4, 5), ary_obj(1, 2, 3), 1, 2, ary_obj(0, 1, 2, 3, 4, 5));//3,4 -> 4,5
return rv;
}
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 String XtoStr(Object ary) {
String_bldr sb = String_bldr_.new_();
int ary_len = Len(ary);
for (int i = 0; i < ary_len; i++)
sb.Add_obj(Get(ary, i)).Add_char_nl();
return sb.XtoStr();
}
public static int Len(Object ary) {return Array.getLength(ary);}
public static final int LenAry(Object[] ary) {return ary == null ? 0 : ary.length;}
public static Object FetchAt(Object ary, int i) {return Array.get(ary, i); }
public static Object Create(Class<?> t, int count) {return Array.newInstance(t, count);}
public static Object Get(Object ary, int i) {return Array.get(ary, i);}
public static void Set(Object ary, int i, Object o) {Array.set(ary, i, o);}
public static Object Expand(Object src, Object trg, int src_len) {
try {System.arraycopy(src, 0, trg, 0, src_len);}
catch (Exception e) {throw Err_.err_(e, "Array_.Expand failed").Add("src_len", src_len);}
return trg;
}
public static void Copy(Object src, Object trg) {System.arraycopy(src, 0, trg, 0, Len(src));}
public static void 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 Class<?> ComponentType(Object ary) {
if (ary == null) throw Err_.null_("ary");
return ary.getClass().getComponentType();
}
public static Object Resize_add(Object src, Object add) {
int srcLen = Len(src);
int trgLen = srcLen + Len(add);
Object trg = Create(ComponentType(src), trgLen);
Copy(src, trg);
for (int i = srcLen; i < trgLen; i++)
Set(trg, i, Get(add, i - srcLen));
return trg;
}
}

View File

@ -0,0 +1,41 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Array__tst {
@Test public void Resize_add() {
tst_Resize_add(ary_(), ary_(1), ary_(1)); // 0 + 1 = 1
tst_Resize_add(ary_(0), ary_(), ary_(0)); // 1 + 0 = 1
tst_Resize_add(ary_(0), ary_(1), ary_(0, 1)); // 1 + 1 = 2
} void tst_Resize_add(int[] source, int[] added, int[] expd) {Tfds.Eq_ary(expd, (int[])Array_.Resize_add(source, added));}
@Test public void Resize() {
tst_Resize(ary_(0), 0, ary_()); // 1 -> 0
tst_Resize(ary_(0, 1), 1, ary_(0)); // 2 -> 1
} void tst_Resize(int[] source, int length, int[] expd) {Tfds.Eq_ary(expd, (int[])Array_.Resize(source, length));}
@Test public void Insert() {
tst_Insert(ary_obj(0, 1, 4, 5), ary_obj(2, 3), 2, ary_obj(0, 1, 2, 3, 4, 5));
} void tst_Insert(Object[] cur, Object[] add, int addPos, Object[] expd) {Tfds.Eq_ary(expd, Array_.Insert(cur, add, addPos));}
@Test public void ReplaceInsert() {
tst_ReplaceInsert(ary_obj(0, 1, 4, 5) , ary_obj(1, 2, 3), 1, 1, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 2, 4, 5) , ary_obj(1, 2, 3), 1, 2, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 2, 3, 4, 5) , ary_obj(1, 2, 3), 1, 3, ary_obj(0, 1, 2, 3, 4, 5));
tst_ReplaceInsert(ary_obj(0, 1, 9, 4, 5) , ary_obj(2, 3) , 2, 1, ary_obj(0, 1, 2, 3, 4, 5));
} void tst_ReplaceInsert(Object[] cur, Object[] add, int curReplacePos, int addInsertPos, Object[] expd) {Tfds.Eq_ary(expd, Array_.ReplaceInsert(cur, add, curReplacePos, addInsertPos));}
Object[] ary_obj(Object... ary) {return ary;}
int[] ary_(int... ary) {return ary;}
}

View File

@ -0,0 +1,59 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bool_ implements GfoInvkAble {
public static final boolean[] Ary_empty = new boolean[0];
public static final Class<?> ClassOf = Boolean.class;
public static int XtoInt(boolean v) {return v ? 1 : 0;}
public static String XtoStr_lower(boolean v) {return v ? "true" : "false";}
public static byte Xto_byte(boolean v) {return v ? Y_byte : N_byte;}
public static boolean cast_(Object obj) {try {return (Boolean)obj;} catch (Exception e) {throw Err_.type_mismatch_exc_(e, boolean.class, obj);}}
public static boolean cast_or_(Object obj, boolean v) {try {return (Boolean)obj;} catch (Exception e) {Err_.Noop(e); return v;}}
public static boolean int_(int v) {return v != 0;}
public static boolean TypeMatch(Class<?> type) {return type == boolean.class || type == Boolean.class;}
public static boolean parse_(String raw) {
if ( String_.Eq(raw, "true")
|| String_.Eq(raw, "True") // needed for Store_Wtr(){boolVal.toString();}
)
return true;
else if ( String_.Eq(raw, "false")
|| String_.Eq(raw, "False")
)
return false;
throw Err_.parse_type_(boolean.class, raw);
}
public static final int N_int = 0, Y_int = 1, __int = -1;
public static final byte N_byte = 0, Y_byte = 1, __byte = 127;
public static final boolean N = false, Y = true;
public static final String N_str = "n", Y_str = "y";
public static final byte[] True_bry = Bry_.new_ascii_("true"), False_bry = Bry_.new_ascii_("false");
public static final byte[] Y_bry = new byte[] {Byte_ascii.Ltr_y}, N_bry = new byte[] {Byte_ascii.Ltr_n};
public static final Bool_ Gfs = new Bool_();
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_to_str)) {
boolean v = m.ReadBool(GfsCore_.Arg_primitive);
String fmt = m.ReadStrOr("fmt", null);
if (fmt == null) return v ? "true" : "false";
else if (String_.Eq(fmt, "yn")) return v ? "y" : "n";
else if (String_.Eq(fmt, "yes_no")) return v ? "yes" : "no";
else return v ? "true" : "false";
}
else return GfoInvkAble_.Rv_unhandled;
} public static final String Invk_to_str = "to_str";
}

View File

@ -0,0 +1,45 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bool_default {
public static final byte Tid_n = 0, Tid_y = 1, Tid_i = 2;
public static final String Str_n = "never", Str_y = "always", Str_i = "default";
public static final byte Chr_n = Byte_ascii.Ltr_n, Chr_y = Byte_ascii.Ltr_y, Chr_i = Byte_ascii.Ltr_i;
public static String Xto_str(byte v) {
switch (v) {
case Tid_n: return Str_n;
case Tid_y: return Str_y;
case Tid_i: return Str_i;
default: throw Err_.unhandled(v);
}
}
public static byte Xto_char_byte(byte v) {
switch (v) {
case Tid_n: return Chr_n;
case Tid_y: return Chr_y;
case Tid_i: return Chr_i;
default: throw Err_.unhandled(v);
}
}
public static byte Xto_tid(String v) {
if (String_.Eq(v, Str_n)) return Tid_n;
else if (String_.Eq(v, Str_y)) return Tid_y;
else if (String_.Eq(v, Str_i)) return Tid_i;
else throw Err_.unhandled(v);
}
}

View File

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bool_obj_ref {
public boolean Val() {return val;} private boolean val;
public Bool_obj_ref Val_y_() {val = true; return this;}
public Bool_obj_ref Val_n_() {val = false; return this;}
public Bool_obj_ref Val_(boolean v) {val = v; return this;}
public Bool_obj_ref Val_toggle_() {val = !val; return this;}
@Override public String toString() {return Bool_.XtoStr_lower(val);}
public static Bool_obj_ref n_() {return new_(false);}
public static Bool_obj_ref y_() {return new_(true);}
public static Bool_obj_ref new_(boolean val) {
Bool_obj_ref rv = new Bool_obj_ref();
rv.val = val;
return rv;
} Bool_obj_ref() {}
}

View File

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bool_obj_val {
public boolean Val() {return val == 1;}
Bool_obj_val(int v) {val = v;} int val;
public static final Bool_obj_val
Null = new Bool_obj_val(-1)
, False = new Bool_obj_val(0)
, True = new Bool_obj_val(1);
public static Bool_obj_val read_(Object o) {String s = String_.as_(o); return s == null ? (Bool_obj_val)o : parse_(s);}
public static Bool_obj_val parse_(String raw) {
if (String_.Eq(raw, "y")) return Bool_obj_val.True;
else if (String_.Eq(raw, "n")) return Bool_obj_val.False;
else if (String_.Eq(raw, "")) return Bool_obj_val.Null;
else throw Err_.parse_type_(Bool_obj_val.class, raw);
}
}

View File

@ -0,0 +1,891 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.lang.*;
import gplx.ios.*;
public class Bry_ {
public static final int NotFound = -1;
public static final byte[] Empty = new byte[0];
public static final byte[][] Ary_empty = new byte[0][];
public static final Class<?> ClassOf = byte[].class;
public static byte[] bytes_(byte... ary) {return ary;}
public static byte[] ints_ (int... ary) {
int len = ary.length;
byte[] rv = new byte[len];
for (int i = 0; i < len; i++)
rv[i] = (byte)ary[i];
return rv;
}
public static byte[] new_utf8_(String s) {
try {return s.getBytes("UTF-8");}
catch (Exception e) {throw Err_.err_(e, "unsupported encoding");}
}
public static byte[] new_ascii_(String s) {
try {return s == null ? null : s.getBytes("ASCII");}
catch (Exception e) {throw Err_.err_(e, "unsupported encoding");}
}
public static byte[] new_ascii_safe_null_(String s) {return s == null ? null : new_ascii_(s);}
public static byte[] Coalesce(byte[] orig, byte[] val_if_not_blank) {return Bry_.Len_eq_0(val_if_not_blank) ? orig : val_if_not_blank;}
public static int While_fwd(byte[] src, byte while_byte, int bgn, int end) {
for (int i = bgn; i < end; i++)
if (src[i] != while_byte) return i;
return end;
}
public static byte[][] Ary_add(byte[][] lhs, byte[][] rhs) {
int lhs_len = lhs.length, rhs_len = rhs.length;
if (lhs_len == 0) return rhs;
else if (rhs_len == 0) return lhs;
else {
byte[][] rv = new byte[lhs_len + rhs_len][];
for (int i = 0; i < lhs_len; i++)
rv[i] = lhs[i];
for (int i = 0; i < rhs_len; i++)
rv[i + lhs_len] = rhs[i];
return rv;
}
}
public static byte[][] Ary(byte[]... ary) {return ary;}
public static byte[][] Ary(String... ary) {
int ary_len = ary.length;
byte[][] rv = new byte[ary_len][];
for (int i = 0; i < ary_len; i++) {
String itm = ary[i];
rv[i] = itm == null ? null : Bry_.new_utf8_(itm);
}
return rv;
}
public static byte[][] Ary_obj(Object... ary) {
if (ary == null) return Bry_.Ary_empty;
int ary_len = ary.length;
byte[][] rv = new byte[ary_len][];
for (int i = 0; i < ary_len; i++) {
Object itm = ary[i];
rv[i] = itm == null ? null : Bry_.new_utf8_(Object_.XtoStr_OrEmpty(itm));
}
return rv;
}
public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);}
public static byte[] Repeat(byte b, int len) {
byte[] rv = new byte[len];
for (int i = 0; i < len; i++)
rv[i] = b;
return rv;
}
public static byte[] 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 void Copy_by_pos(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
int trg_adj = trg_bgn - src_bgn;
for (int i = src_bgn; i < src_end; i++)
trg[i + trg_adj] = src[i];
}
public static void Copy_by_len(byte[] src, int src_bgn, int src_len, byte[] trg, int trg_bgn) {
for (int i = 0; i < src_len; i++)
trg[i + trg_bgn] = src[i + src_bgn];
}
public static byte[][] XtoByteAryAry(String... strAry) {
int strAryLen = strAry.length;
byte[][] rv = new byte[strAryLen][];
for (int i = 0; i < strAryLen; i++)
rv[i] = Bry_.new_utf8_(strAry[i]);
return rv;
}
public static byte[] Xto_str_lower(byte[] src, int bgn, int end) {
int len = end - bgn;
byte[] rv = new byte[len];
for (int i = bgn; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
b += 32;
break;
}
rv[i - bgn] = b;
}
return rv;
}
public static byte[] Replace_one(byte[] src, byte[] find, byte[] repl) {
int src_len = src.length;
int findPos = Bry_finder.Find(src, find, 0, src_len, true); if (findPos == Bry_.NotFound) return src;
int findLen = find.length, replLen = repl.length;
int rvLen = src_len + replLen - findLen;
byte[] rv = new byte[rvLen];
Copy_by_len(src , 0 , findPos , rv, 0 );
Copy_by_len(repl, 0 , replLen , rv, findPos );
Copy_by_len(src , findPos + findLen , src_len - findPos - findLen , rv, findPos + replLen);
return rv;
}
public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);}
public static void Replace_all_direct(byte[] src, byte find, byte repl, int bgn, int end) {
for (int i = bgn; i < end; i++) {
byte b = src[i];
if (b == find) src[i] = repl;
}
}
public static byte[] Add_w_dlm(byte dlm, byte[]... ary) {
int ary_len = ary.length;
if (ary_len == 0) return Bry_.Empty;
int rv_len = ary_len - 1; // rv will have at least as many dlms as itms - 1
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (itm != null) rv_len += itm.length;
}
int rv_pos = 0;
byte[] rv = new byte[rv_len];
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (i != 0) rv[rv_pos++] = dlm;
if (itm == null) continue;
int itm_len = itm.length;
for (int j = 0; j < itm_len; j++) {
rv[rv_pos++] = itm[j];
}
}
return rv;
}
public static byte[] Add(byte[] ary, byte b) {
int ary_len = ary.length;
byte[] rv = new byte[ary_len + 1];
for (int i = 0; i < ary_len; i++)
rv[i] = ary[i];
rv[ary_len] = b;
return rv;
}
public static byte[] Add(byte b, byte[] ary) {
int ary_len = ary.length + 1;
byte[] rv = new byte[ary_len];
for (int i = 1; i < ary_len; i++)
rv[i] = ary[i - 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 (all[i] == 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 (all[i] == null) continue;
int cur_len = cur.length;
for (int j = 0; j < cur_len; j++)
rv[rv_idx++] = cur[j];
}
return rv;
}
public static int LastIdx(byte[] src) {return src.length - 1;}
public static byte[] Limit(byte[] src, int len) {
if (src == null) return null;
int src_len = src.length;
return len < src_len ? Bry_.Mid(src, 0, len) : src;
}
public static byte[] Mid_by_nearby(byte[] src, int pos, int around) {
int bgn = pos - around; if (bgn < 0) bgn = 0;
int src_len = src.length;
int end = pos + around; if (end > src_len) end = src_len;
return Mid(src, bgn, end);
}
public static byte[] Mid_by_len(byte[] src, int bgn, int len) {return Mid(src, bgn, bgn + len);}
public static byte[] Mid_by_len_safe(byte[] src, int bgn, int len) {
if (len > src.length) len = src.length;
return Mid(src, bgn, bgn + len);
}
public static String MidByLenToStr(byte[] src, int bgn, int len) {
int end = bgn + len; end = Int_.BoundEnd(end, src.length);
byte[] ary = Bry_.Mid(src, bgn, end);
return String_.new_utf8_(ary);
}
public static byte[] Mid(byte[] src, int bgn) {return Mid(src, bgn, src.length);}
public static byte[] Mid_or(byte[] src, int bgn, int end, byte[] or) {
int src_len = src.length;
if ( src == null
|| (bgn < 0 || bgn > src_len)
|| (end < 0 || end > src_len)
|| (end < bgn)
)
return or;
return Mid(src, bgn, src.length);
}
public static byte[] Mid(byte[] src, int bgn, int end) {
try {
int len = end - bgn; if (len == 0) return Bry_.Empty;
byte[] rv = new byte[len];
for (int i = bgn; i < end; i++)
rv[i - bgn] = src[i];
return rv;
} catch (Exception e) {
Err err = Err_.new_("").Add("bgn", bgn).Add("end", end);
if (src != null) err.Add("src", String_.new_utf8_len_safe_(src, bgn, 32));
if (src == null) err.Hdr_("src is null");
else if (bgn < 0 || bgn > src.length) err.Hdr_("invalid bgn");
else if (end < 0 || end > src.length) err.Hdr_("invalid end");
else if (end < bgn) err.Hdr_("end < bgn");
else err.Hdr_(Err_.Message_lang(e));
throw err;
}
}
public static byte[] mask_(int len, byte... itms) {
byte[] rv = new byte[len];
int itms_len = itms.length;
for (int i = 0; i < itms_len; i++) {
byte itm = itms[i];
rv[itm & 0xFF] = itm; // PATCH.JAVA:need to convert to unsigned byte
}
return rv;
}
public static final byte[] Trim_ary_ws = mask_(256, Byte_ascii.Tab, Byte_ascii.NewLine, Byte_ascii.CarriageReturn, Byte_ascii.Space);
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
int txt_bgn = bgn, txt_end = end;
boolean all_ws = true;
if (trim_bgn) {
for (int i = bgn; i < end; i++) {
byte b = src[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Nil) {
txt_bgn = i;
i = end;
all_ws = false;
}
}
if (all_ws) return Bry_.Empty;
}
if (trim_end) {
for (int i = end - 1; i > -1; i--) {
byte b = src[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Nil) {
txt_end = i + 1;
i = -1;
all_ws = false;
}
}
if (all_ws) return Bry_.Empty;
}
return Bry_.Mid(src, txt_bgn, txt_end);
}
public static byte[] Trim_end(byte[] v, byte trim, int end) {
boolean trimmed = false;
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len
for (; pos > -1; pos--) {
if (v[pos] == trim) {
trimmed = true;
}
else
break;
}
return trimmed ? Bry_.Mid(v, 0, pos + 1) : v;
}
public static boolean Has(byte[] src, byte lkp) {
int len = src.length;
for (int i = 0; i < len; i++)
if (src[i] == lkp) return true;
return false;
}
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 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 boolean HasAtBgn(byte[] src, byte[] lkp) {return HasAtBgn(src, lkp, 0, src.length);}
public static boolean HasAtBgn(byte[] src, byte[] lkp, int src_bgn, int srcEnd) {
int lkpLen = lkp.length;
if (lkpLen + src_bgn > srcEnd) return false; // lkp is longer than src
for (int i = 0; i < lkpLen; i++) {
if (lkp[i] != src[i + src_bgn]) return false;
}
return true;
}
public static int Skip_fwd(byte[] src, int src_bgn, byte skip) {
int src_len = src.length;
for (int i = src_bgn; i < src_len; i++) {
byte b = src[i];
if (b != skip) return i;
}
return 0;
}
public static int Skip_bwd(byte[] src, int src_bgn, byte skip) {
for (int i = src_bgn; i > -1; i--) {
byte b = src[i];
if (b != skip) return i;
}
return src.length;
}
public static int Skip_fwd_nl(byte[] src, int src_bgn) {
int src_len = src.length;
for (int i = src_bgn; i < src_len; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
break;
default:
return i;
}
}
return 0;
}
public static int Skip_bwd_nl(byte[] src, int src_bgn) {
for (int i = src_bgn; i > -1; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
break;
default:
return i;
}
}
return src.length;
}
public static byte[] Resize_manual(byte[] src, int rvLen) {
byte[] rv = new byte[rvLen];
int src_len = src.length;
if (src_len > rvLen) src_len = rvLen; // resizing smaller; only copy as many elements as in rvLen
for (int i = 0; i < src_len; i++)
rv[i] = src[i];
return rv;
}
public static byte[] Resize(byte[] src, int trgLen) {return Resize(src, 0, trgLen);}
public static byte[] Resize(byte[] src, int src_bgn, int trgLen) {
byte[] trg = new byte[trgLen];
int src_len = src.length > trgLen ? trgLen : src.length; // trgLen can either expand or shrink
Copy_by_len(src, src_bgn, src_len, trg, 0);
return trg;
}
public static boolean Match(byte[] src, byte[] find) {return Match(src, 0, src.length, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, byte[] find) {return Match(src, src_bgn, src.length, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find) {return Match(src, src_bgn, src_end, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end) {
int find_len = find_end - find_bgn;
if (find_len != src_end - src_bgn) return false;
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
for (int i = 0; i < find_len; i++) {
int pos = src_bgn + i;
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
if (src[pos] != find[i + find_bgn]) return false;
}
return true;
}
public static boolean Match_bwd_any(byte[] src, int src_end, int src_bgn, byte[] find) { // NOTE: utf8 doesn't matter (matching byte for byte)
int find_len = find.length;
for (int i = 0; i < find_len; i++) {
int src_pos = src_end - i;
int find_pos = find_len - i - 1;
if (src_pos < src_bgn) return false; // ran out of src; exit; EX: src=ab; find=abc
if (src[src_pos] != find[find_pos]) return false;
}
return true;
}
public static int Compare(byte[] lhs, byte[] rhs) {
if (lhs == null) return CompareAble_.More;
else if (rhs == null) return CompareAble_.Less;
else return Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
}
public static int Compare(byte[] lhs, int lhs_bgn, int lhs_end, byte[] rhs, int rhs_bgn, int rhs_end) {
int lhs_len = lhs_end - lhs_bgn, rhs_len = rhs_end - rhs_bgn;
int min = lhs_len < rhs_len ? lhs_len : rhs_len;
int rv = CompareAble_.Same;
for (int i = 0; i < min; i++) {
rv = (lhs[i + lhs_bgn] & 0xff) - (rhs[i + rhs_bgn] & 0xff); // PATCH.JAVA:need to convert to unsigned byte
if (rv != CompareAble_.Same) return rv > CompareAble_.Same ? CompareAble_.More : CompareAble_.Less; // NOTE: changed from if (rv != CompareAble_.Same) return rv; DATE:2013-04-25
}
return Int_.Compare(lhs_len, rhs_len); // lhs and rhs share same beginning bytes; return len comparisons
}
public static int Len(byte[] v) {return v == null ? 0 : v.length;}
public static boolean Len_gt_0(byte[] v) {return v != null && v.length > 0;}
public static boolean Len_eq_0(byte[] v) {return v == null || v.length == 0;}
public static 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 boolean Eq_itm(byte[] src, int src_len, int pos, byte chk) {
return pos < src_len
&& src[pos] == chk;
}
public static boolean Eq(byte[] lhs, byte[] rhs) {
if (lhs == null && rhs == null) return true;
else if (lhs == null || rhs == null) return false;
int lhs_len = lhs.length;
if (lhs_len != rhs.length) return false;
for (int i = 0; i < lhs_len; i++) // NOTE: lhs_len == rhsLen
if (lhs[i] != rhs[i]) return false;
return true;
}
public static boolean Eq(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++)
if (lhs[i] != rhs[i + rhs_bgn]) return false;
return true;
}
public static byte[] XtoStrBytesByInt(int val, int padLen) {return XtoStrBytesByInt(val, null, 0, padLen);}
public static byte[] XtoStrBytesByInt(int val, byte[] ary, int aryPos, int padLen) {
int neg = 0;
if (val < 0) {
val *= -1;
neg = 1;
}
int digits = val == 0 ? 0 : Math_.Log10(val);
digits += 1; // digits = log + 1; EX: Log(1-9) = 0, Log(10-99) = 1
int aryLen = digits + neg, aryBgn = aryPos, pad = 0;
if (aryLen < padLen) { // padding specified
pad = padLen - aryLen;
aryLen = padLen;
}
if (ary == null) ary = new byte[aryLen];
long factor = 1; // factor needs to be long to handle 1 billion (for which factor would be 10 billion)
for (int i = 0; i < digits; i++) // calc maxFactor
factor *= 10;
if (neg == 1) ary[0] = Byte_NegSign;
for (int i = 0; i < pad; i++) // fill ary with pad
ary[i + aryBgn] = XtoStrByte(0);
aryBgn += pad; // advance aryBgn by pad
for (int i = neg; i < aryLen - 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] = XtoStrByte(digit);
factor /= 10;
}
return ary;
}
public static byte X_to_byte_by_int(byte[] ary, int bgn, int end, byte or) {return (byte)X_to_int_or(ary, bgn, end, or);}
public static int X_to_int(byte[] ary) {return X_to_int_or(ary, null, 0, ary.length, -1);}
public static int X_to_int_or_fail(byte[] ary) {
int rv = X_to_int_or(ary, null, 0, ary.length, Int_.MinValue);
if (rv == Int_.MinValue) throw Err_.new_fmt_("could not parse to int; val={0}", String_.new_utf8_(ary));
return rv;
}
public static boolean X_to_bool_by_int_or_fail(byte[] ary) {
int rv = X_to_int_or(ary, null, 0, ary.length, Int_.MinValue);
switch (rv) {
case 0: return false;
case 1: return true;
default: throw Err_.new_fmt_("could not parse to boolean int; val={0}", String_.new_utf8_(ary));
}
}
public static int X_to_int_or(byte[] ary, int or) {return X_to_int_or(ary, null, 0, ary.length, or);}
public static int X_to_int_or(byte[] ary, int bgn, int end, int or) {return X_to_int_or(ary, null, bgn, end, or);}
public static int X_to_int_or(byte[] ary, byte[] ignore_ary, int bgn, int end, int or) {
if ( ary == null
|| end == bgn // null-len
) return or;
int rv = 0, multiple = 1;
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
rv += multiple * (b - Byte_ascii.Num_0);
multiple *= 10;
break;
case Byte_ascii.Dash:
return i == bgn ? rv * -1 : or;
case Byte_ascii.Plus:
return i == bgn ? rv : or;
default:
boolean invalid = true;
if (ignore_ary != null) {
int ignore_ary_len = ignore_ary.length;
for (int j = 0; j < ignore_ary_len; j++) {
if (b == ignore_ary[j]) {
invalid = false;
break;
}
}
}
if (invalid) return or;
break;
}
}
return rv;
}
public static int X_to_int_or_trim(byte[] ary, int bgn, int end, int or) { // NOTE: same as X_to_int_or, except trims ws at bgn / end; DATE:2014-02-09
if (end == bgn) return or; // null len
int rv = 0, multiple = 1;
boolean numbers_seen = false, ws_seen = false;
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
rv += multiple * (b - Byte_ascii.Num_0);
multiple *= 10;
if (ws_seen) // "number ws number" pattern; invalid ws in middle; see tests
return or;
numbers_seen = true;
break;
case Byte_ascii.Dash:
return i == bgn ? rv * -1 : or;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
if (numbers_seen)
ws_seen = true;
break;
default: return or;
}
}
return rv;
}
public static int X_to_int_or_lax(byte[] ary, int bgn, int end, int or) {
if (end == bgn) return or; // null-len
int end_num = end;
for (int i = bgn; i < end; i++) {
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
break;
case Byte_ascii.Dash:
if (i != bgn) {
end_num = i;
i = end;
}
break;
default:
end_num = i;
i = end;
break;
}
}
return X_to_int_or(ary, bgn, end_num, or);
}
public static float XtoFloatByPos(byte[] ary, int bgn, int end) {return Float_.parse_(String_.new_utf8_(ary, bgn, end));}
public static double XtoDoubleByPosOr(byte[] ary, int bgn, int end, double or) {return Double_.parseOr_(String_.new_utf8_(ary, bgn, end), or);}
public static double XtoDoubleByPos(byte[] ary, int bgn, int end) {return Double_.parse_(String_.new_utf8_(ary, bgn, end));}
public static DecimalAdp XtoDecimalByPos(byte[] ary, int bgn, int end) {return DecimalAdp_.parse_(String_.new_utf8_(ary, bgn, end));}
public static final byte Dlm_fld = (byte)'|', Dlm_row = (byte)'\n', Dlm_quote = (byte)'"', Dlm_null = 0, Ascii_zero = 48;
public static final String Fmt_csvDte = "yyyyMMdd HHmmss.fff";
public static DateAdp ReadCsvDte(byte[] ary, Int_obj_ref posRef, byte lkp) {// ASSUME: fmt = yyyyMMdd HHmmss.fff
int y = 0, M = 0, d = 0, H = 0, m = 0, s = 0, f = 0;
int bgn = posRef.Val();
y += (ary[bgn + 0] - Ascii_zero) * 1000;
y += (ary[bgn + 1] - Ascii_zero) * 100;
y += (ary[bgn + 2] - Ascii_zero) * 10;
y += (ary[bgn + 3] - Ascii_zero);
M += (ary[bgn + 4] - Ascii_zero) * 10;
M += (ary[bgn + 5] - Ascii_zero);
d += (ary[bgn + 6] - Ascii_zero) * 10;
d += (ary[bgn + 7] - Ascii_zero);
H += (ary[bgn + 9] - Ascii_zero) * 10;
H += (ary[bgn + 10] - Ascii_zero);
m += (ary[bgn + 11] - Ascii_zero) * 10;
m += (ary[bgn + 12] - Ascii_zero);
s += (ary[bgn + 13] - Ascii_zero) * 10;
s += (ary[bgn + 14] - Ascii_zero);
f += (ary[bgn + 16] - Ascii_zero) * 100;
f += (ary[bgn + 17] - Ascii_zero) * 10;
f += (ary[bgn + 18] - Ascii_zero);
if (ary[bgn + 19] != lkp) throw Err_.new_("csv date is invalid").Add("txt", String_.new_utf8_len_safe_(ary, bgn, 20));
posRef.Val_add(19 + 1); // +1=lkp.len
return DateAdp_.new_(y, M, d, H, m, s, f);
}
public static String ReadCsvStr(byte[] ary, Int_obj_ref posRef, byte lkp) {return String_.new_utf8_(ReadCsvBry(ary, posRef, lkp, true));}
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp) {return ReadCsvBry(ary, posRef, lkp, true);}
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp, boolean make) {
int bgn = posRef.Val(), aryLen = ary.length;
Bry_bfr bb = null;
if (aryLen > 0 && ary[0] == Dlm_quote) {
int pos = bgn + 1; // +1 to skip quote
if (make) bb = Bry_bfr.new_(16);
while (true) {
if (pos == aryLen) throw Err_.new_("endOfAry reached, but no quote found").Add("txt", String_.new_utf8_len_safe_(ary, bgn, pos));
byte b = ary[pos];
if (b == Dlm_quote) {
if (pos == aryLen - 1) throw Err_.new_("endOfAry reached, quote found but lkp not").Add("txt", String_.new_utf8_len_safe_(ary, bgn, pos));
byte next = ary[pos + 1];
if (next == Dlm_quote) { // byte followed by quote
if (make) bb.Add_byte(b);
pos += 2;
}
else if (next == lkp) {
posRef.Val_(pos + 2); // 1=endQuote;1=lkp;
return make ? bb.XtoAry() : Bry_.Empty;
}
else throw Err_.new_("quote found, but not doubled").Add("txt", String_.new_utf8_len_safe_(ary, bgn, pos + 1));
}
else {
if (make) bb.Add_byte(b);
pos++;
}
}
}
else {
for (int i = bgn; i < aryLen; i++) {
if (ary[i] == lkp) {
posRef.Val_(i + 1); // +1 = lkp.Len
return make ? Bry_.Mid(ary, bgn, i) : Bry_.Empty;
}
}
throw Err_.new_("lkp failed").Add("lkp", (char)lkp).Add("txt", String_.new_utf8_len_safe_(ary, bgn, aryLen));
}
}
public static int ReadCsvInt(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_finder.Find_fwd(ary, lkp, bgn, ary.length);
if (pos == Bry_.NotFound) throw Err_.new_("lkp failed").Add("lkp", (char)lkp).Add("bgn", bgn);
int rv = Bry_.X_to_int_or(ary, posRef.Val(), pos, -1);
posRef.Val_(pos + 1); // +1 = lkp.Len
return rv;
}
public static double ReadCsvDouble(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_finder.Find_fwd(ary, lkp, bgn, ary.length);
if (pos == Bry_.NotFound) throw Err_.new_("lkp failed").Add("lkp", (char)lkp).Add("bgn", bgn);
double rv = Bry_.XtoDoubleByPos(ary, posRef.Val(), pos);
posRef.Val_(pos + 1); // +1 = lkp.Len
return rv;
}
public static void ReadCsvNext(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_finder.Find_fwd(ary, lkp, bgn, ary.length);
posRef.Val_(pos + 1); // +1 = lkp.Len
}
public static byte Byte_NegSign = (byte)'-';
public static int XtoIntBy4Bytes(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[] XbyInt(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 byte XtoStrByte(int digit) {
switch (digit) {
case 0: return Byte_ascii.Num_0; case 1: return Byte_ascii.Num_1; case 2: return Byte_ascii.Num_2; case 3: return Byte_ascii.Num_3; case 4: return Byte_ascii.Num_4;
case 5: return Byte_ascii.Num_5; case 6: return Byte_ascii.Num_6; case 7: return Byte_ascii.Num_7; case 8: return Byte_ascii.Num_8; case 9: return Byte_ascii.Num_9;
default: throw Err_.new_("unknown digit").Add("digit", digit);
}
}
public static byte[][] Split(byte[] src, byte dlm) {return Split(src, dlm, false);}
public static byte[][] Split(byte[] src, byte dlm, boolean trim) {
if (Bry_.Len_eq_0(src)) return Bry_.Ary_empty;
int src_len = src.length, src_pos = 0, fld_bgn = 0;
ListAdp rv = ListAdp_.new_();
while (true) {
boolean last = src_pos == src_len;
byte b = last ? dlm : src[src_pos];
if (b == dlm) {
if (last && (src_pos - fld_bgn == 0)) {}
else {
byte[] itm = Bry_.Mid(src, fld_bgn, src_pos);
if (trim) itm = Bry_.Trim(itm);
rv.Add(itm);
}
fld_bgn = src_pos + 1;
}
if (last) break;
++src_pos;
}
return (byte[][])rv.XtoAry(byte[].class);
}
public static void Replace_reuse(byte[] src, byte find, byte replace) {
int src_len = src.length;
for (int i = 0; i < src_len; i++) {
if (src[i] == find) src[i] = replace;
}
}
public static byte[] Replace(byte[] src, byte find, byte replace) {
int src_len = src.length;
byte[] rv = new byte[src_len];
for (int i = 0; i < src_len; i++) {
byte b = src[i];
rv[i] = b == find ? replace : b;
}
return rv;
}
public static byte[] Replace_safe(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {
if (src == null || find == null || repl == null) return null;
return Replace(bfr, src, find, repl, 0, src.length);
}
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {return Replace(bfr, src, find, repl, 0, src.length);}
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl, int src_bgn, int src_end) {
int pos = src_bgn;
boolean dirty = false;
int find_len = find.length;
int bfr_bgn = pos;
while (pos < src_end) {
int find_pos = Bry_finder.Find_fwd(src, find, pos);
if (find_pos == Bry_finder.Not_found) break;
dirty = true;
bfr.Add_mid(src, bfr_bgn, find_pos);
bfr.Add(repl);
pos = find_pos + find_len;
bfr_bgn = pos;
}
if (dirty)
bfr.Add_mid(src, bfr_bgn, src_end);
return dirty ? bfr.XtoAryAndClear() : src;
}
public static byte[] Replace(byte[] src, byte[] find, byte[] replace) {return Replace_between(src, find, null, replace);}
public static byte[] Replace_between(byte[] src, byte[] bgn, byte[] end, byte[] replace) {
Bry_bfr bfr = Bry_bfr.new_();
boolean replace_all = end == null;
int src_len = src.length, bgn_len = bgn.length, end_len = replace_all ? 0 : end.length;
int pos = 0;
while (true) {
if (pos >= src_len) break;
int bgn_pos = Bry_finder.Find_fwd(src, bgn, pos);
if (bgn_pos == Bry_.NotFound) {
bfr.Add_mid(src, pos, src_len);
break;
}
else {
int bgn_rhs = bgn_pos + bgn_len;
int end_pos = replace_all ? bgn_rhs : Bry_finder.Find_fwd(src, end, bgn_rhs);
if (end_pos == Bry_.NotFound) {
bfr.Add_mid(src, pos, src_len);
break;
}
else {
bfr.Add_mid(src, pos, bgn_pos);
bfr.Add(replace);
pos = end_pos + end_len;
}
}
}
return bfr.XtoAryAndClear();
}
public static int Trim_end_pos(byte[] src, int end) {
for (int i = end - 1; i > -1; i--) {
switch (src[i]) {
case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn: case Byte_ascii.Space:
break;
default:
return i + 1;
}
}
return 0;
}
public static byte[][] Split(byte[] src, byte[] dlm) {
if (Bry_.Len_eq_0(src)) return Bry_.Ary_empty;
int cur_pos = 0, src_len = src.length, dlm_len = dlm.length;
ListAdp rv = ListAdp_.new_();
while (true) {
int find_pos = Bry_finder.Find_fwd(src, dlm, cur_pos);
if (find_pos == Bry_.NotFound) {
if (cur_pos == src_len) break; // dlm is last sequence in src; do not create empty itm
find_pos = src_len;
}
rv.Add(Bry_.Mid(src, cur_pos, find_pos));
if (find_pos == src_len) break;
cur_pos = find_pos + dlm_len;
}
return (byte[][])rv.XtoAry(byte[].class);
}
public static byte[][] Split_lines(byte[] src) {
if (Bry_.Len_eq_0(src)) return Bry_.Ary_empty;
int src_len = src.length, src_pos = 0, fld_bgn = 0;
ListAdp rv = ListAdp_.new_();
while (true) {
boolean last = src_pos == src_len;
byte b = last ? Byte_ascii.NewLine : src[src_pos];
int nxt_bgn = src_pos + 1;
switch (b) {
case Byte_ascii.CarriageReturn:
case Byte_ascii.NewLine:
if ( b == Byte_ascii.CarriageReturn // check for crlf
&& nxt_bgn < src_len && src[nxt_bgn] == Byte_ascii.NewLine) {
++nxt_bgn;
}
if (last && (src_pos - fld_bgn == 0)) {} // ignore trailing itms
else
rv.Add(Bry_.Mid(src, fld_bgn, src_pos));
fld_bgn = nxt_bgn;
break;
}
if (last) break;
src_pos = nxt_bgn;
}
return (byte[][])rv.XtoAry(byte[].class);
}
public static byte[] Increment_last(byte[] ary) {return Increment_last(ary, ary.length - 1);}
public static byte[] Increment_last(byte[] ary, int end_idx) {
for (int i = end_idx; i > -1; i--) {
byte end_val_old = ary[i];
byte end_val_new = (byte)(end_val_old + 1);
ary[i] = end_val_new;
if (end_val_new > (end_val_old & 0xff)) break; // PATCH.JAVA:need to convert to unsigned byte
}
return ary;
}
public static byte[] Upper_1st(byte[] ary) {
if (ary == null) return null;
int len = ary.length;
if (len == 0) return ary;
byte b = ary[0];
if (b > 96 && b < 123)
ary[0] = (byte)(b - 32);
return ary;
}
public static byte[] Upper_ascii(byte[] ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
byte b = ary[i];
if (b > 96 && b < 123)
ary[i] = (byte)(b - 32);
}
return ary;
}
public static byte[] Lower_ascii(byte[] ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
byte b = ary[i];
if (b > 64 && b < 91)
ary[i] = (byte)(b + 32);
}
return ary;
}
public static byte[] Null_if_empty(byte[] v) {return Len_eq_0(v) ? null : v;}
public static byte Get_at_end(byte[] v) {
int v_len = v.length;
return v_len == 0 ? Byte_ascii.Nil : v[v_len - 1];
}
}

View File

@ -0,0 +1,272 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
import gplx.texts.*;
public class Bry__tst {
@Test public void MidByPos() {
tst_MidByPos("abcba", 0, 1, "a");
tst_MidByPos("abcba", 0, 2, "ab");
tst_MidByPos("abcba", 1, 4, "bcb");
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_utf8_(Bry_.Mid(Bry_.new_utf8_(src), bgn, end)));}
@Test public void Replace_one() {
tst_ReplaceOne("a" , "b" , "c" , "a");
tst_ReplaceOne("b" , "b" , "c" , "c");
tst_ReplaceOne("bb" , "b" , "c" , "cb");
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_utf8_(Bry_.Replace_one(Bry_.new_utf8_(src), Bry_.new_utf8_(find), Bry_.new_utf8_(repl))));}
@Test public void XtoStrBytesByInt() {
tst_XtoStrBytesByInt(0, 0);
tst_XtoStrBytesByInt(9, 9);
tst_XtoStrBytesByInt(10, 1, 0);
tst_XtoStrBytesByInt(321, 3, 2, 1);
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
tst_XtoStrBytesByInt(Int_.MaxValue, 2,1,4,7,4,8,3,6,4,7);
}
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
byte[] expd = new byte[expdAryAsInt.length];
for (int i = 0; i < expd.length; i++) {
int expdInt = expdAryAsInt[i];
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Bry_.XtoStrByte(expdAryAsInt[i]);
}
Tfds.Eq_ary(expd, Bry_.XtoStrBytesByInt(val, Int_.DigitCount(val)));
}
@Test public void HasAtEnd() {
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
tst_HasAtEnd("abc", "bc", true); // y
tst_HasAtEnd("abc", "bd", false); // n
tst_HasAtEnd("a", "ab", false); // exceeds_len
}
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.HasAtEnd(Bry_.new_utf8_(src), Bry_.new_utf8_(find), bgn, end));}
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.HasAtEnd(Bry_.new_utf8_(src), Bry_.new_utf8_(find)));}
@Test public void HasAtBgn() {
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.HasAtBgn(Bry_.new_utf8_(src), Bry_.new_utf8_(find), bgn, end), tst);}
@Test public void Match() {
tst_Match("abc", 0, "abc", true);
tst_Match("abc", 2, "c", true);
tst_Match("abc", 0, "cde", false);
tst_Match("abc", 2, "abc", false); // bounds check
tst_Match("abc", 0, "abcd", false);
tst_Match("a" , 0, "", false);
tst_Match("" , 0, "a", false);
tst_Match("" , 0, "", true);
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_utf8_(src), srcPos, Bry_.new_utf8_(find)));}
@Test public void ReadCsvStr() {
tst_ReadCsvStr("a|" , "a");
tst_ReadCsvStr("|a|", 1 , "a");
Int_obj_ref bgn = Int_obj_ref.zero_(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
tst_ReadCsvStr("|", "");
tst_ReadCsvStr_err("a");
tst_ReadCsvStr("'a'|" , "a");
tst_ReadCsvStr("'a''b'|" , "a'b");
tst_ReadCsvStr("'a|b'|" , "a|b");
tst_ReadCsvStr("''|", "");
tst_ReadCsvStr_err("''");
tst_ReadCsvStr_err("'a'b'");
tst_ReadCsvStr_err("'a");
tst_ReadCsvStr_err("'a|");
tst_ReadCsvStr_err("'a'");
}
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
tst_XtoIntBy4Bytes(32, (byte)32); // space
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // &exist;
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
}
@Test public void XtoInt() {
tst_XtoInt("1", 1);
tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.MinValue, Int_.MinValue);
tst_XtoInt("-1", Int_.MinValue, -1);
tst_XtoInt("-123", Int_.MinValue, -123);
tst_XtoInt("123-1", Int_.MinValue, Int_.MinValue);
tst_XtoInt("+123", Int_.MinValue, 123);
tst_XtoInt("", -1);
}
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.X_to_int_or(Bry_.new_utf8_(val), or));}
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.XtoIntBy4Bytes(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.XbyInt(expd), "XbyInt");}
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.zero_() , expd);}
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.new_(bgn), expd);}
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
int bgn = bgnRef.Val();
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_utf8_(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
Tfds.Eq(expd, actl, "rv");
if (rawHasQuotes) {
int quoteAdj = String_.Count(actl, "'");
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
}
else
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
}
void tst_ReadCsvStr_err(String raw) {
try {Bry_.ReadCsvStr(Bry_.new_utf8_(String_.Replace(raw, "'", "\"")), Int_obj_ref.zero_(), (byte)'|');}
catch (Exception e) {Err_.Noop(e); return;}
Tfds.Fail_expdError();
}
@Test public void ReadCsvDte() {
tst_ReadCsvDte("20110801 221435.987");
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_utf8_(raw + "|"), Int_obj_ref.zero_(), (byte)'|'));}
@Test public void ReadCsvInt() {
tst_ReadCsvInt("1234567890");
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.parse_(raw), Bry_.ReadCsvInt(Bry_.new_utf8_(raw + "|"), Int_obj_ref.zero_(), (byte)'|'));}
@Test public void Trim() {
Trim_tst("a b c", 1, 4, "b");
Trim_tst("a c", 1, 3, "");
Trim_tst(" ", 0, 2, "");
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_utf8_(Bry_.Trim(Bry_.new_utf8_(raw), bgn, end)));}
@Test public void X_to_int_lax() {
tst_X_to_int_lax("12a", 12);
tst_X_to_int_lax("1", 1);
tst_X_to_int_lax("123", 123);
tst_X_to_int_lax("a", 0);
tst_X_to_int_lax("-1", -1);
}
private void tst_X_to_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.X_to_int_or_lax(Bry_.new_utf8_(val), 0, String_.Len(val), 0));}
@Test public void X_to_int_or_trim() {
tst_X_to_int_trim("123 " , 123);
tst_X_to_int_trim(" 123" , 123);
tst_X_to_int_trim(" 123 " , 123);
tst_X_to_int_trim(" 1 3 " , -1);
}
private void tst_X_to_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.X_to_int_or_trim(Bry_.new_utf8_(val), 0, String_.Len(val), -1));}
@Test public void Compare() {
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_utf8_(lhs), lhs_bgn, lhs_end, Bry_.new_utf8_(rhs), rhs_bgn, rhs_end));}
@Test public void Increment_last() {
tst_IncrementLast(ary_(0), ary_(1));
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
}
byte[] ary_(int... ary) {
byte[] rv = new byte[ary.length];
for (int i = 0; i < ary.length; i++)
rv[i] = Byte_.int_(ary[i]);
return rv;
}
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
@Test public void Split() {
tst_Split("a|b|c" , Byte_ascii.Pipe, "a", "b", "c");
tst_Split("a|b|c|" , Byte_ascii.Pipe, "a", "b", "c");
tst_Split("|" , Byte_ascii.Pipe, "");
tst_Split("" , Byte_ascii.Pipe);
}
void tst_Split(String raw_str, byte dlm, String... expd) {
byte[][] actl_bry = Bry_.Split(Bry_.new_ascii_(raw_str), dlm);
Tfds.Eq_ary_str(expd, String_.Ary(actl_bry));
}
@Test public void Replace_between() {
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_ascii_(Bry_.Replace_between(Bry_.new_ascii_(src), Bry_.new_ascii_(bgn), Bry_.new_ascii_(end), Bry_.new_ascii_(repl))));}
@Test public void Replace() {
Bry_bfr tmp_bfr = Bry_bfr.new_();
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
}
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
Tfds.Eq(expd, String_.new_ascii_(Bry_.Replace(tmp_bfr, Bry_.new_ascii_(src), Bry_.new_ascii_(bgn), Bry_.new_ascii_(repl))));
}
@Test public void Split_bry() {
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
Split_bry_tst("a|" , "|" , String_.Ary("a"));
}
void Split_bry_tst(String src, String dlm, String[] expd) {
String[] actl = String_.Ary(Bry_.Split(Bry_.new_ascii_(src), Bry_.new_ascii_(dlm)));
Tfds.Eq_ary_str(expd, actl);
}
@Test public void Split_lines() {
Tst_split_lines("a\nb" , "a", "b"); // basic
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
Tst_split_lines("a\rb" , "a", "b"); // cr only
}
void Tst_split_lines(String src, String... expd) {
Tfds.Eq_ary(expd, New_ary(Bry_.Split_lines(Bry_.new_ascii_(src))));
}
String[] New_ary(byte[][] lines) {
int len = lines.length;
String[] rv = new String[len];
for (int i = 0; i < len; i++)
rv[i] = String_.new_utf8_(lines[i]);
return rv;
}
@Test public void Add_w_dlm() {
Tst_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
Tst_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
Tst_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
}
void Tst_add_w_dlm(byte dlm, String[] itms, String expd) {
byte[] actl = Bry_.Add_w_dlm(dlm, Bry_.Ary(itms));
Tfds.Eq(expd, String_.new_ascii_(actl));
}
@Test public void Match_bwd_any() {
Tst_match_bwd_any("abc", 2, 0, "c", true);
Tst_match_bwd_any("abc", 2, 0, "b", false);
Tst_match_bwd_any("abc", 2, 0, "bc", true);
Tst_match_bwd_any("abc", 2, 0, "abc", true);
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
Tst_match_bwd_any("abc", 1, 0, "ab", true);
}
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_ascii_(src), src_end, src_bgn, Bry_.new_ascii_(find)));
}
private ByteAry_fxt fxt = new ByteAry_fxt();
@Test public void Trim_end() {
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.one
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
}
@Test public void XtoByteAry() {
fxt.Test_new_utf8_("a" , Bry_.ints_(97));
fxt.Test_new_utf8_("a b" , Bry_.ints_(97, 32, 98));
fxt.Test_new_utf8_("©" , Bry_.ints_(194, 169));
}
}
class ByteAry_fxt {
public void Test_trim_end(String raw, byte trim, String expd) {
byte[] raw_bry = Bry_.new_ascii_(raw);
Tfds.Eq(expd, String_.new_utf8_(Bry_.Trim_end(raw_bry, trim, raw_bry.length)));
}
public void Test_new_utf8_(String raw, byte[] expd_bry) {
Tfds.Eq_ary(expd_bry, Bry_.new_utf8_(raw));
}
}

View File

@ -0,0 +1,458 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_bfr {
public byte[] Bfr() {return bfr;} private byte[] bfr;
@gplx.Internal protected int Bfr_max() {return bfr_max;} private int bfr_max;
public int Len() {return bfr_len;} private int bfr_len;
public boolean Len_eq_0() {return bfr_len == 0;}
public boolean Len_gt_0() {return bfr_len > 0;}
public void Bfr_init(byte[] bfr, int bfr_len) {
this.bfr = bfr;
this.bfr_len = bfr_len;
this.bfr_max = bfr.length; // NOTE: must sync bfr_max, else will fail later during add; bfr will think bfr has .length of bfr_max, when it actually has .length of bfr_len; DATE:2014-03-09
}
@gplx.Internal protected int Mkr_itm() {return mkr_itm;} private int mkr_itm = -1;
@gplx.Internal protected Bry_bfr_mkr_mgr Mkr_mgr() {return mkr_mgr;} Bry_bfr_mkr_mgr mkr_mgr;
@gplx.Internal protected Bry_bfr Mkr_(Bry_bfr_mkr_mgr mkr_mgr, int itm) {this.mkr_mgr = mkr_mgr; this.mkr_itm = itm; return this;}
public Bry_bfr Mkr_rls() {mkr_mgr.Rls(this); return this;}
private void Mkr_clear() {
if (mkr_mgr != null) mkr_mgr.Rls(this);
mkr_mgr = null;
mkr_itm = -1;
}
private Bry_bfr Reset_(int v) {reset = v; return this;} private int reset;
public Bry_bfr Reset_if_gt(int limit) {
if (bfr_max > limit) {
this.bfr_max = limit;
this.bfr = new byte[limit];
}
bfr_len = 0;
return this;
}
public Bry_bfr Clear() {bfr_len = 0; return this;}
public Bry_bfr ClearAndReset() {bfr_len = 0; if (reset > 0) Reset_if_gt(reset); return this;}
public Bry_bfr Add_safe(byte[] val) {return val == null ? this : Add(val);}
public Bry_bfr Add(byte[] val) {
int val_len = val.length;
if (bfr_len + val_len > bfr_max) Resize((bfr_max + val_len) * 2);
Bry_.Copy_by_pos(val, 0, val_len, bfr, bfr_len);
// Array_.CopyTo(val, 0, bfr, bfr_len, val_len);
bfr_len += val_len;
return this;
}
public Bry_bfr Add_mid(byte[] val, int bgn, int end) {
int len = end - bgn;
if (len < 0) throw Err_.new_fmt_("negative len; bgn={0} end={1} excerpt={2}", bgn, end, String_.new_utf8_len_safe_(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
Bry_.Copy_by_pos(val, bgn, end, bfr, bfr_len);
// Array_.CopyTo(val, bgn, bfr, bfr_len, len);
bfr_len += len;
return this;
}
public Bry_bfr Add_bfr(Bry_bfr src) {
int len = src.bfr_len;
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
Bry_.Copy_by_pos(src.bfr, 0, len, bfr, bfr_len);
// Array_.CopyTo(src.bfr, 0, bfr, bfr_len, len);
bfr_len += len;
return this;
}
public Bry_bfr Add_bfr_and_clear(Bry_bfr src) {
Add_bfr(src);
src.ClearAndReset();
return this;
}
public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end) {return Add_bfr_trim_and_clear(src, trim_bgn, trim_end, Bry_.Trim_ary_ws);}
public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
int src_len = src.bfr_len;
if (bfr_len + src_len > bfr_max) Resize((bfr_max + src_len) * 2);
byte[] src_bry = src.Bfr();
int src_bgn = 0, src_end = src_len;
boolean all_ws = true;
if (trim_bgn) {
for (int i = 0; i < src_len; i++) {
byte b = src_bry[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Nil) {
src_bgn = i;
i = src_len;
all_ws = false;
}
}
if (all_ws) return this;
}
if (trim_end) {
for (int i = src_len - 1; i > -1; i--) {
byte b = src_bry[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Nil) {
src_end = i + 1;
i = -1;
all_ws = false;
}
}
if (all_ws) return this;
}
src_len = src_end - src_bgn;
Bry_.Copy_by_pos(src.bfr, src_bgn, src_end, bfr, bfr_len);
// Array_.CopyTo(src.bfr, src_bgn, bfr, bfr_len, src_len);
bfr_len += src_len;
src.Clear();
return this;
}
public Bry_bfr Add_byte_eq() {return Add_byte(Byte_ascii.Eq);}
public Bry_bfr Add_byte_pipe() {return Add_byte(Byte_ascii.Pipe);}
public Bry_bfr Add_byte_apos() {return Add_byte(Byte_ascii.Apos);}
public Bry_bfr Add_byte_quote() {return Add_byte(Byte_ascii.Quote);}
public Bry_bfr Add_byte_space() {return Add_byte(Byte_ascii.Space);}
public Bry_bfr Add_byte_nl() {return Add_byte(Byte_ascii.NewLine);}
public Bry_bfr Add_byte(byte val) {
int newPos = bfr_len + 1;
if (newPos > bfr_max) Resize(bfr_len * 2);
bfr[bfr_len] = val;
bfr_len = newPos;
return this;
}
public Bry_bfr Add_byte_repeat(byte b, int len) {
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
for (int i = 0; i < len; i++)
bfr[i + bfr_len] = b;
bfr_len += len;
return this;
}
public Bry_bfr Add_byte_if_not_last(byte b) {
if (bfr_len == 0 || (bfr_len > 0 && bfr[bfr_len - 1] == b)) return this;
this.Add_byte(b);
return this;
}
public Bry_bfr Add_utf8_int(int val) {
if (bfr_len + 4 > bfr_max) Resize((bfr_max + 4) * 2);
int utf8_len = gplx.intl.Utf16_.Encode_int(val, bfr, bfr_len);
bfr_len += utf8_len;
return this;
}
public Bry_bfr Add_bool(boolean v) {return Add(v ? Const_bool_true : Const_bool_false);} public static final byte[] Const_bool_true = Bry_.new_ascii_("true"), Const_bool_false = Bry_.new_ascii_("false");
public Bry_bfr Add_int_bool(boolean v) {return Add_int_fixed(v ? 1 : 0, 1);}
public Bry_bfr Add_int_variable(int val) {
int log10 = Int_.Log10(val);
int slots = val > -1 ? log10 + 1 : log10 * -1 + 2;
return Add_int(val, log10, slots);
}
public Bry_bfr Add_int_pad_bgn(byte pad_byte, int str_len, int val) {
int digit_len = Int_.DigitCount(val);
int pad_len = str_len - digit_len;
if (pad_len > 0) // note that this skips pad_len == 0, as well as guarding against negative pad_len; EX: pad(" ", 3, 1234) -> "1234"
Add_byte_repeat(pad_byte, pad_len);
Add_int_fixed(val, digit_len);
return this;
}
public Bry_bfr Add_int_fixed(int val, int digits) {return Add_int(val, Int_.Log10(val), digits);}
public Bry_bfr Add_int(int val, int valLog, int arySlots) {
int aryBgn = bfr_len, aryEnd = bfr_len + arySlots;
if (aryEnd > bfr_max) Resize((aryEnd) * 2);
if (val < 0) {
bfr[aryBgn++] = Byte_ascii.Dash;
val *= -1; // make positive
valLog *= -1; // valLog will be negative; make positive
arySlots -= 1; // reduce slot by 1
}
if (valLog >= arySlots) {
val %= Int_.Log10Ary[arySlots];
}
for (int i = 0; i < arySlots; i++) {
int logIdx = arySlots - i - 1;
int div = logIdx < Int_.Log10AryLen ? Int_.Log10Ary[logIdx] : Int_.MaxValue;
bfr[aryBgn + i] = (byte)((val / div) + 48);
val %= div;
}
bfr_len = aryEnd;
return this;
}
public Bry_bfr Add_long_variable(long v) {int digitCount = Long_.DigitCount(v); return Add_long(v, digitCount, digitCount);}
public Bry_bfr Add_long_fixed(long val, int digits) {return Add_long(val, Long_.DigitCount(val), digits);}
protected Bry_bfr Add_long(long val, int digitCount, int arySlots) {
int aryBgn = bfr_len, aryEnd = bfr_len + arySlots;
if (aryEnd > bfr_max) Resize((aryEnd) * 2);
if (val < 0) {
bfr[aryBgn++] = Byte_ascii.Dash;
val *= -1; // make positive
arySlots -= 1; // reduce slot by 1
}
if (digitCount >= arySlots) {
val %= Long_.Log10Ary[arySlots];
}
for (int i = 0; i < arySlots; i++) {
int logIdx = arySlots - i - 1;
long div = logIdx < Long_.Log10Ary_len ? Long_.Log10Ary[logIdx] : Long_.MaxValue;
bfr[aryBgn + i] = (byte)((val / div) + 48);
val %= div;
}
bfr_len = aryEnd;
return this;
}
public Bry_bfr Add_bry_comma(byte[] v) {return Add_bry(Byte_ascii.Comma, v);}
public Bry_bfr Add_bry(byte dlm, byte[] v) {
if (v == null) return this;
int v_len = v.length;
for (int i = 0; i < v_len; i++) {
if (i != 0) this.Add_byte(dlm);
this.Add_int_variable(v[i]);
}
return this;
}
public Bry_bfr Add_bry_escape_by_doubling(byte quote_byte, byte[] val) {return Add_bry_escape(quote_byte, quote_byte, val, 0, val.length);}
public Bry_bfr Add_bry_escape(byte quote_byte, byte escape_byte, byte[] val, int bgn, int end) {
boolean clean = true;
for (int i = bgn; i < end; i++) {
byte b = val[i];
if (clean) {
if (b == quote_byte) {
clean = false;
this.Add_mid(val, bgn, i);
this.Add_byte(escape_byte);
this.Add_byte(quote_byte);
}
else {}
}
else {
if (b == quote_byte)
this.Add_byte(escape_byte);
this.Add_byte(b);
}
}
if (clean)
Add(val);
return this;
}
public Bry_bfr Add_str(String v) {return Add(Bry_.new_utf8_(v));}
public Bry_bfr Add_float(float f) {Add_str(Float_.XtoStr(f)); return this;}
public Bry_bfr Add_double(double v) {Add_str(Double_.XtoStr(v)); return this;}
public Bry_bfr Add_dte(DateAdp val) {return Add_dte_segs(val.Year(), val.Month(),val.Day(), val.Hour(), val.Minute(), val.Second(), val.Frac());}
public Bry_bfr Add_dte_segs(int y, int M, int d, int H, int m, int s, int f) { // yyyyMMdd HHmmss.fff
if (bfr_len + 19 > bfr_max) Resize((bfr_len + 19) * 2);
bfr[bfr_len + 0] = (byte)((y / 1000) + Bry_.Ascii_zero); y %= 1000;
bfr[bfr_len + 1] = (byte)((y / 100) + Bry_.Ascii_zero); y %= 100;
bfr[bfr_len + 2] = (byte)((y / 10) + Bry_.Ascii_zero); y %= 10;
bfr[bfr_len + 3] = (byte)( y + Bry_.Ascii_zero);
bfr[bfr_len + 4] = (byte)((M / 10) + Bry_.Ascii_zero); M %= 10;
bfr[bfr_len + 5] = (byte)( M + Bry_.Ascii_zero);
bfr[bfr_len + 6] = (byte)((d / 10) + Bry_.Ascii_zero); d %= 10;
bfr[bfr_len + 7] = (byte)( d + Bry_.Ascii_zero);
bfr[bfr_len + 8] = Byte_ascii.Space;
bfr[bfr_len + 9] = (byte)((H / 10) + Bry_.Ascii_zero); H %= 10;
bfr[bfr_len + 10] = (byte)( H + Bry_.Ascii_zero);
bfr[bfr_len + 11] = (byte)((m / 10) + Bry_.Ascii_zero); m %= 10;
bfr[bfr_len + 12] = (byte)( m + Bry_.Ascii_zero);
bfr[bfr_len + 13] = (byte)((s / 10) + Bry_.Ascii_zero); s %= 10;
bfr[bfr_len + 14] = (byte)( s + Bry_.Ascii_zero);
bfr[bfr_len + 15] = Byte_ascii.Dot;
bfr[bfr_len + 16] = (byte)((f / 100) + Bry_.Ascii_zero); f %= 100;
bfr[bfr_len + 17] = (byte)((f / 10) + Bry_.Ascii_zero); f %= 10;
bfr[bfr_len + 18] = (byte)( f + Bry_.Ascii_zero);
bfr_len += 19;
return this;
}
public Bry_bfr Add_dte_utc(int y, int M, int d, int H, int m, int s, int f) { // yyyy-MM-ddTHH:mm:ssZ
if (bfr_len + 20 > bfr_max) Resize((bfr_len + 20) * 2);
bfr[bfr_len + 0] = (byte)((y / 1000) + Bry_.Ascii_zero); y %= 1000;
bfr[bfr_len + 1] = (byte)((y / 100) + Bry_.Ascii_zero); y %= 100;
bfr[bfr_len + 2] = (byte)((y / 10) + Bry_.Ascii_zero); y %= 10;
bfr[bfr_len + 3] = (byte)( y + Bry_.Ascii_zero);
bfr[bfr_len + 4] = Byte_ascii.Dash;
bfr[bfr_len + 5] = (byte)((M / 10) + Bry_.Ascii_zero); M %= 10;
bfr[bfr_len + 6] = (byte)( M + Bry_.Ascii_zero);
bfr[bfr_len + 7] = Byte_ascii.Dash;
bfr[bfr_len + 8] = (byte)((d / 10) + Bry_.Ascii_zero); d %= 10;
bfr[bfr_len + 9] = (byte)( d + Bry_.Ascii_zero);
bfr[bfr_len + 10] = Byte_ascii.Ltr_T;
bfr[bfr_len + 11] = (byte)((H / 10) + Bry_.Ascii_zero); H %= 10;
bfr[bfr_len + 12] = (byte)( H + Bry_.Ascii_zero);
bfr[bfr_len + 13] = Byte_ascii.Colon;
bfr[bfr_len + 14] = (byte)((m / 10) + Bry_.Ascii_zero); m %= 10;
bfr[bfr_len + 15] = (byte)( m + Bry_.Ascii_zero);
bfr[bfr_len + 16] = Byte_ascii.Colon;
bfr[bfr_len + 17] = (byte)((s / 10) + Bry_.Ascii_zero); s %= 10;
bfr[bfr_len + 18] = (byte)( s + Bry_.Ascii_zero);
bfr[bfr_len + 19] = Byte_ascii.Ltr_Z;
bfr_len += 20;
return this;
}
public Bry_bfr Add_swap_ws(byte[] src) {return Add_swap_ws(src, 0, src.length);}
public Bry_bfr Add_swap_ws(byte[] src, int bgn, int end) {
int len = end - bgn;
if (bfr_len + (len * 2) > bfr_max) Resize((bfr_max + (len * 2)) * 2);
for (int i = bgn; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.NewLine: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Ltr_n; bfr_len += 2; break;
case Byte_ascii.Tab: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Ltr_t; bfr_len += 2; break;
case Byte_ascii.Backslash: bfr[bfr_len] = Byte_ascii.Backslash; bfr[bfr_len + 1] = Byte_ascii.Backslash; bfr_len += 2; break;
default: bfr[bfr_len] = b; ++bfr_len; break;
}
}
return this;
}
public Bry_bfr Add_str_pad_space_bgn(String v, int pad_max) {return Add_str_pad_space(v, pad_max, Bool_.N);}
public Bry_bfr Add_str_pad_space_end(String v, int pad_max) {return Add_str_pad_space(v, pad_max, Bool_.Y);}
Bry_bfr Add_str_pad_space(String v, int pad_max, boolean pad_end) {
byte[] v_bry = Bry_.new_utf8_(v);
if (pad_end) Add(v_bry);
int pad_len = pad_max - v_bry.length;
if (pad_len > 0)
Add_byte_repeat(Byte_ascii.Space, pad_len);
if (!pad_end) Add(v_bry);
return this;
}
public Bry_bfr Add_obj(Object o) {
if (o == null) return this; // treat null as empty String;
Class<?> o_type = o.getClass();
if (o_type == byte[].class) Add((byte[])o);
else if (o_type == Integer.class) Add_int_variable(Int_.cast_(o));
else if (o_type == Byte.class) Add_byte(Byte_.cast_(o));
else if (o_type == Long.class) Add_long_variable(Long_.cast_(o));
else if (o_type == String.class) Add_str((String)o);
else if (o_type == Bry_bfr.class) Add_bfr((Bry_bfr)o);
else if (o_type == DateAdp.class) Add_dte((DateAdp)o);
else if (o_type == Io_url.class) Add(((Io_url)o).RawBry());
else if (o_type == boolean.class) Add_yn(Bool_.cast_(o));
else if (o_type == Double.class) Add_double(Double_.cast_(o));
else if (o_type == Float.class) Add_float(Float_.cast_(o));
else ((Bry_fmtr_arg)o).XferAry(this, 0);
return this;
}
public Bry_bfr Add_yn(boolean v) {Add_byte(v ? Byte_ascii.Ltr_y : Byte_ascii.Ltr_n); return this;}
public Bry_bfr Add_base85_len_5(int v) {return Add_base85(v, 5);}
public Bry_bfr Add_base85(int v, int pad) {
int new_len = bfr_len + pad;
if (new_len > bfr_max) Resize((new_len) * 2);
Base85_utl.XtoStrByAry(v, bfr, bfr_len, pad);
bfr_len = new_len;
return this;
}
public boolean Match_end_byt(byte b) {return bfr_len == 0 ? false : bfr[bfr_len - 1] == b;}
public boolean Match_end_byt_nl_or_bos() {return bfr_len == 0 ? true : bfr[bfr_len - 1] == Byte_ascii.NewLine;}
public boolean Match_end_ary(byte[] ary) {return Bry_.Match(bfr, bfr_len - ary.length, bfr_len, ary);}
public Bry_bfr Insert_at(int add_pos, byte[] add_bry) {return Insert_at(add_pos, add_bry, 0, add_bry.length);}
public Bry_bfr Insert_at(int add_pos, byte[] add_bry, int add_bgn, int add_end) {
int add_len = add_end - add_bgn;
int new_max = bfr_max + add_len;
byte[] new_bfr = new byte[new_max];
if (add_pos > 0)
Bry_.Copy_by_pos (bfr , 0, add_pos, new_bfr, 0);
Bry_.Copy_by_pos (add_bry, add_bgn, add_end, new_bfr, add_pos);
Bry_.Copy_by_pos (bfr , add_pos, bfr_len, new_bfr, add_pos + add_len);
bfr = new_bfr;
bfr_len += add_len;
bfr_max = new_max;
return this;
}
public Bry_bfr Delete_rng_to_bgn(int pos) {return Delete_rng(0, pos);}
public Bry_bfr Delete_rng_to_end(int pos) {return Delete_rng(pos, bfr_len);}
public Bry_bfr Delete_rng(int rng_bgn, int rng_end) {
int rng_len = rng_end - rng_bgn;
Bry_.Copy_by_pos(bfr, rng_end, bfr_len, bfr, rng_bgn);
bfr_len -= rng_len;
return this;
}
public Bry_bfr Del_by_1() {
bfr_len -= 1; bfr[bfr_len] = 0; return this;
}
public Bry_bfr Del_by(int count) {
int new_len = bfr_len - count;
if (new_len > -1) bfr_len = new_len;
return this;
}
public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
boolean itm_has_bytes = Bry_.Len_gt_0(itm);
if ( i != 0
&& itm_has_bytes
&& bfr_len > 0
)
this.Add(dlm);
if (itm_has_bytes)
this.Add(itm);
}
return this;
}
public boolean Eq(byte b) {return bfr_len == 1 && bfr[0] == b;}
public byte[] XtoAry() {return bfr_len == 0 ? Bry_.Empty : Bry_.Mid(bfr, 0, bfr_len);}
public byte[] XtoAryAndReset(int v) {
byte[] rv = XtoAry();
this.Clear().Reset_if_gt(v);
return rv;
}
public byte[] XtoAryAndClearAndTrim() {return XtoAryAndClearAndTrim(true, true, Bry_.Trim_ary_ws);}
public byte[] XtoAryAndClearAndTrim(boolean trim_bgn, boolean trim_end, byte[] trim_bry) {
byte[] rv = Bry_.Trim(bfr, 0, bfr_len, trim_bgn, trim_end, trim_bry);
this.Clear();
return rv;
}
public byte[] XtoAryAndClear() {
byte[] rv = XtoAry();
this.Clear();
if (reset > 0) Reset_if_gt(reset);
return rv;
}
public String XtoStr() {return String_.new_utf8_(XtoAry());}
public String XtoStrByPos(int bgn, int end) {return String_.new_utf8_(XtoAry(), bgn, end);}
public String XtoStrAndClear() {return String_.new_utf8_(XtoAryAndClear());}
public String XtoStrAndClearAndTrim() {return String_.new_utf8_(XtoAryAndClearAndTrim());}
public String XtoStrAndReset(int v) {return String_.new_utf8_(XtoAryAndReset(v));}
public int XtoIntAndClear(int or) {int rv = XtoInt(or); this.Clear(); return rv;}
public int XtoInt(int or) {
switch (bfr_len) {
case 0: return or;
case 1: {
byte b = bfr[0];
return Byte_ascii.Is_num(b) ? b - Byte_ascii.Num_0 : or;
}
default:
long rv = 0, mult = 1;
for (int i = bfr_len - 1; i > -1; i--) {
byte b = bfr[i];
if (!Byte_ascii.Is_num(b)) return or;
long dif = (b - Byte_ascii.Num_0 ) * mult;
long new_val = rv + dif;
if (new_val > Int_.MaxValue) return or; // if number is > 2^32 consider error (int overflow); return or; DATE:2014-06-10
rv = new_val;
mult *= 10;
}
return (int)rv;
}
}
public void Rls() {
bfr = null;
Mkr_clear();
}
@Override public int hashCode() {return Bry_obj_ref.CalcHashCode(bfr, 0, bfr_len);}
@Override public boolean equals(Object obj) {return obj == null ? false : Bry_.Match(bfr, 0, bfr_len, ((Bry_obj_ref)obj).Val());} // NOTE: strange, but null check needed; throws null error; PAGE:c:File:Eug<EFBFBD>ne_Delacroix_-_La_libert<EFBFBD>_guidant_le_peuple.jpg
public void Resize(int v) {
bfr_max = v;
bfr = Bry_.Resize(bfr, 0, v);
}
public static Bry_bfr new_() {return new Bry_bfr(16);}
public static Bry_bfr new_(int v) {return new Bry_bfr(v);}
public static Bry_bfr reset_(int v) {return new Bry_bfr(16).Reset_(v);} // PERF: set initial size to 16, not reset val; allows for faster "startup"; DATE:2014-06-14
Bry_bfr(int bfr_max) {
this.bfr_max = bfr_max;
this.bfr = new byte[bfr_max];
}
}

View File

@ -0,0 +1,138 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_bfr_mkr {
public static final byte Tid_b128 = 0, Tid_b512 = 1, Tid_k004 = 2, Tid_m001 = 3;
private Bry_bfr_mkr_mgr mkr_b128 = new Bry_bfr_mkr_mgr(Tid_b128, 128), mkr_b512 = new Bry_bfr_mkr_mgr(Tid_b512, 512), mkr_k004 = new Bry_bfr_mkr_mgr(Tid_k004, 4 * Io_mgr.Len_kb), mkr_m001 = new Bry_bfr_mkr_mgr(Tid_m001, 1 * Io_mgr.Len_mb);
public Bry_bfr Get_b128() {return mkr_b128.Get();}
public Bry_bfr Get_b512() {return mkr_b512.Get();}
public Bry_bfr Get_k004() {return mkr_k004.Get();}
public Bry_bfr Get_m001() {return mkr_m001.Get();}
public void Rls(Bry_bfr v) {
v.Mkr_mgr().Rls(v);
}
public void Reset_if_gt(int v) {
for (byte i = Tid_b128; i <= Tid_m001; i++)
mkr(i).Reset_if_gt(v);
}
public void Clear_fail_check() {
for (byte i = Tid_b128; i <= Tid_m001; i++)
mkr(i).Clear_fail_check();
}
public void Clear() {
for (byte i = Tid_b128; i <= Tid_m001; i++)
mkr(i).Clear();
}
Bry_bfr_mkr_mgr mkr(byte tid) {
switch (tid) {
case Tid_b128: return mkr_b128;
case Tid_b512: return mkr_b512;
case Tid_k004: return mkr_k004;
case Tid_m001: return mkr_m001;
default: throw Err_.unhandled(tid);
}
}
}
class Bry_bfr_mkr_mgr {
public Bry_bfr_mkr_mgr(byte mgr_id, int reset) {this.mgr_id = mgr_id; this.reset = reset;} private int reset;
public byte Mgr_id() {return mgr_id;} private byte mgr_id;
private Bry_bfr[] ary = Ary_empty; private int nxt_idx = 0, ary_max = 0;
private int[] free = Int_.Ary_empty; private int free_len = 0;
private Object thread_lock = new Object();
public void Reset_if_gt(int v) {
this.Clear(); // TODO: for now, just call clear
}
public void Clear_fail_check() {
synchronized (thread_lock) {
for (int i = 0; i < ary_max; i++) {
Bry_bfr itm = ary[i];
if (itm != null) {
if (itm.Mkr_mgr() != null) throw Err_.new_("failed to clear bfr: " + Int_.XtoStr(i));
itm.Clear();
}
ary[i] = null;
}
ary = Ary_empty;
free = Int_.Ary_empty;
free_len = 0;
nxt_idx = ary_max = 0;
}
}
public void Clear() {
synchronized (thread_lock) {
for (int i = 0; i < ary_max; i++) {
Bry_bfr itm = ary[i];
if (itm != null) itm.Clear();
ary[i] = null;
}
ary = Ary_empty;
free = Int_.Ary_empty;
free_len = 0;
nxt_idx = ary_max = 0;
}
}
public Bry_bfr[] Ary() {return ary;}
public int Nxt_idx() {return nxt_idx;}
public Bry_bfr Get() {
synchronized (thread_lock) {
Bry_bfr rv = null;
int rv_idx = -1;
if (free_len > 0) {
rv_idx = free[--free_len];
rv = ary[rv_idx];
}
else {
if (nxt_idx == ary_max) {
Expand();
}
rv_idx = nxt_idx++;
rv = ary[rv_idx];
if (rv == null) {
rv = Bry_bfr.reset_(reset);
ary[rv_idx] = rv;
}
}
rv.Mkr_(this, rv_idx);
return rv.Clear(); // NOTE: ALWAYS call Clear when doing Get. caller may forget to call Clear, and reused bfr may have leftover bytes. unit tests will not catch, and difficult to spot in app
}
}
private void Expand() {
int new_max = ary_max == 0 ? 2 : ary_max * 2;
Bry_bfr[] new_ary = new Bry_bfr[new_max];
Array_.CopyTo(ary, 0, new_ary, 0, ary_max);
ary = new_ary;
ary_max = new_max;
int[] new_free = new int[ary_max];
Array_.CopyTo(free, 0, new_free, 0, free_len);
free = new_free;
}
public void Rls(Bry_bfr v) {
synchronized (thread_lock) {
int idx = v.Mkr_itm();
if (idx == -1) throw Err_mgr._.fmt_("gplx.Bry_bfr", "rls_failed", "rls called on bfr that was not created by factory");
int new_ary_len = nxt_idx - 1;
if (idx == new_ary_len)
nxt_idx = new_ary_len;
else
free[free_len++] = idx;
v.Mkr_(null, -1);
}
}
public static final Bry_bfr[] Ary_empty = new Bry_bfr[0];
}

View File

@ -0,0 +1,74 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Bry_bfr_mkr_tst {
Bry_bfr_mkr_fxt fxt = new Bry_bfr_mkr_fxt();
@Before public void setup() {fxt.Clear();}
@Test public void Get_1() {fxt.Clear().Get().Tst_idxs(0);}
@Test public void Get_2() {fxt.Clear().Get().Get().Tst_idxs(0, 1);}
@Test public void Get_3() {fxt.Clear().Get().Get().Get().Tst_idxs(0, 1, 2);}
@Test public void Rls() {
fxt.Clear().Get().Rls(0).Tst_idxs();
}
@Test public void Rls_skip_1() {
fxt.Clear().Get().Get().Rls(0).Tst_idxs(-1, 1);
fxt.Get().Tst_idxs(0, 1);
}
@Test public void Rls_skip_2_1() {
fxt.Clear().Get().Get().Get().Rls(1).Rls(0).Tst_idxs(-1, -1, 2);
fxt.Get().Tst_idxs(0, -1, 2);
fxt.Get().Tst_idxs(0, 1, 2);
fxt.Get().Tst_idxs(0, 1, 2, 3);
}
@Test public void Get_rls_get() { // PURPOSE: defect in which last rls failed b/c was not doing ++ if rv existed
fxt.Clear().Get().Rls(0).Get().Get().Rls(1).Rls(0).Tst_idxs();
}
public static final int Int_null = -2;
}
class Bry_bfr_mkr_fxt {
Bry_bfr_mkr_mgr mkr;
public Bry_bfr_mkr_fxt Clear() {
if (mkr == null) {
mkr = new Bry_bfr_mkr_mgr(Byte_.Zero, 32);
}
mkr.Clear();
return this;
}
public Bry_bfr_mkr_fxt Get() {
mkr.Get();
return this;
}
public Bry_bfr_mkr_fxt Rls(int i) {
Bry_bfr bfr = mkr.Ary()[i];
mkr.Rls(bfr);
return this;
}
public Bry_bfr_mkr_fxt Tst_idxs(int... expd) {
int actl_len = mkr.Nxt_idx();
int[] actl = new int[actl_len];
for (int i = 0; i < actl_len; i++) {
Bry_bfr bfr = mkr.Ary()[i];
int actl_val = Bry_bfr_mkr_tst.Int_null;
if (bfr != null) actl_val = bfr.Mkr_itm();
actl[i] = actl_val;
}
Tfds.Eq_ary(expd, actl);
return this;
}
}

View File

@ -0,0 +1,227 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Bry_bfr_tst {
Bry_bfr bb = Bry_bfr.new_(16);
@Before public void setup() {bb.Clear();} private ByteAryBfr_fxt fxt = new ByteAryBfr_fxt();
@Test public void AddByte() {
bb = Bry_bfr.new_(2); // NOTE: make sure auto-expands
tst_AddByte("a", "a", 2);
tst_AddByte("b", "ab", 2);
tst_AddByte("c", "abc", 4);
}
@Test public void AddAry() { // NOTE: make sure auto-expands
bb = Bry_bfr.new_(2);
tst_AddByte("abcd", "abcd", 12);
}
@Test public void Add_byte_repeat() { // NOTE: make sure auto-expands
bb = Bry_bfr.new_(2);
tst_Add_byte_repeat(Byte_ascii.Space, 12, String_.Repeat(" ", 12));
} void tst_Add_byte_repeat(byte b, int len, String expd) {Tfds.Eq(expd, bb.Add_byte_repeat(b, len).XtoStrAndClear());}
void tst_AddByte(String s, String expdStr, int expdLen) {
if (String_.Len(s) == 1)
bb.Add_byte((byte)String_.CharAt(s, 0));
else
bb.Add(Bry_.new_utf8_(s));
Tfds.Eq(expdStr, String_.new_utf8_(bb.XtoAry()));
Tfds.Eq(expdLen, bb.Bfr_max());
}
@Test public void Add_dte() {
tst_AddDte("20110801 221435.987");
}
void tst_AddDte(String raw) {
bb.Add_dte(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte));
Tfds.Eq(raw, String_.new_utf8_(bb.XtoAry()));
}
@Test public void Add_int_variable() {
Add_int_variable(-1);
Add_int_variable(-12);
Add_int_variable(-1234);
Add_int_variable(2);
Add_int_variable(12);
Add_int_variable(1234);
Add_int_variable(123456789);
}
@Test public void Add_float() {
tst_Add_float(1 / 3);
tst_Add_float(-1 / 3);
}
void tst_Add_float(float v) {
bb.Add_float(v);
Tfds.Eq(v, Float_.parse_(String_.new_utf8_(bb.XtoAry())));
}
void Add_int_variable(int val) {
bb.Clear();
bb.Add_int_variable(val);
Tfds.Eq(val, Int_.parse_(String_.new_utf8_(bb.XtoAry())));
}
@Test public void Add_int_fixed_len3() {tst_Add_int_fixed(123, 3, "123");}
@Test public void Add_int_fixed_pad_1() {tst_Add_int_fixed(2, 1, "2");}
@Test public void Add_int_fixed_pad_2() {tst_Add_int_fixed(2, 2, "02");}
@Test public void Add_int_fixed_pad_16() {tst_Add_int_fixed(2, 16, "0000000000000002");} // test overflows int
@Test public void Add_int_fixed_neg() {tst_Add_int_fixed(-2, 2, "-2");}
@Test public void Add_int_fixed_neg_pad1() {tst_Add_int_fixed(-2, 1, "-");}
@Test public void Add_int_fixed_chop_1() {tst_Add_int_fixed(123, 1, "3");}
@Test public void Add_int_fixed_chop_neg() {tst_Add_int_fixed(-21, 2, "-1");}
void tst_Add_int_fixed(int val, int digits, String expd) {Tfds.Eq(expd, String_.new_utf8_(bb.Add_int_fixed(val, digits).XtoAry()));}
@Test public void Add_long_fixed_len3() {tst_Add_long_fixed(123, 3, "123");}
@Test public void Add_long_fixed_pad_1() {tst_Add_long_fixed(2, 1, "2");}
@Test public void Add_long_fixed_pad_2() {tst_Add_long_fixed(2, 2, "02");}
@Test public void Add_long_fixed_pad_16() {tst_Add_long_fixed(2, 16, "0000000000000002");} // test overflows long
@Test public void Add_long_fixed_neg() {tst_Add_long_fixed(-2, 2, "-2");}
@Test public void Add_long_fixed_neg_pad1() {tst_Add_long_fixed(-2, 1, "-");}
@Test public void Add_long_fixed_chop_1() {tst_Add_long_fixed(123, 1, "3");}
@Test public void Add_long_fixed_chop_neg() {tst_Add_long_fixed(-21, 2, "-1");}
@Test public void Add_long_fixed_large() {tst_Add_long_fixed(123456789012345L, 15, "123456789012345");}
void tst_Add_long_fixed(long val, int digits, String expd) {Tfds.Eq(expd, String_.new_utf8_(bb.Add_long_fixed(val, digits).XtoAry()));}
@Test public void AddDte_short() {
tst_AddDte_short("2010-08-26T22:38:36Z");
}
void tst_AddDte_short(String raw) {
// byte[] ary = String_.XtoByteAryAscii(raw);
// Bry_fmtr_IntBldr ib = new Bry_fmtr_IntBldr();
// int y = 0, m = 0, d = 0, h = 0, n = 0, s = 0, aryLen = ary.length;
// for (int i = 0; i < aryLen; i++) {
// byte b = ary[i];
// switch (i) {
// case 4: y = ib.XtoIntAndClear(); break;
// case 7: m = ib.XtoIntAndClear(); break;
// case 10: d = ib.XtoIntAndClear(); break;
// case 13: h = ib.XtoIntAndClear(); break;
// case 16: n = ib.XtoIntAndClear(); break;
// case 19: s = ib.XtoIntAndClear(); break;
// default: ib.Add(b); break;
// }
// }
// long l = Pow38_to(y, m, d, h, n, s);
//// Base85_utl.XtoStrByAry(l, bb.
// bb.Add_int(l);
}
// @Test public void InsertAt_str() {
// tst_InsertAt_str("", 0, "c", "c");
// tst_InsertAt_str("ab", 0, "c", "cab");
// tst_InsertAt_str("ab", 0, "cdefghij", "cdefghijab");
// }
// void tst_InsertAt_str(String orig, int insertAt, String insertStr, String expd) {
// bb = Bry_bfr.new_(16);
// bb.Add_str(orig);
// bb.InsertAt_str(insertAt, insertStr);
// String actl = bb.XtoStrAndClear();
// Tfds.Eq(expd, actl);
// }
@Test public void XtoAryAndClearAndTrim() {
tst_XtoAryAndClearAndTrim("a" , "a");
tst_XtoAryAndClearAndTrim(" a " , "a");
tst_XtoAryAndClearAndTrim(" a b " , "a b");
tst_XtoAryAndClearAndTrim(" " , "");
}
void tst_XtoAryAndClearAndTrim(String raw, String expd) {
bb.Add_str(raw);
Tfds.Eq(expd, String_.new_utf8_(bb.XtoAryAndClearAndTrim()));
}
@Test public void XtoInt() {
tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.MinValue);
tst_XtoInt("9999999999", Int_.MinValue);
}
void tst_XtoInt(String raw, int expd) {
bb.Add_str(raw);
Tfds.Eq(expd, bb.XtoIntAndClear(Int_.MinValue));
}
static long Pow38_to(int year, int month, int day, int hour, int minute, int second, int frac) {
return ((long)year) << 26
| ((long)month & 0x0f) << 22 // 16
| ((long)day & 0x1f) << 17 // 32
| ((long)hour & 0x1f) << 12 // 32
| ((long)minute & 0x3f) << 6 // 64
| ((long)second & 0x3f) // 64
;
}
static DateAdp Pow38_by(long v) {
int year = (int) (v >> 26);
int month = (int)((v >> 22) & 0x0f);
int day = (int)((v >> 17) & 0x1f);
int hour = (int)((v >> 12) & 0x1f);
int minute = (int)((v >> 6) & 0x3f);
int second = (int)((v ) & 0x3f);
return DateAdp_.new_(year, month, day, hour, minute, second, 0);
}
@Test public void Add_bfr_trimEnd_and_clear() {
tst_Add_bfr_trimEnd_and_clear("a ", "a");
}
void tst_Add_bfr_trimEnd_and_clear(String raw, String expd) {
Bry_bfr tmp = Bry_bfr.new_().Add_str(raw);
Tfds.Eq(expd, bb.Add_bfr_trim_and_clear(tmp, false, true).XtoStrAndClear());
}
@Test public void Add_bfr_trimAll_and_clear() {
tst_Add_bfr_trimAll_and_clear(" a ", "a");
tst_Add_bfr_trimAll_and_clear(" a b ", "a b");
tst_Add_bfr_trimAll_and_clear("a", "a");
tst_Add_bfr_trimAll_and_clear("", "");
}
void tst_Add_bfr_trimAll_and_clear(String raw, String expd) {
Bry_bfr tmp = Bry_bfr.new_().Add_str(raw);
Tfds.Eq(expd, bb.Add_bfr_trim_and_clear(tmp, true, true).XtoStrAndClear());
}
@Test public void Add_int_pad_bgn() {
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 0, "000");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 1, "001");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 10, "010");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 100, "100");
fxt.Test_Add_int_pad_bgn(Byte_ascii.Num_0, 3, 1000, "1000");
}
@Test public void Add_bry_escape() {
fxt.Test_Add_bry_escape("abc" , "abc"); // nothing to escape
fxt.Test_Add_bry_escape("a'bc" , "a''bc"); // single escape (code handles first quote differently)
fxt.Test_Add_bry_escape("a'b'c" , "a''b''c"); // double escape (code handles subsequent quotes different than first)
}
@Test public void Insert_at() {
fxt.Test_Insert_at("abcd", 0, "xyz" , "xyzabcd"); // bgn
fxt.Test_Insert_at("abcd", 4, "xyz" , "abcdxyz"); // end
fxt.Test_Insert_at("abcd", 2, "xyz" , "abxyzcd"); // mid
fxt.Test_Insert_at("abcd", 2, "xyz", 1, 2 , "abycd"); // mid
}
@Test public void Delete_rng() {
fxt.Test_Delete_rng("abcd", 0, 2 , "cd"); // bgn
fxt.Test_Delete_rng("abcd", 2, 4 , "ab"); // end
fxt.Test_Delete_rng("abcd", 1, 3 , "ad"); // mid
}
@Test public void Delete_rng_to_bgn() {
fxt.Test_Delete_rng_to_bgn("abcd", 2 , "cd");
}
@Test public void Delete_rng_to_end() {
fxt.Test_Delete_rng_to_end("abcd", 2 , "ab");
}
}
class ByteAryBfr_fxt {
private Bry_bfr bfr = Bry_bfr.reset_(16);
public void Clear() {
bfr.ClearAndReset();
}
public void Test_Add_int_pad_bgn(byte pad_byte, int str_len, int val, String expd) {Tfds.Eq(expd, bfr.Add_int_pad_bgn(pad_byte, str_len, val).XtoStrAndClear());}
public void Test_Add_bry_escape(String val, String expd) {
byte[] val_bry = Bry_.new_utf8_(val);
Tfds.Eq(expd, bfr.Add_bry_escape(Byte_ascii.Apos, Byte_ascii.Apos, val_bry, 0, val_bry.length).XtoStrAndClear());
}
public void Test_Insert_at(String init, int pos, String val, String expd) {Tfds.Eq(expd, bfr.Add_str(init).Insert_at(pos, Bry_.new_utf8_(val)).XtoStrAndClear());}
public void Test_Insert_at(String init, int pos, String val, int val_bgn, int val_end, String expd) {Tfds.Eq(expd, bfr.Add_str(init).Insert_at(pos, Bry_.new_utf8_(val), val_bgn, val_end).XtoStrAndClear());}
public void Test_Delete_rng(String init, int bgn, int end, String expd) {Tfds.Eq(expd, bfr.Add_str(init).Delete_rng(bgn, end).XtoStrAndClear());}
public void Test_Delete_rng_to_bgn(String init, int pos, String expd) {Tfds.Eq(expd, bfr.Add_str(init).Delete_rng_to_bgn(pos).XtoStrAndClear());}
public void Test_Delete_rng_to_end(String init, int pos, String expd) {Tfds.Eq(expd, bfr.Add_str(init).Delete_rng_to_end(pos).XtoStrAndClear());}
}

View File

@ -0,0 +1,219 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_finder {
public static final int Not_found = -1;
public static int Find_fwd(byte[] src, byte lkp) {return Find_fwd(src, lkp, 0, src.length);}
public static int Find_fwd(byte[] src, byte lkp, int cur) {return Find_fwd(src, lkp, cur, src.length);}
public static int Find_fwd(byte[] src, byte lkp, int cur, int end) {
for (int i = cur; i < end; i++)
if (src[i] == lkp) return i;
return Bry_finder.Not_found;
}
public static int Find_bwd(byte[] src, byte lkp) {return Find_bwd(src, lkp, src.length, 0);}
public static int Find_bwd(byte[] src, byte lkp, int cur) {return Find_bwd(src, lkp, cur , 0);}
public static int Find_bwd(byte[] src, byte lkp, int cur, int end) {
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
--end;
for (int i = cur; i > end; i--)
if (src[i] == lkp) return i;
return Bry_finder.Not_found;
}
public static int Find_fwd(byte[] src, byte[] lkp) {return Find(src, lkp, 0 , src.length, true);}
public static int Find_fwd(byte[] src, byte[] lkp, int cur) {return Find(src, lkp, cur , src.length, true);}
public static int Find_fwd(byte[] src, byte[] lkp, int cur, int end) {return Find(src, lkp, cur , end, true);}
public static int Find(byte[] src, byte[] lkp, int src_bgn, int src_end, boolean fwd) {
if (src_bgn < 0 || src.length == 0) return Bry_finder.Not_found;
int dif, lkp_len = lkp.length, lkp_bgn, lkp_end, src_end_chk;
if (fwd) {
if (src_bgn > src_end) return Bry_finder.Not_found;
dif = 1; lkp_bgn = 0; lkp_end = lkp_len; src_end_chk = src_end - CompareAble_.OffsetCompare;
}
else {
if (src_bgn < src_end) return Bry_finder.Not_found;
dif = -1; lkp_bgn = lkp_len - 1; lkp_end = -1; src_end_chk = src.length - CompareAble_.OffsetCompare; // src_end_chk needed when going bwd, b/c lkp_len may be > 1
}
while (src_bgn != src_end) { // while src is not done;
int lkp_cur = lkp_bgn;
while (lkp_cur != lkp_end) { // while lkp is not done
int pos = src_bgn + lkp_cur;
if ( pos > src_end_chk // outside bounds; occurs when lkp_len > 1
|| src[pos] != lkp[lkp_cur]) // srcByte doesn't match lkpByte
break;
else
lkp_cur += dif;
}
if (lkp_cur == lkp_end) return src_bgn; // lkp matches src; exit
src_bgn += dif;
}
return Bry_finder.Not_found;
}
public static int Find_bwd(byte[] src, byte[] lkp, int cur) {return Find_bwd(src, lkp, cur , 0);}
public static int Find_bwd(byte[] src, byte[] lkp, int cur, int end) {
if (cur < 1) return Bry_finder.Not_found;
--cur; // always subtract 1 from cur; allows passing in src_len or cur_pos without forcing caller to subtract - 1; DATE:2014-02-11
--end;
int src_len = src.length;
int lkp_len = lkp.length;
for (int i = cur; i > end; i--) {
if (i + lkp_len > src_len) continue; // lkp too small for pos; EX: src=abcde; lkp=bcd; pos=4
boolean match = true;
for (int j = 0; j < lkp_len; j++) {
if (lkp[j] != src[i + j]) {
match = false;
break;
}
}
if (match) return i;
}
return Bry_finder.Not_found;
}
public static int Find_bwd_last_ws(byte[] src, int cur) {
if (cur < 1) return Bry_finder.Not_found;
--cur;
int rv = Bry_finder.Not_found;
for (int i = cur; i > -1; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
rv = i;
break;
default:
i = -1;
break;
}
}
return rv;
}
public static int Find_fwd_last_ws(byte[] src, int cur) {
int end = src.length;
if (cur >= end) return Bry_finder.Not_found;
int rv = Bry_finder.Not_found;
for (int i = cur; i < end; i++) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
rv = i;
break;
default:
i = -1;
break;
}
}
return rv;
}
public static int Find_bwd_non_ws(byte[] src, int cur, int end) { // get pos of 1st char that is not ws;
if (cur >= src.length) return Bry_finder.Not_found;
for (int i = cur; i >= end; i--) {
byte b = src[i];
switch (b) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
break;
default:
return i;
}
}
return Bry_finder.Not_found;
}
public static int Find_bwd_while(byte[] src, int cur, int end, byte while_byte) {
--cur;
while (true) {
if ( cur < end
|| src[cur] != while_byte) return cur;
--cur;
}
}
public static int Find_fwd_while(byte[] src, int cur, int end, byte while_byte) {
while (true) {
if ( cur == end
|| src[cur] != while_byte) return cur;
cur++;
}
}
public static int Find_fwd_until(byte[] src, int cur, int end, byte until_byte) {
while (true) {
if ( cur == end
|| src[cur] == until_byte) return cur;
cur++;
}
}
public static int Find_fwd_while_space_or_tab(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.Space: case Byte_ascii.Tab: ++cur; break;
default: return cur;
}
}
}
public static int Find_fwd_while_ws(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn:
case Byte_ascii.Space: case Byte_ascii.Tab: ++cur; break;
default: return cur;
}
}
}
public static int Find_fwd_while_letter(byte[] src, int cur, int end) {
while (cur < end) {
switch (src[cur]) {
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e:
case Byte_ascii.Ltr_f: case Byte_ascii.Ltr_g: case Byte_ascii.Ltr_h: case Byte_ascii.Ltr_i: case Byte_ascii.Ltr_j:
case Byte_ascii.Ltr_k: case Byte_ascii.Ltr_l: case Byte_ascii.Ltr_m: case Byte_ascii.Ltr_n: case Byte_ascii.Ltr_o:
case Byte_ascii.Ltr_p: case Byte_ascii.Ltr_q: case Byte_ascii.Ltr_r: case Byte_ascii.Ltr_s: case Byte_ascii.Ltr_t:
case Byte_ascii.Ltr_u: case Byte_ascii.Ltr_v: case Byte_ascii.Ltr_w: case Byte_ascii.Ltr_x: case Byte_ascii.Ltr_y: case Byte_ascii.Ltr_z:
break;
default:
return cur;
}
++cur;
}
return cur;
}
public static int Find_fwd_while_num(byte[] src) {return Find_fwd_while_num(src, 0, src.length);}
public static int Find_fwd_while_num(byte[] src, int cur, int end) {
while (cur < end) {
if (!Byte_ascii.Is_num(src[cur]))
return cur;
++cur;
}
return cur;
}
public static int Find_fwd_while_not_ws(byte[] src, int cur, int end) {
while (true) {
if (cur == end) return cur;
switch (src[cur]) {
case Byte_ascii.Space:
case Byte_ascii.NewLine:
case Byte_ascii.Tab:
case Byte_ascii.CarriageReturn:
++cur;
break;
default:
return cur;
}
}
}
}

View File

@ -0,0 +1,47 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
import gplx.texts.*;
public class Bry_finder_tst {
@Test public void Find_fwd() {
tst_Find_fwd("abcba", "b", 0, 1);
tst_Find_fwd("abcba", "z", 0, -1);
tst_Find_fwd("abcba", "b", 1, 1);
tst_Find_fwd("abcba", "b", 2, 3);
tst_Find_fwd("abcba", "b", 4, -1);
tst_Find_fwd("abcba", "zb", 4, -1);
tst_Find_fwd("abcba", "a", 6, -1);
} void tst_Find_fwd(String src, String lkp, int bgn, int expd) {Tfds.Eq(expd, Bry_finder.Find_fwd(Bry_.new_utf8_(src), Bry_.new_utf8_(lkp), bgn));}
@Test public void Find_bwd() {
tst_Find_bwd("abcba", "b", 4, 3);
tst_Find_bwd("abcba", "z", 4, -1);
tst_Find_bwd("abcba", "b", 3, 1);
tst_Find_bwd("abcba", "b", 2, 1);
tst_Find_bwd("abcba", "b", 0, -1);
tst_Find_bwd("abcba", "zb", 4, -1);
tst_Find_fwd("abcba", "a", -1, -1);
tst_Find_bwd("abcba", "ab", 4, 0);
} void tst_Find_bwd(String src, String lkp, int bgn, int expd) {Tfds.Eq(expd, Bry_finder.Find_bwd(Bry_.new_utf8_(src), Bry_.new_utf8_(lkp), bgn));}
@Test public void Find_bwd_last_ws() {
Find_bwd_1st_ws_tst("a b" , 2, 1); // basic
Find_bwd_1st_ws_tst("a b" , 3, 1); // multiple
Find_bwd_1st_ws_tst("ab" , 1, Bry_.NotFound); // none
}
void Find_bwd_1st_ws_tst(String src, int pos, int expd) {Tfds.Eq(expd, Bry_finder.Find_bwd_last_ws(Bry_.new_ascii_(src), pos));}
}

View File

@ -0,0 +1,262 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_fmtr {
public byte[] Fmt() {return fmt;} private byte[] fmt = Bry_.Empty;
public boolean Fmt_null() {return fmt.length == 0;}
public Bry_fmtr_eval_mgr Eval_mgr() {return eval_mgr;} public Bry_fmtr Eval_mgr_(Bry_fmtr_eval_mgr v) {eval_mgr = v; return this;} Bry_fmtr_eval_mgr eval_mgr = Bry_fmtr_eval_mgr_gfs._;
public Bry_fmtr Fmt_(byte[] v) {fmt = v; dirty = true; return this;} public Bry_fmtr Fmt_(String v) {return Fmt_(Bry_.new_utf8_(v));}
public Bry_fmtr Keys_(String... ary) {
if (keys == null) keys = HashAdp_.new_();
else keys.Clear();
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++)
keys.Add(Bry_obj_ref.new_(Bry_.new_utf8_(ary[i])), Int_obj_val.new_(i));
dirty = true;
return this;
} HashAdp keys = null;
public void Bld_bfr(Bry_bfr bfr, byte[]... args) {
if (dirty) Compile();
int args_len = args.length;
for (int i = 0; i < itms_len; i++) {
Bry_fmtr_itm itm = itms[i];
if (itm.Arg) {
int arg_idx = itm.ArgIdx;
if (arg_idx < args_len)
bfr.Add(args[arg_idx]);
else
bfr.Add(missing_bgn).Add_int_variable(arg_idx + missing_adj).Add(missing_end);
}
else
bfr.Add(itm.Dat);
}
}
public void Bld_bfr_none(Bry_bfr bfr) {
if (dirty) Compile();
for (int i = 0; i < itms_len; i++) {
Bry_fmtr_itm itm = itms[i];
if (itm.Arg)
bfr.Add_byte(char_escape).Add_byte(char_arg_bgn).Add_int_variable(itm.ArgIdx).Add_byte(char_arg_end);
else
bfr.Add(itm.Dat);
}
}
public void Bld_bfr(Bry_bfr bfr, Bry_fmtr_arg... args) {
if (dirty) Compile();
for (int i = 0; i < itms_len; i++) {
Bry_fmtr_itm itm = itms[i];
if (itm.Arg)
args[itm.ArgIdx].XferAry(bfr, itm.ArgIdx);
else
bfr.Add(itm.Dat);
}
}
public void Bld_bfr_one(Bry_bfr bfr, Object val) {
Bld_bfr_one_ary[0] = val;
Bld_bfr_ary(bfr, Bld_bfr_one_ary);
} Object[] Bld_bfr_one_ary = new Object[1];
public void Bld_bfr_many(Bry_bfr bfr, Object... args) {Bld_bfr_ary(bfr, args);}
public void Bld_bfr_ary(Bry_bfr bfr, Object[] args) {
if (dirty) Compile();
int args_len = args.length;
for (int i = 0; i < itms_len; i++) {
Bry_fmtr_itm itm = itms[i];
if (itm.Arg) {
int arg_idx = itm.ArgIdx;
if (arg_idx > -1 && arg_idx < args_len)
bfr.Add_obj(args[itm.ArgIdx]);
else
bfr.Add_byte(char_escape).Add_byte(char_arg_bgn).Add_int_variable(arg_idx).Add_byte(char_arg_end);
}
else
bfr.Add(itm.Dat);
}
}
public byte[] Bld_bry_none(Bry_bfr bfr) {Bld_bfr_ary(bfr, Object_.Ary_empty); return bfr.XtoAryAndClear();}
public byte[] Bld_bry_many(Bry_bfr bfr, Object... args) {
Bld_bfr_ary(bfr, args);
return bfr.XtoAryAndClear();
}
public String Bld_str_many(Bry_bfr bfr, String fmt, Object... args) {
this.Fmt_(fmt).Bld_bfr_many(bfr, args);
return bfr.XtoStrAndClear();
}
public String Bld_str_many(String... args) {
if (dirty) Compile();
String_bldr rv = String_bldr_.new_();
int args_len = args.length;
for (int i = 0; i < itms_len; i++) {
Bry_fmtr_itm itm = itms[i];
if (itm.Arg) {
int arg_idx = itm.ArgIdx;
if (arg_idx < args_len)
rv.Add(args[arg_idx]);
else
rv.Add(missing_bgn).Add(arg_idx + missing_adj).Add(missing_end);
}
else
rv.Add(itm.DatStr());
}
return rv.XtoStr();
} private Bry_fmtr_itm[] itms; int itms_len;
public byte[] Missing_bgn() {return missing_bgn;} public Bry_fmtr Missing_bgn_(byte[] v) {missing_bgn = v; return this;} private byte[] missing_bgn = missing_bgn_static; static byte[] missing_bgn_static = Bry_.new_utf8_("~{"), missing_end_static = Bry_.new_utf8_("}");
public byte[] Missing_end() {return missing_end;} public Bry_fmtr Missing_end_(byte[] v) {missing_end = v; return this;} private byte[] missing_end = missing_end_static;
public int Missing_adj() {return missing_adj;} public Bry_fmtr Missing_adj_(int v) {missing_adj = v; return this;} int missing_adj;
public boolean Fail_when_invalid_escapes() {return fail_when_invalid_escapes;} public Bry_fmtr Fail_when_invalid_escapes_(boolean v) {fail_when_invalid_escapes = v; return this;} private boolean fail_when_invalid_escapes = true;
public Bry_fmtr Compile() {
Bry_bfr lkp_bfr = Bry_bfr.new_(16);
int fmt_len = fmt.length; int fmt_end = fmt_len - 1; int fmt_pos = 0;
byte[] trg_bry = new byte[fmt_len]; int trg_pos = 0;
boolean lkp_is_active = false, lkp_is_numeric = true;
byte nxt_byte, tmp_byte;
ListAdp list = ListAdp_.new_();
fmt_args_exist = false;
while (true) {
if (fmt_pos > fmt_end) break;
byte cur_byte = fmt[fmt_pos];
if (lkp_is_active) {
if (cur_byte == char_arg_end) {
if (lkp_is_numeric)
list.Add(Bry_fmtr_itm.arg_(lkp_bfr.XtoInt(0) - baseInt));
else {
byte[] key_fmt = lkp_bfr.XtoAry();
Object idx_ref = keys.Fetch(Bry_obj_ref.new_(key_fmt));
if (idx_ref == null) {
int lkp_bfr_len = lkp_bfr.Len();
byte[] lkp_bry = lkp_bfr.Bfr();
trg_bry[trg_pos++] = char_escape;
trg_bry[trg_pos++] = char_arg_bgn;
for (int i = 0; i < lkp_bfr_len; i++)
trg_bry[trg_pos++] = lkp_bry[i];
trg_bry[trg_pos++] = char_arg_end;
}
else {
list.Add(Bry_fmtr_itm.arg_(((Int_obj_val)idx_ref).Val() - baseInt));
}
}
lkp_is_active = false;
lkp_bfr.Clear();
fmt_args_exist = true;
}
else {
lkp_bfr.Add_byte(cur_byte);
switch (cur_byte) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
break;
default:
lkp_is_numeric = false;
break;
}
}
fmt_pos += 1;
}
else if (cur_byte == char_escape) {
if (fmt_pos == fmt_end) {
if (fail_when_invalid_escapes)
throw Err_.new_("escape char encountered but no more chars left");
else {
trg_bry[trg_pos] = cur_byte;
break;
}
}
nxt_byte = fmt[fmt_pos + 1];
if (nxt_byte == char_arg_bgn) {
if (trg_pos > 0) {list.Add(Bry_fmtr_itm.dat_(trg_bry, trg_pos)); trg_pos = 0;} // something pending; add it to list
int eval_lhs_bgn = fmt_pos + 2;
if (eval_lhs_bgn < fmt_len && fmt[eval_lhs_bgn] == char_eval_bgn) { // eval found
fmt_pos = Compile_eval_cmd(fmt, fmt_len, eval_lhs_bgn, list);
continue;
}
else {
lkp_is_active = true;
lkp_is_numeric = true;
}
}
else { // ~{0}; ~~ -> ~; ~n -> newLine; ~t -> tab
if (nxt_byte == char_escape) tmp_byte = char_escape;
else if (nxt_byte == char_escape_nl) tmp_byte = Byte_ascii.NewLine;
else if (nxt_byte == char_escape_tab) tmp_byte = Byte_ascii.Tab;
else {
if (fail_when_invalid_escapes) throw Err_.new_("unknown escape code").Add("code", Char_.XbyInt(nxt_byte)).Add("fmt_pos", fmt_pos + 1);
else
tmp_byte = cur_byte;
}
trg_bry[trg_pos++] = tmp_byte;
}
fmt_pos += 2;
}
else {
trg_bry[trg_pos++] = cur_byte;
fmt_pos += 1;
}
}
if (lkp_is_active) throw Err_.new_("idx mode not closed");
if (trg_pos > 0) {list.Add(Bry_fmtr_itm.dat_(trg_bry, trg_pos)); trg_pos = 0;}
itms = (Bry_fmtr_itm[])list.XtoAry(Bry_fmtr_itm.class);
itms_len = itms.length;
return this;
}
int Compile_eval_cmd(byte[] fmt, int fmt_len, int eval_lhs_bgn, ListAdp list) {
int eval_lhs_end = Bry_finder.Find_fwd(fmt, char_eval_end, eval_lhs_bgn + Int_.Const_dlm_len, fmt_len); if (eval_lhs_end == Bry_.NotFound) throw Err_mgr._.fmt_(GRP_KEY, "eval_lhs_end_invalid", "could not find eval_lhs_end: ~{0}", String_.new_utf8_(fmt, eval_lhs_bgn, fmt_len));
byte[] eval_dlm = Bry_.Mid(fmt, eval_lhs_bgn , eval_lhs_end + Int_.Const_dlm_len);
int eval_rhs_bgn = Bry_finder.Find_fwd(fmt, eval_dlm , eval_lhs_end + Int_.Const_dlm_len, fmt_len); if (eval_rhs_bgn == Bry_.NotFound) throw Err_mgr._.fmt_(GRP_KEY, "eval_rhs_bgn_invalid", "could not find eval_rhs_bgn: ~{0}", String_.new_utf8_(fmt, eval_lhs_end, fmt_len));
byte[] eval_cmd = Bry_.Mid(fmt, eval_lhs_end + Int_.Const_dlm_len, eval_rhs_bgn);
byte[] eval_rslt = eval_mgr.Eval(eval_cmd);
int eval_rhs_end = eval_rhs_bgn + Int_.Const_dlm_len + eval_dlm.length;
if (eval_rslt == null) eval_rslt = Bry_.Mid(fmt, eval_lhs_bgn - 2, eval_rhs_end); // not found; return original argument
list.Add(Bry_fmtr_itm.dat_bry_(eval_rslt));
return eval_rhs_end;
}
static final String GRP_KEY = "gplx.Bry_fmtr";
public boolean Fmt_args_exist() {return fmt_args_exist;} private boolean fmt_args_exist;
boolean dirty = true;
int baseInt = 0;
public static final byte char_escape = Byte_ascii.Tilde, char_arg_bgn = Byte_ascii.Curly_bgn, char_arg_end = Byte_ascii.Curly_end, char_escape_nl = Byte_ascii.Ltr_n, char_escape_tab = Byte_ascii.Ltr_t, char_eval_bgn = Byte_ascii.Lt, char_eval_end = Byte_ascii.Gt;
public static final Bry_fmtr Null = new Bry_fmtr().Fmt_("");
public static Bry_fmtr tmp_() {return new Bry_fmtr().Fmt_("").Keys_();}
public static Bry_fmtr new_(String fmt, String... keys) {return new Bry_fmtr().Fmt_(fmt).Keys_(keys);} // NOTE: keys may seem redundant, but are needed to align ordinals with proc; EX: fmt may be "~{A} ~{B}" or "~{B} ~{A}"; call will always be Bld(a, b); passing in "A", "B" guarantees A is 0 and B is 1;
public static Bry_fmtr new_() {return new Bry_fmtr();}
public static Bry_fmtr keys_(String... keys) {return new Bry_fmtr().Keys_(keys);}
public static Bry_fmtr new_bry_(byte[] fmt, String... keys) {return new Bry_fmtr().Fmt_(fmt).Keys_(keys);}
public static String New_fmt_str(String key, Object[] args) {
tmp_bfr.Clear();
tmp_bfr.Add_str(key);
tmp_bfr.Add_byte(Byte_ascii.Colon);
int args_len = args.length;
for (int i = 0; i < args_len; i++) { // add " 0='~{0}'"
tmp_bfr.Add_byte(Byte_ascii.Space);
tmp_bfr.Add_int_variable(i);
tmp_bfr.Add_byte(Byte_ascii.Eq);
tmp_bfr.Add_byte(Byte_ascii.Apos);
tmp_bfr.Add_byte(Byte_ascii.Tilde);
tmp_bfr.Add_byte(Byte_ascii.Curly_bgn);
tmp_bfr.Add_int_variable(i);
tmp_bfr.Add_byte(Byte_ascii.Curly_end);
tmp_bfr.Add_byte(Byte_ascii.Apos);
}
return tmp_bfr.XtoStrAndClear();
} static Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
public void Bld_bfr_many_and_set_fmt(Object... args) {
Bry_bfr bfr = Bry_bfr.new_();
this.Bld_bfr_many(bfr, args);
byte[] bry = bfr.XtoAryAndClear();
this.Fmt_(bry).Compile();
}
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface Bry_fmtr_arg {
void XferAry(Bry_bfr bfr, int idx);
}

View File

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import gplx.brys.*;
public class Bry_fmtr_arg_ {
public static Bry_fmtr_arg_bry bry_(String v) {return new Bry_fmtr_arg_bry(Bry_.new_utf8_(v));}
public static Bry_fmtr_arg_bry bry_(byte[] v) {return new Bry_fmtr_arg_bry(v);}
public static Bry_fmtr_arg_byt byt_(byte v) {return new Bry_fmtr_arg_byt(v);}
public static Bry_fmtr_arg_int int_(int v) {return new Bry_fmtr_arg_int(v);}
public static Bry_fmtr_arg_bfr bfr_(Bry_bfr v) {return new Bry_fmtr_arg_bfr(v);}
public static Bry_fmtr_arg_bfr_retain bfr_retain_(Bry_bfr v) {return new Bry_fmtr_arg_bfr_retain(v);}
public static Bry_fmtr_arg fmtr_(Bry_fmtr v, Bry_fmtr_arg... arg_ary) {return new Bry_fmtr_arg_fmtr(v, arg_ary);}
public static Bry_fmtr_arg_fmtr_objs fmtr_null_() {return new Bry_fmtr_arg_fmtr_objs(null, null);}
public static final Bry_fmtr_arg Null = new Bry_fmtr_arg_null();
}
class Bry_fmtr_arg_null implements Bry_fmtr_arg {
public void XferAry(Bry_bfr trg, int idx) {}
}

View File

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_fmtr_arg_fmtr_objs implements Bry_fmtr_arg {
public Bry_fmtr_arg_fmtr_objs Atrs_(Bry_fmtr fmtr, Object... objs) {this.fmtr = fmtr; this.objs = objs; return this;}
public void XferAry(Bry_bfr trg, int idx) {
fmtr.Bld_bfr_many(trg, objs);
}
public Bry_fmtr_arg_fmtr_objs(Bry_fmtr fmtr, Object[] objs) {this.fmtr = fmtr; this.objs = objs;} Bry_fmtr fmtr; Object[] objs;
}

View File

@ -0,0 +1,22 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public interface Bry_fmtr_eval_mgr {
boolean Enabled(); void Enabled_(boolean v);
byte[] Eval(byte[] cmd);
}

View File

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_fmtr_eval_mgr_ {
public static Io_url Eval_url(Bry_fmtr_eval_mgr eval_mgr, byte[] fmt) {
if (eval_mgr == null) return Io_url_.new_any_(String_.new_utf8_(fmt));
Bry_bfr bfr = Bry_bfr.reset_(255);
Bry_fmtr fmtr = Bry_fmtr.tmp_();
fmtr.Eval_mgr_(eval_mgr).Fmt_(fmt).Bld_bfr_none(bfr);
return Io_url_.new_any_(bfr.XtoStrAndClear());
}
}

View File

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_fmtr_eval_mgr_gfs implements Bry_fmtr_eval_mgr {
public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled;
public byte[] Eval(byte[] cmd) {
return enabled ? Bry_.new_utf8_(Object_.XtoStr_OrNullStr(GfsCore._.ExecText(String_.new_utf8_(cmd)))) : null;
}
public static final Bry_fmtr_eval_mgr_gfs _ = new Bry_fmtr_eval_mgr_gfs(); Bry_fmtr_eval_mgr_gfs() {}
}

View File

@ -0,0 +1,33 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_fmtr_itm {
public boolean Arg;
public int ArgIdx;
public byte[] Dat;
public String DatStr() {
if (datStr == null) datStr = String_.new_utf8_(Dat);
return datStr;
} String datStr;
public static Bry_fmtr_itm arg_(int idx) {return new Bry_fmtr_itm(true, idx, Bry_.Empty);}
public static Bry_fmtr_itm dat_(byte[] dat, int len) {return new Bry_fmtr_itm(false, -1, Bry_.Mid(dat, 0, len));}
public static Bry_fmtr_itm dat_bry_(byte[] bry) {return new Bry_fmtr_itm(false, -1, bry);}
Bry_fmtr_itm(boolean arg, int argIdx, byte[] dat) {
this.Arg = arg; this.ArgIdx = argIdx; this.Dat = dat;
}
}

View File

@ -0,0 +1,75 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Bry_fmtr_tst {
@Test public void Idx_text() {tst_Format("a", "a");}
@Test public void Idx_1() {tst_Format("a", "~{0}", "a");}
@Test public void Idx_3() {tst_Format("abc", "~{0}~{1}~{2}", "a", "b", "c");}
@Test public void Idx_mix() {tst_Format("abcde", "a~{0}c~{1}e", "b", "d");}
@Test public void Key_basic() {tst("~{key}" , String_.Ary("key") , ary_("a") , "a");}
@Test public void Key_mult() {tst("~{key1}~{key2}" , String_.Ary("key1", "key2") , ary_("a", "b") , "ab");}
@Test public void Key_mix() {tst("~{key1}~{1}" , String_.Ary("key1", "key2") , ary_("a", "b") , "ab");}
@Test public void Key_repeat() {tst("~{key1}~{key1}" , String_.Ary("key1") , ary_("a") , "aa");}
@Test public void Simple() {
Bry_fmtr fmtr = Bry_fmtr.new_("0~{key1}1~{key2}2", "key1", "key2");
Tfds.Eq("0.1,2", fmtr.Bld_str_many(".", ","));
}
@Test public void Cmd() {
Bry_fmtr_tst_mok mok = new Bry_fmtr_tst_mok();
Bry_fmtr fmtr = Bry_fmtr.new_("0~{key1}2~{<>3<>}4", "key1").Eval_mgr_(mok);
Tfds.Eq("012~{<>3<>}4", fmtr.Bld_str_many("1"));
mok.Enabled_(true);
Tfds.Eq("01234", fmtr.Bld_str_many("1"));
}
@Test public void Err_missing_idx() {tst_Format("~{0}", "~{0}");}
String[] ary_(String... ary) {return ary;}
void tst(String fmt, String[] keys, String[] args, String expd) {
Bry_fmtr fmtr = new Bry_fmtr().Fmt_(Bry_.new_utf8_(fmt));
fmtr.Keys_(keys);
String actl = fmtr.Bld_str_many(args);
Tfds.Eq(expd, actl);
}
void tst_Format(String expd, String fmt, String... args) {
Bry_fmtr fmtr = new Bry_fmtr().Fmt_(fmt);
Tfds.Eq(expd, fmtr.Bld_str_many(args));
}
@Test public void Bld_bfr_many_and_set_fmt() {
Bry_fmtr_fxt fxt = new Bry_fmtr_fxt().Clear();
fxt.Bld_bfr_many_and_set_fmt("a~{0}c", Object_.Ary("b"), "abc");
}
}
class Bry_fmtr_tst_mok implements Bry_fmtr_eval_mgr {
public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled;
public byte[] Eval(byte[] cmd) {
return enabled ? cmd : null;
}
}
class Bry_fmtr_fxt {
public Bry_fmtr_fxt Clear() {
if (fmtr == null) {
fmtr = Bry_fmtr.new_();
}
return this;
} private Bry_fmtr fmtr;
public void Bld_bfr_many_and_set_fmt(String fmt, Object[] args, String expd) {
fmtr.Fmt_(fmt);
fmtr.Bld_bfr_many_and_set_fmt(args);
Tfds.Eq(expd, String_.new_ascii_(fmtr.Fmt()));
}
}

View File

@ -0,0 +1,35 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Bry_obj_ref {
public byte[] Val() {return val;} public Bry_obj_ref Val_(byte[] v) {val = v; return this;} private byte[] val;
@Override public int hashCode() {return CalcHashCode(val, 0, val.length);}
@Override public boolean equals(Object obj) {return obj == null ? false : Bry_.Eq(val, ((Bry_obj_ref)obj).Val());} // NOTE: strange, but null check needed; throws null error; EX.WP: File:Eug<EFBFBD>ne Delacroix - La libert<EFBFBD> guidant le peuple.jpg
public static int CalcHashCode(byte[] ary, int bgn, int end) {
int rv = 0;
for (int i = bgn; i < end; i++)
rv = (31 * rv) + ary[i];
return rv;
}
public static Bry_obj_ref null_() {return new_(null);}
public static Bry_obj_ref new_(byte[] val) {
Bry_obj_ref rv = new Bry_obj_ref();
rv.val = val;
return rv;
} private Bry_obj_ref() {}
}

View File

@ -0,0 +1,48 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Byte_ {
public static final byte MinValue = Byte.MIN_VALUE;
public static byte[] Ary(byte... ary) {return ary;}
public static byte[] Ary_by_ints(int... ary) {
int ary_len = ary.length;
byte[] rv = new byte[ary_len];
for (int i = 0; i < ary_len; i++)
rv[i] = int_(ary[i]);
return rv;
}
public static String XtoStr(byte v) {return new Byte(v).toString();}
public static int XtoInt(byte v) {return v < 0 ? (int)v + 256 : v;}
public static boolean In(byte v, byte... ary) {
for (byte itm : ary)
if (v == itm) return true;
return false;
}
public static int Compare(byte lhs, byte rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
public static byte cast_(Object o) {try {return (Byte)o;} catch (Exception e) {throw Err_.type_mismatch_exc_(e, byte.class, o);}}
public static byte parse_(String raw) {return Byte.parseByte(raw);}
public static byte int_(int v) {return v > 127 ? (byte)(v - 256) : (byte)v;} // PERF?: (byte)(v & 0xff)
public static byte X_to_boolean_byte(boolean v) {
return v ? Bool_.Y_byte : Bool_.N_byte;
}
public static final byte Zero = 0, MaxValue_127 = 127;
}

View File

@ -0,0 +1,35 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Byte__tst {
@Test public void int_() {
tst_int_( 0, 0);
tst_int_( 127, 127);
tst_int_( 128, 128); // NOTE: JAVA defines byte as -128 -> 127
tst_int_( 255, 255);
tst_int_( 256, 0); // NOTE: 256 will cast to 1; (byte)256 works same in both JAVA/.NET
} void tst_int_(int v, int expd) {Tfds.Eq((byte)expd, Byte_.int_(v));} // WORKAROUND/JAVA: expd is of type int b/c java promotes numbers to ints
@Test public void XtoInt() {
tst_XtoInt( 0, 0);
tst_XtoInt( 127, 127);
tst_XtoInt( 128, 128);
tst_XtoInt( 255, 255);
tst_XtoInt( 256, 0);
} void tst_XtoInt(int v, int expd) {Tfds.Eq(expd, Byte_.XtoInt((byte)v));} // WORKAROUND/JAVA: v is of type int b/c java promotes numbers to ints
}

View File

@ -0,0 +1,76 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Byte_ascii {
public static final byte
Nil = 0 , Backfeed = 8, Tab = 9
, NewLine = 10, Formfeed = 12, CarriageReturn = 13
, Space = 32, Bang = 33, Quote = 34
, Hash = 35, Dollar = 36, Percent = 37, Amp = 38, Apos = 39
, Paren_bgn = 40, Paren_end = 41, Asterisk = 42, Plus = 43, Comma = 44
, Dash = 45, Dot = 46, Slash = 47, Num_0 = 48, Num_1 = 49
, Num_2 = 50, Num_3 = 51, Num_4 = 52, Num_5 = 53, Num_6 = 54
, Num_7 = 55, Num_8 = 56, Num_9 = 57, Colon = 58, Semic = 59
, Lt = 60, Eq = 61, Gt = 62, Question = 63, At = 64
, Ltr_A = 65, Ltr_B = 66, Ltr_C = 67, Ltr_D = 68, Ltr_E = 69
, Ltr_F = 70, Ltr_G = 71, Ltr_H = 72, Ltr_I = 73, Ltr_J = 74
, Ltr_K = 75, Ltr_L = 76, Ltr_M = 77, Ltr_N = 78, Ltr_O = 79
, Ltr_P = 80, Ltr_Q = 81, Ltr_R = 82, Ltr_S = 83, Ltr_T = 84
, Ltr_U = 85, Ltr_V = 86, Ltr_W = 87, Ltr_X = 88, Ltr_Y = 89
, Ltr_Z = 90, Brack_bgn = 91, Backslash = 92, Brack_end = 93, Pow = 94 // Circumflex
, Underline = 95, Tick = 96, Ltr_a = 97, Ltr_b = 98, Ltr_c = 99
, Ltr_d = 100, Ltr_e = 101, Ltr_f = 102, Ltr_g = 103, Ltr_h = 104
, Ltr_i = 105, Ltr_j = 106, Ltr_k = 107, Ltr_l = 108, Ltr_m = 109
, Ltr_n = 110, Ltr_o = 111, Ltr_p = 112, Ltr_q = 113, Ltr_r = 114
, Ltr_s = 115, Ltr_t = 116, Ltr_u = 117, Ltr_v = 118, Ltr_w = 119
, Ltr_x = 120, Ltr_y = 121, Ltr_z = 122, Curly_bgn = 123, Pipe = 124
, Curly_end = 125, Tilde = 126
;
public static final byte Max_7_bit = (byte)127, Ascii_min = 0, Ascii_max = 127;
public static final byte[] Space_len2 = new byte[] {Space, Space}, Space_len4 = new byte[] {Space, Space, Space, Space};
public static boolean Is_ltr(byte b) {
return ( b >= Byte_ascii.Ltr_a && b <= Byte_ascii.Ltr_z
|| b >= Byte_ascii.Ltr_A && b <= Byte_ascii.Ltr_Z);
}
public static boolean Is_ws(byte b) {
switch (b) {
case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn: case Byte_ascii.Space: return true;
default: return false;
}
}
public static boolean Is_num(byte b) {
return b > Byte_ascii.Slash && b < Byte_ascii.Colon;
}
public static int X_to_digit(byte b) {return b - Byte_ascii.Num_0;}
public static byte Case_upper(byte b) {
return b > 96 && b < 123
? (byte)(b - 32)
: b
;
}
public static byte Case_lower(byte b) {
return b > 64 && b < 91
? (byte)(b + 32)
: b
;
}
public static final byte[]
Dot_bry = new byte[] {Byte_ascii.Dot}
, NewLine_bry = new byte[] {Byte_ascii.NewLine}
;
}

View File

@ -0,0 +1,31 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Byte_obj_ref {
public byte Val() {return val;} private byte val;
public Byte_obj_ref Val_(byte v) {val = v; return this;}
@Override public int hashCode() {return val;}
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((Byte_obj_ref)obj).Val();}
@Override public String toString() {return Int_.XtoStr(val);}
public static Byte_obj_ref zero_() {return new_(Byte_.Zero);}
public static Byte_obj_ref new_(byte val) {
Byte_obj_ref rv = new Byte_obj_ref();
rv.val = val;
return rv;
} private Byte_obj_ref() {}
}

View File

@ -0,0 +1,29 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Byte_obj_val {
public byte Val() {return val;} private byte val;
@Override public String toString() {return Int_.XtoStr(val);}
@Override public int hashCode() {return val;}
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((Byte_obj_val)obj).Val();}
public static Byte_obj_val new_(byte val) {
Byte_obj_val rv = new Byte_obj_val();
rv.val = val;
return rv;
} private Byte_obj_val() {}
}

View File

@ -0,0 +1,76 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Char_ {
public static final char Null = '\0', NewLine = '\n';
public static final int CharLen = 1;
public static final int AsciiZero = 48;
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 IsCaseLower(char c) {return Character.isLowerCase(c);}
public static boolean IsLetterOrDigit(char c) {return Character.isLetterOrDigit(c);}
public static boolean IsLetterEnglish(char c) {
switch (c) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': return true;
default: return false;
}
}
public static boolean IsLetterLowerEnglish(char c) {
switch (c) {
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': return true;
default: return false;
}
}
public static boolean IsWhitespace(char c) {
switch (c) {
case ' ': case '\t': case '\n': case '\r': return true;
default: return false;
}
}
public static int To_int_or(char c, int or) {
switch (c) {
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
default: return or;
}
}
public static boolean In(char match, char... ary) {
for (char itm : ary)
if (itm == match) return true;
return false;
}
public static String XtoStr(char[] ary, int pos, int length) {return new String(ary, pos, length);}
public static byte[] XtoByteAry(int v) {return Bry_.new_utf8_(Char_.XtoStr((char)v));}
public static char XbyInt(int i) {return (char)i;}
public static String XtoStr(int b) {return XtoStr((char)b);}
public static String XtoStr(char c) {return String.valueOf(c);}
public static byte XtoByte(char c) {return (byte)c;}
public static char cast_(Object o) {try {return (Character)o;} catch(Exception e) {throw Err_.type_mismatch_exc_(e, char.class, o);}}
public static char parse_(String raw) {try {return raw.charAt(0);} catch(Exception exc) {throw Err_.parse_type_exc_(exc, char.class, raw);}}
}

View File

@ -0,0 +1,37 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Double_ {
public static final Class<?> ClassOf = Double.class;
public static final double Inf_pos = Double.POSITIVE_INFINITY;;
public static final double NaN = Double.NaN;;
public static final byte[] NaN_bry = Bry_.new_ascii_("NaN");
public static boolean IsNaN(double v) {return Double.isNaN(v);}
public static double coerce_(Object v) {
try {String s = String_.as_(v); return s == null ? Double_.cast_(v) : Double_.parse_(s);}
catch (Exception e) {throw Err_.cast_(e, double.class, v);}
}
public static String XtoStr(double v) {
int v_int = (int)v;
return v - v_int == 0 ? Int_.XtoStr(v_int) : Double.toString(v);
}
public static double cast_(Object o) {try {return (Double)o;} catch(Exception e) {throw Err_.type_mismatch_exc_(e, double.class, o);}}
public static double parse_(String raw) {try {return Double.parseDouble(raw);} catch(Exception e) {throw Err_.parse_type_exc_(e, double.class, raw);}}
public static double parseOr_(String raw, double v) {try {return Double.parseDouble(raw);} catch(Exception e) {Err_.Noop(e); return v;}}
public static final double MinValue = Double.MIN_VALUE;
}

View File

@ -0,0 +1,40 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Float_ {
public static final float NaN = Float.NaN;;
public static boolean IsNaN(float v) {return Float.isNaN(v);}
public static int RoundUp(float val) {
int rv = (int)val;
return (rv == val) ? rv : rv + 1;
}
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 String XtoStr(float v) {
int v_int = (int)v;
return v - v_int == 0 ? Int_.XtoStr(v_int) : Float.toString(v);
}
public static float cast_double_(double v) {return (float)v;}
public static float cast_(Object obj) {try {return (Float)obj;} catch(Exception exc) {throw Err_.type_mismatch_exc_(exc, float.class, obj);}}
public static float read_(Object o) {String s = String_.as_(o); return s != null ? Float_.parse_(s) : Float_.cast_(o);}
public static float parse_(String raw) {try {return Float.parseFloat(raw);} catch(Exception exc) {throw Err_.parse_type_exc_(exc, float.class, raw);}}
public static float parseOr_(String raw, float v) {
if (raw == null || raw.length() == 0) return v;
try {return Float.parseFloat(raw);} catch(Exception e) {Err_.Noop(e); return v;}
}
}

View File

@ -0,0 +1,251 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Int_ implements GfoInvkAble {
public static final Class<?> ClassOf = Integer.class;
public static final int Base1 = 1;
public static final int Const_dlm_len = 1;
public static final int Const_position_after_char = 1;
public static final int Null = Int_.MinValue;
public static int coerce_(Object v) {
try {String s = String_.as_(v); return s == null ? Int_.cast_(v) : Int_.parse_(s);}
catch (Exception e) {throw Err_.cast_(e, int.class, v);}
}
public static int[] Ary_empty = new int[0];
public static int[] Ary(int... v) {return v;}
public static int[] Ary_copy(int[] ary) {return Ary_copy(ary, ary.length);}
public static int[] Ary_copy(int[] ary, int new_len) {
int old_len = ary.length;
int[] rv = new int[new_len];
for (int i = 0; i < old_len; i++)
rv[i] = ary[i];
return rv;
}
public static int[] AryRng(int bgn, int end) {
int len = end - bgn + 1;
int[] rv = new int[len];
for (int i = 0; i < len; i++)
rv[i] = bgn + i;
return rv;
}
public static final int
MinValue = Integer.MIN_VALUE
, MaxValue = Integer.MAX_VALUE
, Neg1 = -1
, Neg1_count = -1
;
public static int parse_or_(String raw, int or) {
if (raw == null) return or;
int rawLen = String_.Len(raw); if (rawLen == 0) return or;
int rv = 0, tmp = 0, factor = 1;
for (int i = rawLen; i > 0; i--) {
char c = String_.CharAt(raw, i - 1);
switch (c) {
case '0': tmp = 0; break; case '1': tmp = 1; break; case '2': tmp = 2; break; case '3': tmp = 3; break; case '4': tmp = 4; break;
case '5': tmp = 5; break; case '6': tmp = 6; break; case '7': tmp = 7; break; case '8': tmp = 8; break; case '9': tmp = 9; break;
case '-': rv *= -1; continue; // NOTE: note continue
default: return or;
}
rv += (tmp * factor);
factor *= 10;
}
return rv;
}
public static int EnsureLessThan(int v, int max) {return v >= max ? max : v;}
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 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 ModIfNeg1(int v, int or) {return v == -1 ? or : v;}
public static boolean RangeCheck(int v, int max) {return v >= 0 && v < max;}
public static void RangeCheckOrFail_list(int v, int max, String s) {if (v < 0 || v >= max) throw Err_.new_("bounds check failed").Add("msg", s).Add("v", v).Add("min", 0).Add("max", max - 1);}
public static void RangeCheckOrFail(int v, int min, int max, String s) {if (v < min || v >= max) throw Err_.new_("bounds check failed").Add("msg", s).Add("v", v).Add("min", min).Add("max", max);}
public static boolean Between(int v, int lhs, int rhs) {
int lhsCompare = v == lhs ? 0 : (v < lhs ? -1 : 1);
int rhsCompare = v == rhs ? 0 : (v < rhs ? -1 : 1);
return (lhsCompare * rhsCompare) != 1; // 1 when v is (a) greater than both or (b) less than both
}
public static int Div(int v, float divisor) {return (int)((float)v / divisor);}
public static int DivAndRoundUp(int v, int divisor) {
int whole = v / divisor;
int partial = v % divisor == 0 ? 0 : 1;
return whole + partial;
}
public static int Mult(int v, float multiplier) {
float product = ((float)v * multiplier); // WORKAROUND (DotNet): (int)((float)v * multiplier) returns 0 for 100 and .01f
return (int)product;
}
public static int Compare(int lhs, int rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
public static int DigitCount(int v) {
int log10 = Log10(v);
return v > -1 ? log10 + 1 : log10 * -1 + 2;
}
public static int Log10(int v) {
if (v == 0) return 0;
int sign = 1;
if (v < 0) {
if (v == Int_.MinValue) return -9; // NOTE: Int_.MinValue * -1 = Int_.MinValue
v *= -1;
sign = -1;
}
int rv = Log10AryLen - 2; // rv will only happen when v == Int_.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 < Log10AryLen; i++) {
if (v < Log10Ary[i]) {rv = i - 1; break;}
}
return rv * sign;
} public static int[] Log10Ary = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, Int_.MaxValue}; public static int Log10AryLen = 11;
public Int_ FailIfNeg1(String key, int val) {
if (val < 0) throw Err_.new_("key must be >= 0").Add("key", key).Add("val", val);
return this;
}
public static String XtoStr_PadBgn_space(int v, int reqdPlaces) {return Xto_str_pad_bgn(v, reqdPlaces, Byte_ascii.Space, true);} // EX: 1, 3 returns " 1"
public static String XtoStr_PadBgn(int v, int reqdPlaces) {return Xto_str_pad_bgn(v, reqdPlaces, Byte_ascii.Num_0, true);} // EX: 1, 3 returns "001"
static String Xto_str_pad_bgn(int val, int places, byte pad_chr, boolean bgn) {
int len = DigitCount(val);
int pad_len = places - len; if (pad_len < 0) return Int_.XtoStr(val);
Bry_bfr bfr = Bry_bfr.new_();
boolean neg = val < 0;
if (bgn) { // special logic to handle negative numbers; EX: -1 -> "-001", not "00-1"
if (neg) {
bfr.Add_byte(Byte_ascii.Dash);
val *= -1;
--len;
}
}
else
bfr.Add_int_fixed(val, len);
bfr.Add_byte_repeat(pad_chr, pad_len);
if (bgn) bfr.Add_int_fixed(val, len); // NOTE: neg handled above
return bfr.XtoStr();
}
public static int read_(Object o) {String s = String_.as_(o); return s != null ? Int_.parse_(s) : Int_.cast_(o);}
public static int parse_(String raw) {try {return Integer.parseInt(raw);} catch(Exception e) {throw Err_.parse_type_exc_(e, int.class, raw);}}
public static int cast_(Object obj) {try {return (Integer)obj;} catch(Exception exc) {throw Err_.type_mismatch_exc_(exc, int.class, obj);}}
public static int cast_or_(Object obj, int or) {try {return (Integer)obj;} catch(Exception e) {Err_.Noop(e); return or;}}
public static int X_by_double_(double v) {return (int)v;}
public static String XtoStr(int v) {return new Integer(v).toString();}
public static String XtoStr_fmt(int v, String fmt) {return new java.text.DecimalFormat(fmt).format(v);}
public static boolean TypeMatch(Class<?> type) {return type == int.class || type == Integer.class;}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_XtoStr_PadBgn)) {
int v = m.ReadInt(GfsCore_.Arg_primitive), pad = m.ReadInt("pad");
return ctx.Deny() ? (Object)this : XtoStr_PadBgn(v, pad);
}
else if (ctx.Match(k, "Add")) {
int v = m.ReadInt(GfsCore_.Arg_primitive), operand = m.ReadInt("operand");
return ctx.Deny() ? (Object)this : v + operand;
}
else return GfoInvkAble_.Rv_unhandled;
} public static final String Invk_XtoStr_PadBgn = "XtoStr_PadBgn";
public static final Int_ Gfs = new Int_();
// public static int Xto_int_hex(String v) {return Integer.parseInt(v, 16);}
public static int Xto_int_hex(byte[] src) {return Xto_int_hex(src, 0, src.length);}
public static int Xto_int_hex(byte[] src, int bgn, int end) {
int rv = 0; int factor = 1;
for (int i = end - 1; i >= bgn; i--) {
int val = Xto_int_hex(src[i]);
rv += (val * factor);
factor *= 16;
}
return rv;
}
public static int Xto_int_hex(byte b) {
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
return b - Byte_ascii.Num_0;
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E: case Byte_ascii.Ltr_F:
return b - Byte_ascii.Ltr_A + 10;
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e: case Byte_ascii.Ltr_f:
return b - Byte_ascii.Ltr_a + 10;
default:
return -1;
}
}
public static String XtoStr_hex(int v) {
String rv = Integer.toHexString(v);
int rvLen = String_.Len(rv);
if (rvLen < 8) rv = String_.Repeat("0", 8 - rvLen) + rv;
return String_.Upper(rv);
}
public static String XtoStr(int[] ary) {
String_bldr sb = String_bldr_.new_();
for (int i = 0; i < ary.length; i++)
sb.Add_spr_unless_first(Int_.XtoStr(ary[i]), " ", i);
return sb.XtoStr();
}
public static int[] Ary_parse(String raw_str, int reqd_len, int[] or) {
byte[] raw_bry = Bry_.new_ascii_(raw_str);
int raw_bry_len = raw_bry.length;
int[] rv = new int[reqd_len];
int cur_val = 0, cur_mult = 1, cur_idx = reqd_len - 1; boolean signed = false;
for (int i = raw_bry_len - 1; i > -2; i--) {
byte b = i == -1 ? Byte_ascii.Comma : raw_bry[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
if (signed) return or;
cur_val += (b - Byte_ascii.Num_0) * cur_mult;
cur_mult *= 10;
break;
case Byte_ascii.Space: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn: case Byte_ascii.Tab:
break;
case Byte_ascii.Comma:
if (cur_idx < 0) return or;
rv[cur_idx--] = cur_val;
cur_val = 0; cur_mult = 1;
signed = false;
break;
case Byte_ascii.Dash:
if (signed) return or;
cur_val *= -1;
signed = true;
break;
case Byte_ascii.Plus: // noop; all values positive by default
if (signed) return or;
signed = true;
break;
default:
return or;
}
}
return cur_idx == -1 ? rv : or; // cur_idx == -1 checks for unfilled; EX: Ary_parse("1,2", 3, null) is unfilled
}
public static int[] Ary_parse(String raw_str, String spr) {
String[] ary = String_.Split(raw_str, spr);
int len = ary.length;
int[] rv = new int[len];
for (int i = 0; i < len; i++)
rv[i] = Int_.parse_(ary[i]);
return rv;
}
}

View File

@ -0,0 +1,115 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Int__tst {
@Test public void XtoStr_PadBgn() {
// tst_XtoStr_PadLeft_Zeroes(1 , 3, "001"); // pad
// tst_XtoStr_PadLeft_Zeroes(123 , 3, "123"); // no pad
// tst_XtoStr_PadLeft_Zeroes(1234 , 3, "1234"); // val exceeds pad; confirm noop
tst_XtoStr_PadLeft_Zeroes(-1 , 3, "-01"); // negative
tst_XtoStr_PadLeft_Zeroes(-12 , 3, "-12"); // negative
tst_XtoStr_PadLeft_Zeroes(-123 , 3, "-123"); // negative
tst_XtoStr_PadLeft_Zeroes(-1234 , 3, "-1234"); // negative
} void tst_XtoStr_PadLeft_Zeroes(int val, int zeros, String expd) {Tfds.Eq(expd, Int_.XtoStr_PadBgn(val, zeros));}
@Test public void parseOr_() {
tst_ParseOr("", -1); // empty
tst_ParseOr("123", 123); // single
tst_ParseOr("1a", -1); // fail
} void tst_ParseOr(String raw, int expd) {Tfds.Eq(expd, Int_.parse_or_(raw, -1));}
@Test public void Between() {
tst_Between(1, 0, 2, true); // simple true
tst_Between(3, 0, 2, false); // simple false
tst_Between(0, 0, 2, true); // bgn true
tst_Between(2, 0, 2, true); // end true
} void tst_Between(int val, int lhs, int rhs, boolean expd) {Tfds.Eq(expd, Int_.Between(val, lhs, rhs));}
@Test public void Xto_fmt() {
tst_XtoStr_fmt(1, "1");
tst_XtoStr_fmt(1000, "1,000");
} void tst_XtoStr_fmt(int v, String expd) {Tfds.Eq(expd, Int_.XtoStr_fmt(v, "#,###"));}
@Test public void AryRng() {
tst_AryRng(1, 3, Int_.Ary(1, 2, 3));
} void tst_AryRng(int bgn, int end, int[] expd) {Tfds.Eq_ary(expd, Int_.AryRng(bgn, end));}
@Test public void Log10_pos() {
tst_Log10(0, 0);
tst_Log10(1, 0);
tst_Log10(9, 0);
tst_Log10(10, 1);
tst_Log10(100, 2);
tst_Log10(1000000, 6);
tst_Log10(1000000000, 9);
tst_Log10(Int_.MaxValue, 9);
}
@Test public void Log10_neg() {
tst_Log10(-1, 0);
tst_Log10(-10, -1);
tst_Log10(-100, -2);
tst_Log10(-1000000, -6);
tst_Log10(-1000000000, -9);
tst_Log10(Int_.MinValue, -9);
tst_Log10(Int_.MinValue + 1, -9);
}
void tst_Log10(int val, int expd) {Tfds.Eq(expd, Int_.Log10(val));}
@Test public void DigitCount() {
tst_DigitCount(0, 1);
tst_DigitCount(9, 1);
tst_DigitCount(100, 3);
tst_DigitCount(-1, 2);
tst_DigitCount(-100, 4);
} void tst_DigitCount(int val, int expd) {Tfds.Eq(expd, Int_.DigitCount(val), Int_.XtoStr(val));}
@Test public void Log10() {
tst_Log10( 0, 0);
tst_Log10( 1, 0);
tst_Log10( 2, 0);
tst_Log10( 10, 1);
tst_Log10( 12, 1);
tst_Log10( 100, 2);
tst_Log10( 123, 2);
tst_Log10( 1000, 3);
tst_Log10( 1234, 3);
tst_Log10( 10000, 4);
tst_Log10( 12345, 4);
tst_Log10( 100000, 5);
tst_Log10( 123456, 5);
tst_Log10( 1000000, 6);
tst_Log10( 1234567, 6);
tst_Log10( 10000000, 7);
tst_Log10( 12345678, 7);
tst_Log10( 100000000, 8);
tst_Log10( 123456789, 8);
tst_Log10( 1000000000, 9);
tst_Log10( 1234567890, 9);
tst_Log10(Int_.MaxValue, 9);
}
@Test public void Xto_int_hex_tst() {
Xto_int_hex("007C", 124);
} void Xto_int_hex(String raw, int expd) {Tfds.Eq(expd, Int_.Xto_int_hex(Bry_.new_ascii_(raw)));}
@Test public void Ary_parse() {
Ary_parse__tst("1,2,3" , 3, Int_.Ary_empty, 1, 2, 3);
Ary_parse__tst("123,321,213" , 3, Int_.Ary_empty, 123, 321, 213);
Ary_parse__tst(" 1, 2,3" , 3, Int_.Ary_empty, 1, 2, 3);
Ary_parse__tst("-1,+2,-3" , 3, Int_.Ary_empty, -1, 2, -3);
Ary_parse__tst(Int_.XtoStr(Int_.MinValue) , 1, Int_.Ary_empty, Int_.MinValue);
Ary_parse__tst(Int_.XtoStr(Int_.MaxValue) , 1, Int_.Ary_empty, Int_.MaxValue);
Ary_parse__tst("1,2" , 1, Int_.Ary_empty);
Ary_parse__tst("1" , 2, Int_.Ary_empty);
Ary_parse__tst("a" , 1, Int_.Ary_empty);
Ary_parse__tst("1-2," , 1, Int_.Ary_empty);
}
void Ary_parse__tst(String raw, int reqd_len, int[] or, int... expd) {Tfds.Eq_ary(expd, Int_.Ary_parse(raw, reqd_len, or));}
}

View File

@ -0,0 +1,95 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Int_ary_ {
public static int[] Parse_list_or(byte[] src, int[] or) {
try {
if (Bry_.Len_eq_0(src)) return or; // null, "" should return [0]
int raw_len = src.length;
int[] rv = null; int rv_idx = 0, rv_len = 0;
int pos = 0;
int num_bgn = -1, num_end = -1;
boolean itm_done = false, itm_is_rng = false;
int rng_bgn = Int_.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 = Bry_.X_to_int_or(src, num_bgn, num_end, Int_.MinValue);
if (num == Int_.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 + ListAdp_.Base1;
if (add_len == 0) return or; // bgn >= end;
}
if (add_len + rv_idx > rv_len) { // ary out of space; resize
rv_len = (add_len + rv_idx) * 2;
rv = (int[])Array_.Resize(rv, rv_len);
}
if (itm_is_rng) {
for (int i = rng_bgn; i <= num; i++)
rv[rv_idx++] = i;
}
else {
rv[rv_idx++] = num;
}
num_bgn = num_end = -1;
itm_done = itm_is_rng = false;
rng_bgn = Int_.MinValue;
if (pos_is_last) break;
}
byte b = src[pos];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
if (num_bgn == -1) // num_bgn not set
num_bgn = pos;
num_end = pos + 1; // num_end is always after pos; EX: "9": num_end = 1; "98,7": num_end=2
break;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn: // NOTE: parseNumList replaces ws with '', so "1 1" will become "11"
break;
case Byte_ascii.Comma:
if (pos == raw_len -1) return or; // eos; EX: "1,"
if (num_bgn == -1) return or; // empty itm; EX: ","; "1,,2"
itm_done = true;
break;
case Byte_ascii.Dash:
if (pos == raw_len -1) return or; // eos; EX: "1-"
if (num_bgn == -1) return or; // no rng_bgn; EX: "-2"
rng_bgn = Bry_.X_to_int_or(src, num_bgn, pos, Int_.MinValue);
if (rng_bgn == Int_.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[])Array_.Resize(rv, rv_idx);
} catch (Exception e) {Err_.Noop(e); return or;}
}
}

View File

@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Int_ary__tst {
private Int_ary__fxt fxt = new Int_ary__fxt();
@Test public void Parse_list_or_() {
fxt.Test_Parse_list_or("1", 1);
fxt.Test_Parse_list_or("123", 123);
fxt.Test_Parse_list_or("1,2,123", 1, 2, 123);
fxt.Test_Parse_list_or("1,2,12,123", 1, 2, 12, 123);
fxt.Test_Parse_list_or("1-5", 1, 2, 3, 4, 5);
fxt.Test_Parse_list_or("1-1", 1);
fxt.Test_Parse_list_or("1-3,7,11-13,21", 1, 2, 3, 7, 11, 12, 13, 21);
fxt.Test_Parse_list_empty("1 2"); // NOTE: MW would gen 12; treat as invalid
fxt.Test_Parse_list_empty("1,"); // eos
fxt.Test_Parse_list_empty("1,,2"); // empty comma
fxt.Test_Parse_list_empty("1-"); // eos
fxt.Test_Parse_list_empty("3-1"); // bgn > end
fxt.Test_Parse_list_empty("1,a,2");
fxt.Test_Parse_list_empty("a-1,2");
fxt.Test_Parse_list_empty("-1"); // no rng bgn
}
}
class Int_ary__fxt {
public void Test_Parse_list_empty(String raw) {Tfds.Eq_ary(Int_.Ary_empty, Int_ary_.Parse_list_or(Bry_.new_ascii_(raw), Int_.Ary_empty));}
public void Test_Parse_list_or(String raw, int... expd) {Tfds.Eq_ary(expd, Int_ary_.Parse_list_or(Bry_.new_ascii_(raw), Int_.Ary_empty));}
}

View File

@ -0,0 +1,44 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Int_obj_ref {
public int Val() {return val;} public Int_obj_ref Val_(int v) {val = v; return this;} int val;
public int Val_add() {val++; return val;}
public int Val_add_post() {return val++;}
public int Val_add(int v) {val += v; return val;}
public Int_obj_ref Val_zero_() {val = 0; return this;}
public Int_obj_ref Val_neg1_() {val = -1; return this;}
@Override public String toString() {return Int_.XtoStr(val);}
@Override public int hashCode() {return val;}
@Override public boolean equals(Object obj) {return val == ((Int_obj_ref)obj).Val();}
public static Int_obj_ref neg1_() {return new_(-1);}
public static Int_obj_ref zero_() {return new_(0);}
public static Int_obj_ref new_(int val) {
Int_obj_ref rv = new Int_obj_ref();
rv.val = val;
return rv;
} Int_obj_ref() {}
public static int[] Ary_xto_int_ary(Int_obj_ref[] ary) {
int len = ary.length;
int[] rv = new int[len];
for (int i = 0; i < len; ++i)
rv[i] = ary[i].val;
return rv;
}
}

View File

@ -0,0 +1,32 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Int_obj_val implements CompareAble {
public int Val() {return val;} int val;
@Override public String toString() {return Int_.XtoStr(val);}
@Override public int hashCode() {return val;}
@Override public boolean equals(Object obj) {return obj == null ? false : val == ((Int_obj_val)obj).Val();}
public int compareTo(Object obj) {Int_obj_val comp = (Int_obj_val)obj; return Int_.Compare(val, comp.val);}
public static Int_obj_val neg1_() {return new_(-1);}
public static Int_obj_val zero_() {return new_(0);}
public static Int_obj_val new_(int val) {
Int_obj_val rv = new Int_obj_val();
rv.val = val;
return rv;
} Int_obj_val() {}
}

View File

@ -0,0 +1,110 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Long_ {
public static final long MinValue = Long.MIN_VALUE;
public static final long MaxValue = Long.MAX_VALUE;
public static final long Neg1 = -1;
public static final int Log10Ary_len = 21;
public static long[] Log10Ary = new long[]
{ 1, 10, 100, 1000, 10000
, 100000, 1000000, 10000000, 100000000, 1000000000
, Long_.Pow(10, 10), Long_.Pow(10, 11), Long_.Pow(10, 12), Long_.Pow(10, 13), Long_.Pow(10, 14)
, Long_.Pow(10, 15), Long_.Pow(10, 16), Long_.Pow(10, 17), Long_.Pow(10, 18), Long_.Pow(10, 19)
, Long_.MaxValue
};
public static String XtoStr(long v) {return Long.toString(v);}
public static String XtoStr_PadBgn(long v, int reqdPlaces) {return String_.Pad(XtoStr(v), reqdPlaces, "0", true);} // ex: 1, 3 returns 001
public static long parse_or_(String raw, int or) {
if (raw == null) return or;
try {
int rawLen = String_.Len(raw);
if (raw == null || rawLen == 0) return or;
long rv = 0, factor = 1; int tmp = 0;
for (int i = rawLen; i > 0; i--) {
tmp = Char_.To_int_or(String_.CharAt(raw, i - 1), Int_.MinValue);
if (tmp == Int_.MinValue) return or;
rv += (tmp * factor);
factor *= 10;
}
return rv;
} catch (Exception e) {Err_.Noop(e); return or;}
}
public static int Compare(long lhs, long rhs) {
if (lhs == rhs) return CompareAble_.Same;
else if (lhs < rhs) return CompareAble_.Less;
else return CompareAble_.More;
}
public static long parse_(String raw) {try {return Long.parseLong(raw);} catch(Exception e) {throw Err_.parse_type_exc_(e, long.class, raw);}}
public static long cast_(Object obj) {try {return (Long)obj;} catch(Exception e) {throw Err_.type_mismatch_exc_(e, long.class, obj);}}
public static long coerce_(Object v) {
try {String s = String_.as_(v); return s == null ? Long_.cast_(v) : Long_.parse_(s);}
catch (Exception e) {throw Err_.cast_(e, long.class, v);}
}
public static int FindIdx(long[] ary, long find_val) {
int ary_len = ary.length;
int adj = 1;
int prv_pos = 0;
int prv_len = ary_len;
int cur_len = 0;
int cur_idx = 0;
long cur_val = 0;
while (true) {
cur_len = prv_len / 2;
if (prv_len % 2 == 1) ++cur_len;
cur_idx = prv_pos + (cur_len * adj);
if (cur_idx < 0) cur_idx = 0;
else if (cur_idx >= ary_len) cur_idx = ary_len - 1;
cur_val = ary[cur_idx];
if (find_val < cur_val) adj = -1;
else if (find_val > cur_val) adj = 1;
else if (find_val == cur_val) return cur_idx;
if (cur_len == 1) {
if (adj == -1 && cur_idx > 0)
return --cur_idx;
return cur_idx;
}
prv_len = cur_len;
prv_pos = cur_idx;
}
}
public static int DigitCount(long v) {
int adj = Int_.Base1;
if (v < 0) {
if (v == Long_.MinValue) return 19; // NOTE: Long_.MinValue * -1 = Long_.MinValue
v *= -1;
++adj;
}
return FindIdx(Log10Ary, v) + adj;
}
public static long Pow(int val, int exp) {
long rv = val;
for (int i = 1; i < exp; i++)
rv *= val;
return rv;
}
public static long Int_merge(int hi, int lo) {return (long)hi << 32 | (lo & 0xFFFFFFFFL);}
public static int Int_split_lo(long v) {return (int)(v);}
public static int Int_split_hi(long v) {return (int)(v >> 32);}
public static long X_by_int(int v) {return (long)v;}
}
/* 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;}
*/

View File

@ -0,0 +1,49 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Long__tst {
@Test public void DigitCount() {
tst_DigitCount(0, 1);
tst_DigitCount(1, 1);
tst_DigitCount(9, 1);
tst_DigitCount(10, 2);
tst_DigitCount(100, 3);
tst_DigitCount(10000, 5);
tst_DigitCount(100000, 6);
tst_DigitCount(1000000, 7);
tst_DigitCount(1000000000, 10);
tst_DigitCount(10000000000L, 11);
tst_DigitCount(100000000000L, 12);
tst_DigitCount(10000000000000000L, 17);
tst_DigitCount(-1, 2);
} void tst_DigitCount(long val, int expd) {Tfds.Eq(expd, Long_.DigitCount(val));}
@Test public void Int_merge() {
tst_Int_merge(123, 456, 528280977864L);
tst_Int_merge(123, 457, 528280977865L);
}
void tst_Int_merge(int hi, int lo, long expd) {
Tfds.Eq(expd, Long_.Int_merge(hi, lo));
Tfds.Eq(hi, Long_.Int_split_hi(expd));
Tfds.Eq(lo, Long_.Int_split_lo(expd));
}
@Test public void parse_or_() {
parse_or_tst("10000000000", 10000000000L);
}
void parse_or_tst(String raw, long expd) {Tfds.Eq(expd, Long_.parse_or_(raw, -1));}
}

View File

@ -0,0 +1,41 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Object_ {
public static final Object[] Ary_empty = new Object[0];
public static Object[] Ary(Object... ary) {return ary;}
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 Object Parse(String val, String valType) {
if (String_.Eq(valType, IntClassXtn.Key_const)) return Int_.parse_(val);
else return val;
}
public static String XtoStr_OrNull(Object v) {return v == null ? null : ToString_lang(v);}
public static String XtoStr_OrNullStr(Object v) {return v == null ? String_.Null_mark : ToString_lang(v);}
public static String XtoStr_OrEmpty(Object v) {return v == null ? String_.Empty : ToString_lang(v);}
static String ToString_lang(Object v) {
if (v == null) return null;
Class<?> c = v.getClass();
if (ClassAdp_.Eq(c, Bry_.ClassOf)) return String_.new_utf8_((byte[])v);
else if (ClassAdp_.Eq(c, String_.ClassOf)) return (String)v;
else return v.toString();
}
}

View File

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class Object__tst {
@Test public void Eq() {
tst_Eq(null, null, true); // both null
tst_Eq(5, 5, true); // both non-null
tst_Eq(5, null, false); // rhs non-null
tst_Eq(null, 5, false); // lhs non-null
} void tst_Eq(Object lhs, Object rhs, boolean expd) {Tfds.Eq(expd, Object_.Eq(lhs, rhs));}
}

View File

@ -0,0 +1,21 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class Short_ {
public static short cast_(Object obj) {try {return (Short)obj;} catch(Exception exc) {throw Err_.type_mismatch_exc_(exc, short.class, obj);}}
}

View File

@ -0,0 +1,523 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.lang.*;
public class String_ implements GfoInvkAble {
public static final Class<?> ClassOf = String.class;
public static final int Find_none = -1, Pos_neg1 = -1;
public static final String Null = null, Empty = "", Null_mark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n";
public static String cast_(Object v) {return (String)v;}
public static String as_(Object obj) {return obj instanceof String ? (String)obj : null;}
public static String new_ascii_(byte[] v) {return v == null ? null : new_ascii_(v, 0, v.length);}
public static String new_ascii_(byte[] v, int bgn, int end) {
try {
return v == null
? null
: new String(v, bgn, end - bgn, "ASCII");
}
catch (Exception e) {throw Err_.err_(e, "unsupported encoding");}
}
public static String new_utf8_(byte[] v) {return v == null ? null : new_utf8_(v, 0, v.length);}
public static String new_utf8_mid_safe_(byte[] v, int bgn, int end) {return v == null ? null : new_utf8_(v, bgn, end);}
public static String new_utf8_(byte[] v, int bgn, int end) {
try {
return v == null
? null
: new String(v, bgn, end - bgn, "UTF-8");
}
catch (Exception e) {throw Err_.err_(e, "unsupported encoding");}
}
public static String new_utf8_len_safe_(byte[] v, int bgn, int len) {
int v_len = v.length;
if (bgn + len > v_len) len = v_len - bgn;
return new_utf8_(v, bgn, bgn + len);
}
public static String[] Ary_add(String[]... arys) {
if (arys == null) return String_.Ary_empty;
int arys_len = arys.length;
int rv_len = 0;
for (int i = 0; i < arys_len; i++) {
String[] ary = arys[i];
rv_len += ary.length;
}
int rv_idx = 0;
String[] rv = new String[rv_len];
for (int i = 0; i < arys_len; i++) {
String[] ary = arys[i];
int ary_len = ary.length;
for (int j = 0; j < ary_len; j++)
rv[rv_idx++] = ary[j];
}
return rv;
}
public static boolean Len_gt_0(String s) {return s != null && s.length() > 0;}
public static boolean Len_eq_0(String s) {return s == null || s.length() == 0;}
public static int Len(String s) {return s.length();}
public static String Lower(String s) {return s.toLowerCase();}
public static String Upper(String s) {return s.toUpperCase();}
public static String CaseNormalize(boolean caseSensitive, String s) {return caseSensitive ? s : String_.Lower(s);}
public static String Trim(String s) {return s.trim();}
public static String Mid(String s, int bgn) {return s.substring(bgn);}
public static String Replace(String s, String find, String replace) {return s.replace(find, replace);}
public static char[] XtoCharAry(String s) {return s.toCharArray();}
public static char CharAt(String s, int i) {return s.charAt(i);}
public static int CodePointAt(String s, int i) {return s.codePointAt(i);}
public static boolean Has(String s, String find) {return s.indexOf(find) != String_.Find_none;}
public static boolean HasAtBgn(String s, String v) {return s.startsWith(v);}
public static boolean HasAtEnd(String s, String v) {return s.endsWith(v);}
public static int FindFwd(String s, String find) {return s.indexOf(find);}
public static int FindFwd(String s, String find, int pos) {return s.indexOf(find, pos);}
public static int FindBwd(String s, String find) {return s.lastIndexOf(find);}
public static int FindBwd(String s, String find, int pos) {
return s.lastIndexOf(find, pos);
}
public static int FindBetween(String s, String find, int bgn, int end) {
int rv = FindFwd(s, find, bgn);
return (rv > end) ? String_.Find_none : rv;
}
public static int FindAfter(String s, String find, int bgn) {
int rv = FindFwd(s, find, bgn);
return rv == String_.Find_none ? String_.Find_none : rv + Len(find);
}
public static int FindAfterRev(String s, String find, int pos) {
int rv = FindBwd(s, find, pos);
return rv == String_.Find_none ? String_.Find_none : rv + Len(find);
}
public static int Count(String s, String part) {
int count = 0, pos = -1; // -1 b/c first pass must be 0 (see pos + 1 below)
do {
pos = FindFwd(s, part, pos + 1);
if (pos == String_.Find_none) break;
count++;
} while (true);
return count;
}
public static boolean Eq(String lhs, String rhs) {return lhs == null ? rhs == null : lhs.equals(rhs);}
public static boolean EqAny(String lhs, String... rhsAry) {
for (int i = 0; i < rhsAry.length; i++)
if (Eq(lhs, rhsAry[i])) return true;
return false;
}
public static boolean EqNot(String lhs, String rhs) {return !Object_.Eq(lhs, rhs);}
public static boolean EqEmpty(String lhs, String rhs) {return lhs.equals("");}
public static String IfNullOrEmpty(String s, String or) {return s == null || s.length() == 0 ? or : s;}
public static int Compare(String lhs, String rhs) {return lhs.compareTo(rhs);} // NOTE: Compare instead of compareTo b/c javafy lowercases compareTo
public static int Compare_ignoreCase(String lhs, String rhs) {
if (lhs == null && rhs != null) return CompareAble_.Less;
else if (lhs != null && rhs == null) return CompareAble_.More;
else if (lhs == null && rhs == null) return CompareAble_.Same;
else return lhs.compareToIgnoreCase(rhs);
//#-
/*
if (lhs == null && rhs != null) return CompareAble_.Less;
else if (lhs != null && rhs == null) return CompareAble_.More;
else if (lhs == null && rhs == null) return CompareAble_.Same;
else return lhs.compareToIgnoreCase(rhs);
*/
}
public static int Compare_strict(String lhs, String rhs) {
int compare = String_.Compare(lhs, rhs);
if (compare == CompareAble_.Same) return CompareAble_.Same;
else if (compare < CompareAble_.Same) return CompareAble_.Less;
else /* (compare > CompareAble_.Same) */ return CompareAble_.More;
}
public static int Compare_byteAry(String lhs, String rhs) {
int lhsLen = lhs.length(), rhsLen = rhs.length();
int aryLen = lhsLen < rhsLen ? lhsLen : rhsLen;
int[] lhsAry = XtoIntAry(lhs, aryLen), rhsAry = XtoIntAry(rhs, aryLen);
for (int i = 0; i < aryLen; i++) {
int comp = Int_.Compare(lhsAry[i], rhsAry[i]);
if (comp != CompareAble_.Same) return comp;
}
return Int_.Compare(lhsLen, rhsLen);
}
public static int[] XtoIntAry(String s, int len) {
int[] rv = new int[len];
for (int i = 0; i < len; i++)
rv[i] = (int)s.charAt(i);
return rv;
}
public static String Coalesce(String s, String alt) {return Len(s) == 0 ? alt : s;}
public static boolean In(String s, String... ary) {
for (String itm : ary)
if (String_.Eq(s, itm)) return true;
return false;
}
public static String new_charAry_(char[] ary, int bgn, int len) {return new String(ary, bgn, len);}
public static String Mid(String s, int bgn, int end) {
try {return Mid_lang(s, bgn, end - bgn);}
catch (Exception e) {
int len = s == null ? 0 : Len(s);
Err err = Err_.new_("unknown error").Add("s", s).Add("bgn", bgn).Add("end", end).Add("len", len).Add("e", Err_.Message_lang(e));
if (s == null) err.Hdr_("s is null");
else if (bgn > end) err.Hdr_("@bgn > @end");
else if (bgn < 0 || bgn >= len) err.Hdr_("@bgn is invalid");
else if (end < 0 || end > len) err.Hdr_("@end is invalid");
throw err;
}
}
public static String MidByLenSafe(String s, int bgn, int len) {
if (bgn + len >= Len(s)) len = Len(s) - bgn;
return Mid_lang(s, bgn, len);
}
public static String MidByLen(String s, int bgn, int len) {return Mid_lang(s, bgn, len);}
public static String GetStrBefore(String s, String spr) {
int sprPos = String_.FindFwd(s, spr); if (sprPos == String_.Find_none) throw Err_.new_("could not find spr").Add("s", s).Add("spr", spr);
return Mid(s, 0, sprPos);
}
public static String GetStrAfter(String s, String spr) {
int sprPos = String_.FindFwd(s, spr); if (sprPos == String_.Find_none) throw Err_.new_("could not find spr").Add("s", s).Add("spr", spr);
return Mid(s, sprPos + 1);
}
public static String LimitToFirst(String s, int len) {
if (len < 0) throw Err_arg.cannotBe_("< 0", "len", len);
int sLen = Len(s); if (len > sLen) return s;
return Mid_lang(s, 0, len);
}
public static String LimitToLast(String s, int len) {
if (len < 0) throw Err_arg.cannotBe_("< 0", "len", len);
int sLen = Len(s); if (len > sLen) return s;
return Mid_lang(s, sLen - len, len);
}
public static String DelBgn(String s, int count) {
if (count < 0) throw Err_arg.cannotBe_("< 0", "count", count);
if (s == null) throw Err_arg.null_("s");
int len = Len(s); if (count > len) throw Err_arg.cannotBe_("> @len", "count", count).Add("len", len);
return String_.Mid(s, count);
}
public static String DelBgnIf(String s, String find) {
if (s == null) throw Err_arg.null_("s"); if (find == null) throw Err_arg.null_("find");
return HasAtBgn(s, find) ? String_.Mid(s, Len(find)) : s;
}
public static String DelEnd(String s, int count) {
if (count < 0) throw Err_arg.cannotBe_("< 0", "count", count);
if (s == null) throw Err_arg.null_("s");
int len = Len(s); if (count > len) throw Err_arg.cannotBe_("> len", "count", count).Add("len", len);
return Mid_lang(s, 0, len + -count);
}
public static String DelEndIf(String s, String find) {
if (s == null) throw Err_arg.null_("s"); if (find == null) throw Err_arg.null_("find");
return HasAtEnd(s, find) ? Mid_lang(s, 0, Len(s) - Len(find)) : s;
}
public static String LowerFirst(String s) {
int len = Len(s); if (len == 0) return String_.Empty;
String char0 = Lower(Mid_lang(s, 0, 1));
return len == 1 ? char0 : char0 + Mid(s, 1);
}
public static String UpperFirst(String s) {
int len = Len(s); if (len == 0) return String_.Empty;
String char0 = Upper(Mid_lang(s, 0, 1));
return len == 1 ? char0 : char0 + Mid(s, 1);
}
public static String PadBgn(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, true);}
public static String PadEnd(String s, int totalLen, String pad) {return Pad(s, totalLen, pad, false);}
@gplx.Internal protected static String Pad(String s, int totalLen, String pad, boolean bgn) {
int sLen = Len(s);
int padLen = totalLen - sLen; if (padLen < 0) return s;
String_bldr sb = String_bldr_.new_();
if (!bgn) sb.Add(s);
for (int i = 0; i < padLen; i++)
sb.Add(pad);
if (bgn) sb.Add(s);
return sb.XtoStr();
}
public static String TrimEnd(String s) {if (s == null) return null;
int len = String_.Len(s);
if (len == 0) return s;
int last = len;
for (int i = len; i > 0; i--) {
char c = s.charAt(i - 1);
last = i;
if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
break;
}
}
return (last == len) ? s : Mid_lang(s, 0, last);
}
public static String Repeat(String s, int count) {
if (count < 0) throw Err_.new_("count cannot be negative").Add("count", count).Add("s", s);
String_bldr sb = String_bldr_.new_();
for (int i = 0; i < count; i++)
sb.Add(s);
return sb.XtoStr();
}
public static String Insert(String s, int pos, String toInsert) {
if (pos < 0 || pos >= String_.Len(s)) throw Err_.new_("String_.Insert failed; pos invalid").Add("pos", pos).Add("s", s).Add("toInsert", toInsert);
return s.substring(0, pos) + toInsert + s.substring(pos);
}
public static String Format(String fmt, Object... args) {return Format_do(fmt, args);}
public static String FormatOrEmptyStrIfNull(String fmt, Object arg) {return arg == null ? "" : Format(fmt, arg);}
public static String Concat(char... ary) {return new String(ary);}
public static String Concat(String s1, String s2, String s3) {return s1 + s2 + s3;}
public static String Concat(String... ary) {
String_bldr sb = String_bldr_.new_();
for (String val : ary)
sb.Add(val);
return sb.XtoStr();
}
public static String Concat_any(Object... ary) {
String_bldr sb = String_bldr_.new_();
for (Object val : ary)
sb.Add_obj(val);
return sb.XtoStr();
}
public static String ConcatWith_any(String separator, Object... ary) {
String_bldr sb = String_bldr_.new_();
int aryLen = Array_.Len(ary);
for (int i = 0; i < aryLen; i++) {
if (i != 0) sb.Add(separator);
Object val = ary[i];
sb.Add_obj(Object_.XtoStr_OrEmpty(val));
}
return sb.XtoStr();
}
public static String Concat_with_str(String spr, String... ary) {
String_bldr sb = String_bldr_.new_();
int len = ary.length;
for (int i = 0; i < len; i++) {
if (i != 0) sb.Add(spr);
sb.Add_obj(ary[i]);
}
return sb.XtoStr();
}
public static String Concat_lines_crlf(String... values) {
String_bldr sb = String_bldr_.new_();
for (String val : values)
sb.Add(val).Add(String_.CrLf);
return sb.XtoStr();
}
public static String Concat_lines_crlf_skipLast(String... values) {
String_bldr sb = String_bldr_.new_();
for (String val : values) {
if (sb.Count() != 0) sb.Add(String_.CrLf);
sb.Add(val);
}
return sb.XtoStr();
}
public static String Concat_lines_nl(String... values) {
String_bldr sb = String_bldr_.new_();
for (String val : values)
sb.Add(val).Add("\n");
return sb.XtoStr();
}
public static String Concat_lines_nl_skip_last(String... ary) {
String_bldr sb = String_bldr_.new_();
int ary_len = ary.length; int ary_end = ary_len - 1;
for (int i = 0; i < ary_len; i++) {
sb.Add(ary[i]);
if (i != ary_end) sb.Add("\n");
}
return sb.XtoStr();
}
public static String[] Ary(String... ary) {return ary;}
public static String AryXtoStr(String... ary) {
String_bldr sb = String_bldr_.new_();
for (String s : ary)
sb.Add(s).Add(";");
return sb.XtoStr();
}
public static final String[] Ary_empty = new String[0];
public static String[] Split(String raw, char dlm) {return Split(raw, dlm, false);}
public static String[] Split(String raw, char dlm, boolean addEmptyIfDlmIsLast) {
ListAdp list = ListAdp_.new_(); String_bldr sb = String_bldr_.new_();
int rawLen = String_.Len(raw); char c = '\0';
for (int i = 0; i < rawLen; i++) {
c = String_.CharAt(raw, i);
if (c == dlm) {
if (!addEmptyIfDlmIsLast && sb.Count() == 0 && i == rawLen - 1) {}
else list.Add(sb.XtoStrAndClear());
}
else
sb.Add(c);
}
if (sb.Count() > 0)
list.Add(sb.XtoStrAndClear());
return list.XtoStrAry();
}
public static String[] Split(String s, String separator) {return Split_do(s, separator, false);}
public static String[] SplitLines_crlf(String s) {return Split(s, Op_sys.Wnt.Nl_str());}
public static String[] SplitLines_nl(String s) {return Split(s, Op_sys.Lnx.Nl_str());}
public static String[] SplitLines_any(String s) {return Split_do(s, Op_sys.Lnx.Nl_str(), true);}
static String Format_do(String s, Object[] ary) {
int aryLength = Array_.LenAry(ary); if (aryLength == 0) return s; // nothing to format
String_bldr sb = String_bldr_.new_();
char bracketBgn = '{', bracketEnd = '}';
String aryVal = null; char c, next;
int pos = 0; int textLength = Len(s); String numberStr = ""; boolean bracketsOn = false;
while (true) {
if (pos == textLength) break;
c = CharAt(s, pos);
if (bracketsOn) { // mode=bracketsOn
if (c == bracketBgn) { // first bracketBgn is fake; add bracketBgn and whatever is in numberStr
sb.Add(bracketBgn).Add(numberStr);
numberStr = "";
}
else if (c == bracketEnd) {
int aryIdx = Int_.parse_or_(numberStr, Int_.MinValue);
if (aryIdx != Int_.MinValue && Int_.Between(aryIdx, 0, aryLength - 1)) // check (a) aryIdx is num; (b) aryIdx is in bounds
aryVal = Object_.XtoStr_OrEmpty(ary[aryIdx]);
else
aryVal = String_.Concat_any(bracketBgn, numberStr, bracketEnd); // not valid, just add String
sb.Add(aryVal);
bracketsOn = false;
numberStr = "";
}
else // char=anythingElse
numberStr += c;
}
else { // mode=bracketsOff
if (c == bracketBgn || c == bracketEnd) {
boolean isEnd = pos == textLength - 1;
if (isEnd)
sb.Add(c);
else {
next = CharAt(s, pos + 1);
if (next == c) { // "{{" or "}}": escape by doubling
sb.Add(c);
pos++;
}
else
bracketsOn = true;
}
}
else // char=anythingElse
sb.Add(c);
}
pos++;
}
if (Len(numberStr) > 0) // unclosed bracket; add bracketBgn and whatever is in numberStr; ex: "{0"
sb.Add(bracketBgn).Add(numberStr);
return sb.XtoStr();
}
static String[] Split_do(String s, String spr, boolean skipChar13) {
if (String_.Eq(s, "") // "".Split('a') return array with one member: ""
|| String_.Eq(spr, "")) // "a".Split('\0') returns array with one member: "a"
return new String[] {s};
ListAdp list = ListAdp_.new_(); String_bldr sb = String_bldr_.new_();
int i = 0, sprPos = 0; boolean sprMatched = false; char spr0 = CharAt(spr, 0);
int textLength = Len(s); int sprLength = Len(spr);
while (true) {
if (sprMatched
|| i == textLength) { // last pass; add whatever's in sb to list
list.Add(sb.XtoStrAndClear());
if (sprMatched && i == textLength) list.Add(""); // if s ends with spr and last pass, add emptyString as last
sprMatched = false;
}
if (i == textLength) break;
char c = CharAt(s, i);
if (skipChar13 && c == (char)13) {i++; continue;}
if (c == spr0) { // matches first char of spr
sprPos = 1;
while (true) {
if (sprPos == sprLength) { // made it to end, must be match
sprMatched = true;
break;
}
if (i + sprPos == textLength) break; // ran out of s; handles partial match at end of String; ab+, +-
if (CharAt(s, i + sprPos) != CharAt(spr, sprPos)) break; // no match
sprPos++;
}
if (!sprMatched) // add partial match to sb
sb.Add(Mid_lang(s, i, sprPos));
i += sprPos;
}
else { // no spr match; just add char, increment pos
sb.Add(c);
i++;
}
}
return (String[])list.XtoAry(String.class);
}
static String Mid_lang(String s, int bgn, int len) {return s.substring(bgn, bgn + len);}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_Replace)) {
String s = m.ReadStr(GfsCore_.Arg_primitive), find = m.ReadStr("find"), replace = m.ReadStr("replace");
if (ctx.Deny()) return this;
return Replace(s, find, replace);
}
else if (ctx.Match(k, Invk_Len)) {
String s = m.ReadStr(GfsCore_.Arg_primitive);
if (ctx.Deny()) return this;
return Len(s);
}
else if (ctx.Match(k, Invk_PadBgn)) {
String s = m.ReadStr(GfsCore_.Arg_primitive); int totalLen = m.ReadInt("totalLen"); String pad = m.ReadStr("pad");
if (ctx.Deny()) return this;
return PadBgn(s, totalLen, pad);
}
else return GfoInvkAble_.Rv_unhandled;
} public static final String Invk_Replace = "Replace", Invk_Len = "Len", Invk_PadBgn = "PadBgn";
public static final String_ Gfs = new String_();
public static String Extract_after_bwd(String src, String dlm) {
int dlm_pos = String_.FindBwd(src, dlm); if (dlm_pos == String_.Find_none) return String_.Empty;
int src_len = String_.Len(src); if (dlm_pos == src_len - 1) return String_.Empty;
return String_.Mid(src, dlm_pos + 1, src_len);
}
public static String Replace_by_pos(String v, int del_bgn, int del_end, String repl) {
return String_.Mid(v, 0, del_bgn) + repl + String_.Mid(v, del_end, String_.Len(v));
}
public static String read_(Object obj) {// NOTE: same as cast_; for consistent readability only
String rv = as_(obj);
if (rv == null && obj != null) throw Err_.type_mismatch_(String.class, obj); // NOTE: obj != null needed; EX: cast_(null) --> null
return rv;
}
public static String[] Ary(byte[]... ary) {
if (ary == null) return String_.Ary_empty;
int ary_len = ary.length;
String[] rv = new String[ary_len];
for (int i = 0; i < ary_len; i++)
rv[i] = String_.new_utf8_(ary[i]);
return rv;
}
public static String [] Ary_filter(String[] src, String[] filter) {
HashAdp hash = HashAdp_.new_();
int len = filter.length;
for (int i = 0; i < len; i++) {
String itm = filter[i];
hash.AddReplace(itm, itm);
}
ListAdp rv = ListAdp_.new_();
len = src.length;
for (int i = 0; i < len; i++) {
String itm = src[i];
if (hash.Has(itm)) rv.Add(itm);
}
return rv.XtoStrAry();
}
public static String[] Ary_flatten(String[][] src_ary) {
int trg_len = 0;
int src_len = Array_.Len(src_ary);
for (int i = 0; i < src_len; i++) {
String[] itm = src_ary[i];
if (itm != null) trg_len += Array_.Len(itm);
}
String[] trg_ary = new String[trg_len];
trg_len = 0;
for (int i = 0; i < src_len; i++) {
String[] itm = src_ary[i];
if (itm == null) continue;
int itm_len = Array_.Len(itm);
for (int j = 0; j < itm_len; j++)
trg_ary[trg_len++] = itm[j];
}
return trg_ary;
}
}

View File

@ -0,0 +1,184 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class String__tst {
@Test public void Len() {
tst_Len("", 0);
tst_Len("abc", 3);
} void tst_Len(String v, int expd) {Tfds.Eq(expd, String_.Len(v), "Len");}
@Test public void LimitToFirst() {
tst_LimitToFirst("abc", 0, "");
tst_LimitToFirst("abc", 1, "a");
tst_LimitToFirst("abc", 2, "ab");
tst_LimitToFirst("abc", 3, "abc");
tst_LimitToFirst("abc", 4, "abc");
err_LimitToFirst("abc", -1);
}
void tst_LimitToFirst(String s, int v, String expd) {Tfds.Eq(expd, String_.LimitToFirst(s, v));}
void err_LimitToFirst(String s, int v) {try {String_.LimitToFirst(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void LimitToLast() {
tst_LimitToLast("abc", 0, "");
tst_LimitToLast("abc", 1, "c");
tst_LimitToLast("abc", 2, "bc");
tst_LimitToLast("abc", 3, "abc");
tst_LimitToLast("abc", 4, "abc");
err_LimitToLast("abc", -1);
}
void tst_LimitToLast(String s, int v, String expd) {Tfds.Eq(expd, String_.LimitToLast(s, v));}
void err_LimitToLast(String s, int v) {try {String_.LimitToLast(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void DelBgn() {
tst_DelBgn("abc", 0, "abc");
tst_DelBgn("abc", 1, "bc");
tst_DelBgn("abc", 2, "c");
tst_DelBgn("abc", 3, "");
err_DelBgn(null, 0);
err_DelBgn("abc", 4);
}
void tst_DelBgn(String s, int v, String expd) {Tfds.Eq(expd, String_.DelBgn(s, v));}
void err_DelBgn(String s, int v) {try {String_.DelBgn(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void DelBgnIf() {
tst_DelBgnIf("abc", "", "abc");
tst_DelBgnIf("abc", "a", "bc");
tst_DelBgnIf("abc", "ab", "c");
tst_DelBgnIf("abc", "abc", "");
tst_DelBgnIf("abc", "abcd", "abc");
tst_DelBgnIf("abc", "bcd", "abc");
err_DelBgnIf(null, "abc");
err_DelBgnIf("abc", null);
}
void tst_DelBgnIf(String s, String v, String expd) {Tfds.Eq(expd, String_.DelBgnIf(s, v));}
void err_DelBgnIf(String s, String v) {try {String_.DelBgnIf(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void DelEnd() {
tst_DelEnd("abc", 0, "abc");
tst_DelEnd("abc", 1, "ab");
tst_DelEnd("abc", 2, "a");
tst_DelEnd("abc", 3, "");
err_DelEnd(null, 0);
err_DelEnd("abc", 4);
}
void tst_DelEnd(String s, int v, String expd) {Tfds.Eq(expd, String_.DelEnd(s, v));}
void err_DelEnd(String s, int v) {try {String_.DelEnd(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void DelEndIf() {
tst_DelEndIf("abc", "", "abc");
tst_DelEndIf("abc", "c", "ab");
tst_DelEndIf("abc", "bc", "a");
tst_DelEndIf("abc", "abc", "");
tst_DelEndIf("abc", "abcd", "abc");
tst_DelEndIf("abc", "ab", "abc");
err_DelEndIf(null, "");
err_DelEndIf("", null);
}
void tst_DelEndIf(String s, String v, String expd) {Tfds.Eq(expd, String_.DelEndIf(s, v));}
void err_DelEndIf(String s, String v) {try {String_.DelEndIf(s, v);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err_arg.class); return;} Tfds.Fail_expdError();}
@Test public void MidByPos() {
tst_MidByPos("abc", 0, 0, "");
tst_MidByPos("abc", 0, 1, "a");
tst_MidByPos("abc", 0, 2, "ab");
tst_MidByPos("abc", 0, 3, "abc");
tst_MidByPos("abc", 2, 3, "c");
err_MidByPos("abc", 1, 5);
// err_MidByPos("abc", 0, 4);
}
void tst_MidByPos(String s, int bgn, int end, String expd) {Tfds.Eq(expd, String_.Mid(s, bgn, end));}
void err_MidByPos(String s, int bgn, int end) {try {String_.Mid(s, bgn, end);} catch (Exception exc) {Tfds.Err_classMatch(exc, Err.class); return;} Tfds.Fail_expdError();}
@Test public void TrimEnd() {
tst_TrimEnd("a", "a");
tst_TrimEnd("a ", "a");
tst_TrimEnd("a\t", "a");
tst_TrimEnd("a\n", "a");
tst_TrimEnd("a\r", "a");
tst_TrimEnd("a\r\n \t", "a");
tst_TrimEnd(" a", " a");
tst_TrimEnd(null, null);
}
void tst_TrimEnd(String s, String expd) {Tfds.Eq(expd, String_.TrimEnd(s));}
@Test public void Count() {
String text = "0 0 0";
Tfds.Eq(3, String_.Count(text, "0"));
}
@Test public void Has() {
String text = "find word";
Tfds.Eq_true(String_.Has(text, "word"));
Tfds.Eq_false(String_.Has(text, "nothing"));
}
@Test public void Repeat() {
Tfds.Eq("333", String_.Repeat("3", 3));
}
@Test public void Format() {
tst_Format("", ""); // empty
tst_Format("no args", "no args"); // no args
tst_Format("0", "{0}", 0); // one
tst_Format("0 and 1", "{0} and {1}", 0, 1); // many
tst_Format("{", "{{", 0); // escape bracketBgn
tst_Format("}", "}}", 0); // escape bracketEnd
tst_Format("{a0c}", "{a{0}c}", 0); // nested;
tst_Format("{a{b}c}", "{a{b}c}", 0); // invalid invalid
tst_Format("{1}", "{1}", 1); // invalid array index
tst_Format("{a} {b}", "{a} {b}", 0); // invalid many
tst_Format("{a}0{b}1", "{a}{0}{b}{1}", 0, 1); // invalid and valid
tst_Format("{0", "{0", 0); // invalid dangling
} void tst_Format(String expd, String fmt, Object... ary) {Tfds.Eq(expd, String_.Format(fmt, ary));}
@Test public void Split() {
tst_Split("ab", " ", "ab"); // no match -> return array with original input
tst_Split("ab cd", " ", "ab", "cd"); // separator.length = 1
tst_Split("ab+!cd", "+!", "ab", "cd"); // separator.length = 2
tst_Split("ab+!cd+!ef", "+!", "ab", "cd", "ef"); // terms = 3
tst_Split("ab+!cd+!", "+!", "ab", "cd", ""); // closing separator
tst_Split("+!ab", "+!", "", "ab"); // opening separator
tst_Split("ab+cd+!ef", "+!", "ab+cd", "ef"); // ignore partial matches
tst_Split("ab+!cd+", "+!", "ab", "cd+"); // ignore partial matches; end of String
// boundary
tst_Split("ab", "", "ab"); // separator.length = 0 -> return array with input as only member
tst_Split("", " ", ""); // empty input -> return array with empty input
// acceptance
tst_Split("this\r\nis\na\rtest\r\n.", "\r\n", "this", "is\na\rtest", ".");
} void tst_Split(String text, String separator, String... expd) {Tfds.Eq_ary(expd, String_.Split(text, separator));}
@Test public void ConcatWith_any() {
tst_ConcatWith_any("a|b", "|", "a", "b"); // do not append final delimiter
tst_ConcatWith_any("a||c", "|", "a", null, "c"); // null
tst_ConcatWith_any("a|b", "|", Object_.Ary("a", "b")); // pass array as arg
} void tst_ConcatWith_any(String expd, String delimiter, Object... array) {Tfds.Eq(expd, String_.ConcatWith_any(delimiter, array));}
@Test public void Compare_byteAry() {
tst_Compare_byteAry("a", "a", CompareAble_.Same);
tst_Compare_byteAry("a", "b", CompareAble_.Less);
tst_Compare_byteAry("b", "a", CompareAble_.More);
tst_Compare_byteAry("ab", "ac", CompareAble_.Less);
tst_Compare_byteAry("ac", "ab", CompareAble_.More);
tst_Compare_byteAry("a", "ab", CompareAble_.Less);
tst_Compare_byteAry("ab", "a", CompareAble_.More);
tst_Compare_byteAry("101", "1-0-1", CompareAble_.More); // NOTE: regular String_.Compare returns Less in .NET, More in Java
tst_Compare_byteAry("1-0-1", "101 (album)", CompareAble_.Less);
} void tst_Compare_byteAry(String lhs, String rhs, int expd) {Tfds.Eq(expd, String_.Compare_byteAry(lhs, rhs));}
@Test public void FindBwd() { // WORKAROUND.CS:String.LastIndexOf returns -1 for multi-chars;
tst_FindRev("abc", "a", 0, 0);
tst_FindRev("abc", "ab", 0, 0); // 2 chars
tst_FindRev("abc", "abc", 0, 0); // 3 chars
tst_FindRev("ab", "abc", 0, -1); // out of index error
tst_FindRev("ababab", "ab", 2, 2); // make sure cs implementation doesn't pick up next
} void tst_FindRev(String s, String find, int pos, int expd) {Tfds.Eq(expd, String_.FindBwd(s, find, pos));}
@Test public void Extract_after_bwd() {
Extract_after_bwd_tst("a/b", "/", "b");
Extract_after_bwd_tst("a/", "/", "");
Extract_after_bwd_tst("a", "/", "");
} void Extract_after_bwd_tst(String src, String dlm, String expd) {Tfds.Eq(expd, String_.Extract_after_bwd(src, dlm));}
}

View File

@ -0,0 +1,30 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class String_obj_ref {
public String Val() {return val;} public String_obj_ref Val_(String v) {val = v; return this;} private String val;
public String_obj_ref Val_null_() {return Val_(null);}
@Override public String toString() {return val;}
public static String_obj_ref empty_() {return new_("");}
public static String_obj_ref null_() {return new_(null);}
public static String_obj_ref new_(String val) {
String_obj_ref rv = new String_obj_ref();
rv.val = val;
return rv;
} String_obj_ref() {}
}

View File

@ -0,0 +1,31 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class String_obj_val implements CompareAble {
public String Val() {return val;} private String val;
@Override public String toString() {return val;}
public int compareTo(Object obj) {
String_obj_val comp = (String_obj_val)obj;
return String_.Compare_strict(val, comp.val);
}
public static String_obj_val new_(String val) {
String_obj_val rv = new String_obj_val();
rv.val = val;
return rv;
} String_obj_val() {}
}

View File

@ -0,0 +1,61 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
public class String_ring {
String[] ary = String_.Ary_empty;
public int Len() {return len;} int len;
public String_ring Max_(int v) {
if (v != max) {
ary = new String[v];
max = v;
}
return this;
} int max;
public void Clear() {
for (int i = 0; i < max; i++) {
ary[i] = null;
}
len = nxt = 0;
}
int nxt;
public void Push(String v) {
int idx = nxt++;
if (idx == max) {
idx = 0;
}
if (nxt == max) {
nxt = 0;
}
ary[idx] = v;
if (len < max)
++len;
}
public String[] Xto_str_ary() {
String[] rv = new String[len];
int ary_i = nxt - 1;
for (int rv_i = len - 1; rv_i > -1; rv_i--) {
if (ary_i == -1) {
ary_i = max - 1;
}
rv[rv_i] = ary[ary_i];
--ary_i;
}
return rv;
}
// public String Get_at(int i) {return }
}

View File

@ -0,0 +1,46 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class String_ring_tst {
String_ring_fxt fxt = new String_ring_fxt();
@Before public void init() {fxt.Clear();}
@Test public void Basic() {
fxt.Clear().Max_(3).Push_many("a") .Expd("a");
fxt.Clear().Max_(3).Push_many("a", "b") .Expd("a", "b");
fxt.Clear().Max_(3).Push_many("a", "b", "c") .Expd("a", "b", "c");
fxt.Clear().Max_(3).Push_many("a", "b", "c", "d") .Expd("b", "c", "d");
fxt.Clear().Max_(3).Push_many("a", "b", "c", "d", "e") .Expd("c", "d", "e");
fxt.Clear().Max_(3).Push_many("a", "b", "c", "d", "e", "f") .Expd("d", "e", "f");
}
}
class String_ring_fxt {
String_ring ring = new String_ring();
public String_ring_fxt Clear() {ring.Clear(); return this;}
public String_ring_fxt Max_(int v) {ring.Max_(v); return this;}
public String_ring_fxt Push_many(String... ary) {
int ary_len = ary.length;
for (int i = 0; i < ary_len; i++)
ring.Push(ary[i]);
return this;
}
public String_ring_fxt Expd(String... expd) {
Tfds.Eq_ary_str(expd, ring.Xto_str_ary());
return this;
}
}

View File

@ -0,0 +1,27 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_ary_dim2 implements Bry_fmtr_arg {
public Bry_fmtr_arg_ary_dim2 Data_(byte[][] v) {ary_dim2 = v; return this;}
public Bry_fmtr_arg_ary_dim2 Ary_dim2_(byte[][] v) {this.ary_dim2 = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {
for (byte[] ary : ary_dim2)
trg.Add(ary);
}
public Bry_fmtr_arg_ary_dim2() {} byte[][] ary_dim2 = new byte[0][];
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_bfr implements Bry_fmtr_arg {
public Bry_fmtr_arg_bfr Data_(Bry_bfr v) {bfr = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {trg.Add_bfr_and_clear(bfr);}
public Bry_fmtr_arg_bfr(Bry_bfr bfr) {this.bfr = bfr;} Bry_bfr bfr;
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_bfr_retain implements Bry_fmtr_arg {
public Bry_fmtr_arg_bfr_retain Data_(Bry_bfr v) {bfr = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {trg.Add_bfr(bfr);}
public Bry_fmtr_arg_bfr_retain(Bry_bfr bfr) {this.bfr = bfr;} Bry_bfr bfr;
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_bry implements Bry_fmtr_arg {
public Bry_fmtr_arg_bry Data_(byte[] v) {ary = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {trg.Add(ary);}
public Bry_fmtr_arg_bry(byte[] v) {this.ary = v;} byte[] ary;
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_byt implements Bry_fmtr_arg {
public Bry_fmtr_arg_byt Data_(byte v) {byt = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {trg.Add_byte(byt);}
public Bry_fmtr_arg_byt(byte byt) {this.byt = byt;} private byte byt;
}

View File

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_decimal_int implements Bry_fmtr_arg {
public int Val() {return val;} public Bry_fmtr_arg_decimal_int Val_(int v) {val = v; return this;} int val;
public Bry_fmtr_arg_decimal_int Places_(int v) {places = v; multiple = (int)Math_.Pow(10, v); return this;} int multiple = 1000, places = 3;
public void XferAry(Bry_bfr bfr, int idx) {
bfr.Add_int_variable(val / multiple).Add_byte(Byte_ascii.Dot).Add_int_fixed(val % multiple, places);
}
}

View File

@ -0,0 +1,25 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_fmtr implements Bry_fmtr_arg {
public Bry_fmtr_arg_fmtr Data_(Bry_fmtr v) {fmtr = v; return this;}
public void XferAry(Bry_bfr trg, int idx) {
fmtr.Bld_bfr(trg, arg_ary);
}
public Bry_fmtr_arg_fmtr(Bry_fmtr fmtr, Bry_fmtr_arg... arg_ary) {this.fmtr = fmtr; this.arg_ary = arg_ary;} Bry_fmtr fmtr; Bry_fmtr_arg[] arg_ary;
}

View File

@ -0,0 +1,23 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_int implements Bry_fmtr_arg {
public Bry_fmtr_arg_int Data_(int v) {val = Int_.cast_(v); val_digits = Int_.DigitCount(val); return this;}
public void XferAry(Bry_bfr trg, int idx) {trg.Add_int_fixed(val, val_digits);}
public Bry_fmtr_arg_int(int v) {this.val = v; this.val_digits = Int_.DigitCount(v);} int val, val_digits;
}

View File

@ -0,0 +1,55 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
public class Bry_fmtr_arg_time implements Bry_fmtr_arg {
public Bry_fmtr_arg_time() {
units_len = units.length;
}
public long Seconds() {return seconds;} public Bry_fmtr_arg_time Seconds_(long v) {seconds = v; return this;} long seconds;
byte[][] segs = new byte[][]
{ Bry_.new_ascii_("d")
, Bry_.new_ascii_("h")
, Bry_.new_ascii_("m")
, Bry_.new_ascii_("s")
};
int[] units = new int[] {86400, 3600, 60, 1};
int units_len;
byte[] spr = new byte[] {Byte_ascii.Space};
public void XferAry(Bry_bfr bfr, int idx) {
if (seconds == 0) { // handle 0 separately (since it will always be < than units[*]
bfr.Add_int_fixed(0, 2).Add(segs[units_len - 1]);
return;
}
long val = seconds;
boolean dirty = false;
for (int i = 0; i < units_len; i++) {
long unit = units[i];
long seg = 0;
if (val >= unit) { // unit has value; EX: 87000 > 86400, so unit is 1 day
seg = val / unit;
val = val - (seg * unit);
}
if (seg > 0 || dirty) { // dirty check allows for 0 in middle units (EX: 1h 0m 1s)
if (dirty) bfr.Add(spr);
if (seg < 10) bfr.Add_byte(Byte_ascii.Num_0); // 0 pad
bfr.Add_long_variable(seg).Add(segs[i]);
dirty = true;
}
}
}
}

View File

@ -0,0 +1,42 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.brys; import gplx.*;
import org.junit.*;
public class Bry_fmtr_arg_time_tst {
@Test public void Basic() {
Time_fmtr_arg_fxt fxt = new Time_fmtr_arg_fxt().Clear();
fxt.XferAry( 1, "01s"); // seconds
fxt.XferAry( 62, "01m 02s"); // minutes
fxt.XferAry( 3723, "01h 02m 03s"); // hours
fxt.XferAry( 93784, "01d 02h 03m 04s"); // days
fxt.XferAry( 0, "00s"); // handle 0 seconds
fxt.XferAry( 3601, "01h 00m 01s"); // handle 0 in middle unit
}
}
class Time_fmtr_arg_fxt {
public Time_fmtr_arg_fxt Clear() {
if (arg == null) arg = new Bry_fmtr_arg_time();
return this;
} Bry_fmtr_arg_time arg;
public void XferAry(int seconds, String expd) {
Bry_bfr bfr = Bry_bfr.reset_(255);
arg.Seconds_(seconds);
arg.XferAry(bfr, 0);
Tfds.Eq(expd, bfr.XtoStr());
}
}

View File

@ -0,0 +1,152 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
public class DateAdp implements CompareAble, GfoInvkAble {
public int compareTo(Object obj) {DateAdp comp = (DateAdp)obj; return under.compareTo(comp.under);}
@Override public String toString() {return XtoStr_gplx_long();}
public String XtoStr_gplx() {return XtoStr_fmt("yyyyMMdd_HHmmss.fff");}
public String XtoStr_gplx_long() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss.fff");}
public String XtoStr_fmt_HHmmss() {return XtoStr_fmt("HH:mm:ss");}
public String XtoStr_fmt_HHmm() {return XtoStr_fmt("HH:mm");}
public String XtoStr_fmt_yyyy_MM_dd() {return XtoStr_fmt("yyyy-MM-dd");}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_XtoStr_fmt)) return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");
else if (ctx.Match(k, Invk_AddDays)) {
int days = m.ReadInt("days");
if (ctx.Deny()) return this;
return this.Add_day(days);
}
else return GfoInvkAble_.Rv_unhandled;
} public static final String Invk_XtoStr_fmt = "XtoStr_fmt", Invk_AddDays = "Add_day";
public int Segment(int segmentIdx) {
switch (segmentIdx) {
case DateAdp_.SegIdx_year: return this.Year();
case DateAdp_.SegIdx_month: return this.Month();
case DateAdp_.SegIdx_day: return this.Day();
case DateAdp_.SegIdx_hour: return this.Hour();
case DateAdp_.SegIdx_minute: return this.Minute();
case DateAdp_.SegIdx_second: return this.Second();
case DateAdp_.SegIdx_frac: return this.Frac();
case DateAdp_.SegIdx_dayOfWeek: return this.DayOfWeek();
case DateAdp_.SegIdx_weekOfYear: return this.WeekOfYear();
case DateAdp_.SegIdx_dayOfYear: return this.DayOfYear();
default: throw Err_.unhandled(segmentIdx);
}
}
public int[] XtoSegAry() {
int[] rv = new int[7];
rv[DateAdp_.SegIdx_year] = this.Year();
rv[DateAdp_.SegIdx_month] = this.Month();
rv[DateAdp_.SegIdx_day] = this.Day();
rv[DateAdp_.SegIdx_hour] = this.Hour();
rv[DateAdp_.SegIdx_minute] = this.Minute();
rv[DateAdp_.SegIdx_second] = this.Second();
rv[DateAdp_.SegIdx_frac] = this.Frac();
return rv;
}
public String XtoStr_fmt_yyyyMMdd_HHmmss() {return XtoStr_fmt("yyyyMMdd_HHmmss");}
public String XtoStr_fmt_yyyyMMdd_HHmmss_fff() {return XtoStr_fmt("yyyyMMdd_HHmmss.fff");}
public String XtoStr_fmt_yyyyMMdd_HHmm() {return XtoStr_fmt("yyyyMMdd_HHmm");}
public String XtoStr_fmt_yyyy_MM_dd_HH_mm() {return XtoStr_fmt("yyyy-MM-dd HH:mm");}
public String XtoStr_fmt_yyyy_MM_dd_HH_mm_ss() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");}
public String XtoStr_fmt_iso_8561() {return XtoStr_fmt("yyyy-MM-dd HH:mm:ss");}
public static int Timezone_offset_test = Int_.MinValue;
public Calendar UnderDateTime() {return under;} Calendar under;
public int Year() {return under.get(Calendar.YEAR);}
public int Month() {return under.get(Calendar.MONTH) + Month_base0adj;}
public int Day() {return under.get(Calendar.DAY_OF_MONTH);}
public int Hour() {return under.get(Calendar.HOUR_OF_DAY);}
public int Minute() {return under.get(Calendar.MINUTE);}
public int Second() {return under.get(Calendar.SECOND);}
public int DayOfWeek() {return under.get(Calendar.DAY_OF_WEEK) - 1;} // -1 : Base0; NOTE: dotnet/php is also Sunday=0
public int DayOfYear() {return under.get(Calendar.DAY_OF_YEAR);}
public int Timezone_offset() {
return Timezone_offset_test == Int_.MinValue // Timezone_offset_test not over-ridden
? 0
// ? under.getTimeZone().getOffset(this.Timestamp_unix()) / 1000 // divide by 1000 to convert from ms to seconds
: Timezone_offset_test
;
}
public DateAdp XtoUtc() {
java.util.Date date = under.getTime();
java.util.TimeZone tz = under.getTimeZone();
long msFromEpochGmt = date.getTime();
int offsetFromUTC = tz.getOffset(msFromEpochGmt);
Calendar gmtCal = Calendar.getInstance();
gmtCal.setTimeInMillis(msFromEpochGmt + -offsetFromUTC);
return new DateAdp(gmtCal);
}
public DateAdp XtoLocal() {
java.util.Date date = under.getTime();
java.util.TimeZone tz = under.getTimeZone();
long msFromEpochGmt = date.getTime();
int offsetFromUTC = tz.getOffset(msFromEpochGmt);
Calendar gmtCal = Calendar.getInstance();
gmtCal.setTimeInMillis(msFromEpochGmt + offsetFromUTC);
return new DateAdp(gmtCal);
}
public long Timestamp_unix() {
long offsetFromUTC = (under.getTimeZone().getOffset(0));
boolean dst = TimeZone.getDefault().inDaylightTime(under.getTime());
long dst_adj = dst ? 3600000 : 0;
return (under.getTimeInMillis() + offsetFromUTC + dst_adj) / 1000;
}
public int WeekOfYear() {return under.get(Calendar.WEEK_OF_YEAR);}
public int Frac() {return under.get(Calendar.MILLISECOND);}
public DateAdp Add_frac(int val) {return CloneAndAdd(Calendar.MILLISECOND, val);}
public DateAdp Add_second(int val) {return CloneAndAdd(Calendar.SECOND, val);}
public DateAdp Add_minute(int val) {return CloneAndAdd(Calendar.MINUTE, val);}
public DateAdp Add_hour(int val) {return CloneAndAdd(Calendar.HOUR, val);}
public DateAdp Add_day(int val) {return CloneAndAdd(Calendar.DAY_OF_MONTH, val);}
public DateAdp Add_month(int val) {return CloneAndAdd(Calendar.MONTH, val);}
public DateAdp Add_year(int val) {return CloneAndAdd(Calendar.YEAR, val);}
DateAdp CloneAndAdd(int field, int val) {
Calendar clone = (Calendar)under.clone();
clone.add(field, val);
return new DateAdp(clone);
}
public String XtoStr_fmt(String fmt) {
fmt = fmt.replace("f", "S");
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
return sdf.format(under.getTime());
}
public String XtoStr_tz() {
SimpleDateFormat sdf = new SimpleDateFormat("Z");
String time_zone = sdf.format(under.getTime());
return String_.Mid(time_zone, 0, 3) + ":" + String_.Mid(time_zone, 3, String_.Len(time_zone));
}
public boolean Eq(DateAdp v) {DateAdp comp = v; return Object_.Eq(under.getTimeInMillis(), comp.under.getTimeInMillis());}
public int Diff_days(DateAdp prev) {
long diff = this.under.getTimeInMillis() - prev.under.getTimeInMillis();
return (int)(diff / (1000 * 60 * 60 * 24));
}
public TimeSpanAdp Diff(DateAdp earlier) {
long diff = this.under.getTimeInMillis() - earlier.under.getTimeInMillis();
return TimeSpanAdp_.fracs_(diff);
}
protected DateAdp(Calendar under) {this.under = under;}
protected DateAdp(int year, int month, int day, int hour, int minute, int second, int frac) {
this.under = new GregorianCalendar(year, month - Month_base0adj, day, hour, minute, second);
under.set(Calendar.MILLISECOND, frac);
}
public static final int Month_base0adj = 1;
}

View File

@ -0,0 +1,113 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
public class DateAdp_ implements GfoInvkAble {
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_Now)) return Now();
else return GfoInvkAble_.Rv_unhandled;
} public static final String Invk_Now = "Now";
public static final DateAdp MinValue = new DateAdp( 1, 1, 1, 0, 0, 0, 0);
public static final DateAdp MaxValue = new DateAdp(9999, 12, 31, 23, 59, 59, 999);
public static DateAdp Now() {return Tfds.Now_enabled() ? Tfds.Now() : new DateAdp(new GregorianCalendar());}
public static DateAdp new_(int year, int month, int day, int hour, int minute, int second, int frac) {return new DateAdp(year, month, day, hour, minute, second, frac);}
public static DateAdp seg_(int[] ary) {
int ary_len = ary.length;
int y = ary_len > 0 ? ary[0] : 1;
int M = ary_len > 1 ? ary[1] : 1;
int d = ary_len > 2 ? ary[2] : 1;
int h = ary_len > 3 ? ary[3] : 0;
int m = ary_len > 4 ? ary[4] : 0;
int s = ary_len > 5 ? ary[5] : 0;
int f = ary_len > 6 ? ary[6] : 0;
return new DateAdp(y, M, d, h, m, s, f);
}
public static DateAdp cast_(Object arg) {try {return (DateAdp)arg;} catch(Exception exc) {throw Err_.type_mismatch_exc_(exc, DateAdp.class, arg);}}
public static DateAdp parse_iso8561(String raw) { // NOTE: for now, same as parse_gplx
int[] ary = date_parser.Parse_iso8651_like(raw);
if (ary[1] < 1 || ary[1] > 12) return DateAdp_.MinValue; // guard against invalid month
if (ary[2] < 1 || ary[2] > 31) return DateAdp_.MinValue;
return new DateAdp(ary[0], ary[1], ary[2], ary[3], ary[4], ary[5], ary[6]);
}
public static DateAdp parse_gplx(String raw) {
int[] ary = date_parser.Parse_iso8651_like(raw);
if (ary[1] < 1 || ary[1] > 12) return DateAdp_.MinValue; // guard against invalid month
if (ary[2] < 1 || ary[2] > 31) return DateAdp_.MinValue;
return new DateAdp(ary[0], ary[1], ary[2], ary[3], ary[4], ary[5], ary[6]);
} static DateAdp_parser date_parser = DateAdp_parser.new_();
public static DateAdp dateTime_(GregorianCalendar v) {return new DateAdp(v);}
public static DateAdp dateTime_obj_(Object v) {return new DateAdp((GregorianCalendar)v);}
public static final DateAdp_ Gfs = new DateAdp_();
public static int DaysInMonth(DateAdp date) {
int rv = DaysInMonth_ary[date.Month() - Int_.Base1];
if (rv == 28 && IsLeapYear(date.Year())) rv = 29;
return rv;
} static int [] DaysInMonth_ary = {31,28,31,30,31,30,31,31,30,31,30,31};
public static boolean IsLeapYear(int year) {
if (year % 4 != 0) return false;
else if (year % 400 == 0) return true;
else if (year % 100 == 0) return false;
else return true;
}
public static DateAdp unixtime_utc_seconds_(long v) {return unixtime_utc_ms_(v * 1000);}
public static DateAdp db_(Object v) {
Timestamp ts = (Timestamp)v;
Calendar gc = Calendar.getInstance();
gc.setTimeInMillis(ts.getTime());
return new DateAdp(gc);
}
public static DateAdp parse_(String raw) {
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = null;
try {d = sdf.parse(raw);}
catch (ParseException e) {throw Err_.new_key_("parse", "failed to parse to DateAdp").Add("raw", raw);}
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
cal.setTime(d);
return dateTime_(cal);
}
public static DateAdp parse_fmt(String raw, String fmt) {
fmt = fmt.replace('t', 'a'); // AM/PM
fmt = fmt.replace('f', 'S'); // milliseconds
SimpleDateFormat sdf = new SimpleDateFormat(fmt, Locale.US);
Date d = null;
try {d = sdf.parse(raw);}
catch (ParseException e) {throw Err_.new_key_("parse", "failed to parse to DateAdp").Add("raw", raw).Add("fmt", fmt);}
GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
cal.setTime(d);
return dateTime_(cal);
}
public static DateAdp unixtime_utc_ms_(long v) {return unixtime_lcl_ms_(v).XtoUtc();}
public static DateAdp unixtime_lcl_ms_(long v) {
GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(v);
return new DateAdp(c);
}
public static final int SegIdx_year = 0, SegIdx_month = 1, SegIdx_day = 2, SegIdx_hour = 3, SegIdx_minute = 4, SegIdx_second = 5, SegIdx_frac = 6, SegIdx_dayOfWeek = 7, SegIdx_weekOfYear = 8, SegIdx_dayOfYear = 9, SegIdx__max = 10;
public static final String Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss";
public static String Xto_str_fmt_or(DateAdp v, String fmt, String or) {
return v == null ? or : v.XtoStr_fmt(fmt);
}
}

View File

@ -0,0 +1,68 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import org.junit.*;
public class DateAdp__tst {
@Test public void Parse_gplx() {
tst_Parse_gplx("99991231_235959.999", "99991231_235959.999");
tst_Parse_gplx("20090430_213200.123", "20090430_213200.123");
tst_Parse_gplx("20090430_213200" , "20090430_213200.000");
tst_Parse_gplx("20090430" , "20090430_000000.000");
}
@Test public void Parse_separators() {
tst_Parse_gplx("2009-04-30 21:32:00.123", "20090430_213200.123");
tst_Parse_gplx("2009-04-30 21:32:00" , "20090430_213200.000");
tst_Parse_gplx("2009-04-30" , "20090430_000000.000");
}
@Test public void DayOfWeek() {
tst_DayOfWeek("2012-01-18", 3); //3=Wed
} void tst_DayOfWeek(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).DayOfWeek());}
@Test public void WeekOfYear() {
tst_WeekOfYear("2006-02-01", 5); // 1-1:Sun;2-1:Wed
tst_WeekOfYear("2007-02-01", 5); // 1-1:Mon;2-1:Thu
tst_WeekOfYear("2008-02-01", 5); // 1-1:Tue;2-1:Fri
tst_WeekOfYear("2009-02-01", 6); // 1-1:Thu;2-1:Sun
tst_WeekOfYear("2010-02-01", 6); // 1-1:Fri;2-1:Mon
tst_WeekOfYear("2011-02-01", 6); // 1-1:Sat;2-1:Tue
} void tst_WeekOfYear(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).WeekOfYear());}
@Test public void DayOfYear() {
tst_DayOfYear("2012-01-01", 1);
tst_DayOfYear("2012-02-29", 60);
tst_DayOfYear("2012-12-31", 366);
} void tst_DayOfYear(String raw, int expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).DayOfYear());}
@Test public void Timestamp_unix() {
tst_Timestamp_unix("1970-01-01 00:00:00", 0);
tst_Timestamp_unix("2012-01-01 00:00:00", 1325376000);
} void tst_Timestamp_unix(String raw, long expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).Timestamp_unix());}
@Test public void DaysInMonth() {
tst_DaysInMonth("2012-01-01", 31);
tst_DaysInMonth("2012-02-01", 29);
tst_DaysInMonth("2012-04-01", 30);
tst_DaysInMonth("2011-02-01", 28);
} void tst_DaysInMonth(String raw, int expd) {Tfds.Eq(expd, DateAdp_.DaysInMonth(DateAdp_.parse_gplx(raw)));}
@Test public void XtoUtc() {
tst_XtoUtc("2012-01-01 00:00", "2012-01-01 05:00"); //4=Wed
} void tst_XtoUtc(String raw, String expd) {Tfds.Eq(expd, DateAdp_.parse_gplx(raw).XtoUtc().XtoStr_fmt_yyyy_MM_dd_HH_mm());}
void tst_Parse_gplx(String raw, String expd) {
DateAdp date = DateAdp_.parse_gplx(raw);
String actl = date.XtoStr_gplx();
Tfds.Eq(expd, actl);
}
DateAdp_parser bldr = DateAdp_parser.new_();
}

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