You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/100_core/src/gplx/Bry_.java

1049 lines
40 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx;
import java.lang.*;
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.ios.*;
public class Bry_ {
public static final String Cls_val_name = "byte[]";
public static final byte[] Empty = new byte[0];
public static final byte[][] Ary_empty = new byte[0][];
public static final Class<?> Cls_ref_type = byte[].class;
public static byte[] cast(Object val) {return (byte[])val;}
public static byte[] New_by_byte(byte b) {return new byte[] {b};}
public static byte[] New_by_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_by_objs(Bry_bfr bfr, Object... ary) {
int len = ary.length;
for (int i = 0; i < len; ++i) {
Object itm = ary[i];
Class<?> type = Type_adp_.ClassOf_obj(itm);
if (Type_adp_.Eq(type, int.class)) bfr.Add_byte((byte)Int_.cast(itm));
else if (Type_adp_.Eq(type, String.class)) bfr.Add_str_u8((String)itm);
else if (Type_adp_.Eq(type, byte[].class)) bfr.Add((byte[])itm);
else throw Err_.new_unhandled(Type_adp_.FullNameOf_type(type));
}
return bfr.To_bry_and_clear();
}
public static byte[] Coalesce_to_empty(byte[] v) {return v == null ? Bry_.Empty : v;}
public static byte[] Coalesce(byte[] v, byte[] or) {return v == null ? or : v;}
public static byte[] new_a7(String str) {
if (str == null) return null;
int str_len = str.length();
if (str_len == 0) return Bry_.Empty;
byte[] rv = new byte[str_len];
for (int i = 0; i < str_len; ++i) {
char c = str.charAt(i);
if (c > 128) c = '?';
rv[i] = (byte)c;
}
return rv;
}
public static byte[] new_u8_safe(String str) {return str == null ? null : new_u8(str);}
public static byte[] new_u8(String str) {
try {
int str_len = str.length();
int bry_len = new_u8__by_len(str, str_len);
byte[] rv = new byte[bry_len];
new_u8__write(str, str_len, rv, 0);
return rv;
}
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
}
public static int new_u8__by_len(String s, int s_len) {
int rv = 0;
for (int i = 0; i < s_len; ++i) {
char c = s.charAt(i);
int c_len = 0;
if ( c < 128) c_len = 1; // 1 << 7
else if ( c < 2048) c_len = 2; // 1 << 11
else if ( (c > 55295) // 0xD800
&& (c < 56320)) c_len = 4; // 0xDFFF
else c_len = 3; // 1 << 16
if (c_len == 4) ++i; // surrogate is 2 wide, not 1
rv += c_len;
}
return rv;
}
public static byte[] New_u8_nl_apos(String... lines) {
Bry_bfr bfr = Bry_bfr_.Get();
try {
New_u8_nl_apos(bfr, lines);
return bfr.To_bry_and_clear();
}
finally {bfr.Mkr_rls();}
}
public static void New_u8_nl_apos(Bry_bfr bfr, String... lines) {
int lines_len = lines.length;
for (int i = 0; i < lines_len; ++i) {
if (i != 0) bfr.Add_byte_nl();
byte[] line = Bry_.new_u8(lines[i]);
boolean dirty = false;
int prv = 0;
int line_len = line.length;
for (int j = 0; j < line_len; ++j) {
byte b = line[j];
if (b == Byte_ascii.Apos) {
bfr.Add_mid(line, prv, j);
bfr.Add_byte(Byte_ascii.Quote);
dirty = true;
prv = j + 1;
}
}
if (dirty)
bfr.Add_mid(line, prv, line_len);
else
bfr.Add(line);
}
}
public static void new_u8__write(String str, int str_len, byte[] bry, int bry_pos) {
for (int i = 0; i < str_len; ++i) {
char c = str.charAt(i);
if ( c < 128) {
bry[bry_pos++] = (byte)c;
}
else if ( c < 2048) {
bry[bry_pos++] = (byte)(0xC0 | (c >> 6));
bry[bry_pos++] = (byte)(0x80 | (c & 0x3F));
}
else if ( (c > 55295) // 0xD800
&& (c < 56320)) { // 0xDFFF
if (i >= str_len) throw Err_.new_wo_type("incomplete surrogate pair at end of String", "char", c);
char nxt_char = str.charAt(i + 1);
int v = 0x10000 + (c - 0xD800) * 0x400 + (nxt_char - 0xDC00);
bry[bry_pos++] = (byte)(0xF0 | (v >> 18));
bry[bry_pos++] = (byte)(0x80 | (v >> 12) & 0x3F);
bry[bry_pos++] = (byte)(0x80 | (v >> 6) & 0x3F);
bry[bry_pos++] = (byte)(0x80 | (v & 0x3F));
++i;
}
else {
bry[bry_pos++] = (byte)(0xE0 | (c >> 12));
bry[bry_pos++] = (byte)(0x80 | (c >> 6) & 0x3F);
bry[bry_pos++] = (byte)(0x80 | (c & 0x3F));
}
}
}
public static byte[] Copy(byte[] src) {
int src_len = src.length;
byte[] trg = new byte[src_len];
for (int i = 0; i < src_len; ++i)
trg[i] = src[i];
return trg;
}
public static byte[] Resize(byte[] src, int trg_len) {return Resize(src, 0, trg_len);}
public static byte[] Resize(byte[] src, int src_bgn, int trg_len) {
byte[] trg = new byte[trg_len];
int src_len = src.length; if (src_len > trg_len) src_len = trg_len; // trg_len can be less than src_len
Copy_by_len(src, src_bgn, src_len, trg, 0);
return trg;
}
public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);}
public static byte[] Repeat(byte b, int len) {
byte[] rv = new byte[len];
for (int i = 0; i < len; i++)
rv[i] = b;
return rv;
}
public static byte[] Add(byte[] src, byte b) {
int src_len = src.length;
byte[] rv = new byte[src_len + 1];
Copy_by_pos(src, 0, src_len, rv, 0);
rv[src_len] = b;
return rv;
}
public static byte[] Add(byte b, byte[] src) {
int src_len = src.length;
byte[] rv = new byte[src_len + 1];
Copy_by_pos(src, 0, src_len, rv, 1);
rv[0] = b;
return rv;
}
public static byte[] Add(byte[]... all) {
int all_len = all.length, rv_len = 0;
for (int i = 0; i < all_len; ++i) {
byte[] cur = all[i]; if (cur == null) continue;
rv_len += cur.length;
}
byte[] rv = new byte[rv_len];
int rv_idx = 0;
for (int i = 0; i < all_len; ++i) {
byte[] cur = all[i]; if (cur == null) continue;
int cur_len = cur.length;
for (int j = 0; j < cur_len; ++j)
rv[rv_idx++] = cur[j];
}
return rv;
}
public static byte[] Add_w_dlm(byte[] dlm, byte[]... ary) {
int ary_len = ary.length;
if (ary_len == 0) return Bry_.Empty;
int dlm_len = dlm.length;
int rv_len = dlm_len * (ary_len - 1); // rv will have at least as many dlms as itms - 1
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (itm != null) rv_len += itm.length;
}
int rv_pos = 0;
byte[] rv = new byte[rv_len];
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (i != 0) {
for (int j = 0; j < dlm_len; j++) {
rv[rv_pos++] = dlm[j];
}
}
if (itm == null) continue;
int itm_len = itm.length;
for (int j = 0; j < itm_len; j++) {
rv[rv_pos++] = itm[j];
}
}
return rv;
}
public static byte[] Add_w_dlm(byte dlm, byte[]... ary) {
int ary_len = ary.length;
if (ary_len == 0) return Bry_.Empty;
int rv_len = ary_len - 1; // rv will have at least as many dlms as itms - 1
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (itm != null) rv_len += itm.length;
}
int rv_pos = 0;
byte[] rv = new byte[rv_len];
for (int i = 0; i < ary_len; i++) {
byte[] itm = ary[i];
if (i != 0) rv[rv_pos++] = dlm;
if (itm == null) continue;
int itm_len = itm.length;
for (int j = 0; j < itm_len; j++) {
rv[rv_pos++] = itm[j];
}
}
return rv;
}
public static int Len(byte[] v) {return v == null ? 0 : v.length;}
public static boolean Len_gt_0(byte[] v) {return v != null && v.length > 0;}
public static boolean Len_eq_0(byte[] v) {return v == null || v.length == 0;}
public static byte Get_at_end(byte[] bry) {return bry[bry.length - 1];} // don't bother checking for errors; depend on error trace
public static boolean Has_at(byte[] src, int src_len, int pos, byte b) {return (pos < src_len) && (src[pos] == b);}
public static boolean Has(byte[] src, byte[] lkp) {return Bry_find_.Find_fwd(src, lkp) != Bry_find_.Not_found;}
public static boolean Has(byte[] src, byte lkp) {
if (src == null) return false;
int len = src.length;
for (int i = 0; i < len; i++)
if (src[i] == lkp) return true;
return false;
}
public static boolean Has_at_bgn(byte[] src, byte lkp) {return Has_at_bgn(src, lkp, 0);}
public static boolean Has_at_bgn(byte[] src, byte lkp, int src_bgn) {return src_bgn < src.length ? src[src_bgn] == lkp : false;}
public static boolean Has_at_bgn(byte[] src, byte[] lkp) {return Has_at_bgn(src, lkp, 0, src.length);}
public static boolean Has_at_bgn(byte[] src, byte[] lkp, int src_bgn, int src_end) {
int lkp_len = lkp.length;
if (lkp_len + src_bgn > src_end) return false; // lkp is longer than src
for (int i = 0; i < lkp_len; i++) {
if (lkp[i] != src[i + src_bgn]) return false;
}
return true;
}
public static boolean Has_at_end(byte[] src, byte[] lkp) {int src_len = src.length; return Has_at_end(src, lkp, src_len - lkp.length, src_len);}
public static boolean Has_at_end(byte[] src, byte[] lkp, int src_bgn, int src_end) {
int lkp_len = lkp.length;
if (src_bgn < 0) return false;
int pos = src_end - lkp_len; if (pos < src_bgn) return false; // lkp is longer than src
for (int i = 0; i < lkp_len; i++) {
if (lkp[i] != src[i + pos]) return false;
}
return true;
}
public static void Set(byte[] src, int bgn, int end, byte[] repl) {
int repl_len = repl.length;
for (int i = 0; i < repl_len; i++)
src[i + bgn] = repl[i];
}
public static void Copy_by_pos(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
int trg_adj = trg_bgn - src_bgn;
for (int i = src_bgn; i < src_end; i++)
trg[i + trg_adj] = src[i];
}
private static void Copy_by_len(byte[] src, int src_bgn, int src_len, byte[] trg, int trg_bgn) {
for (int i = 0; i < src_len; i++)
trg[i + trg_bgn] = src[i + src_bgn];
}
public static byte[] Replace_one(byte[] src, byte[] find, byte[] repl) {
int src_len = src.length;
int findPos = Bry_find_.Find(src, find, 0, src_len, true); if (findPos == Bry_find_.Not_found) return src;
int findLen = find.length, replLen = repl.length;
int rvLen = src_len + replLen - findLen;
byte[] rv = new byte[rvLen];
Copy_by_len(src , 0 , findPos , rv, 0 );
Copy_by_len(repl, 0 , replLen , rv, findPos );
Copy_by_len(src , findPos + findLen , src_len - findPos - findLen , rv, findPos + replLen);
return rv;
}
public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);}
public static void Replace_all_direct(byte[] src, byte find, byte repl, int bgn, int end) {
for (int i = bgn; i < end; i++) {
byte b = src[i];
if (b == find) src[i] = repl;
}
}
public static byte[] Limit(byte[] src, int len) {
if (src == null) return null;
int src_len = src.length;
return len < src_len ? Bry_.Mid(src, 0, len) : src;
}
public static byte[] Mid_by_nearby(byte[] src, int pos, int around) {
int bgn = pos - around; if (bgn < 0) bgn = 0;
int src_len = src.length;
int end = pos + around; if (end > src_len) end = src_len;
return Mid(src, bgn, end);
}
public static byte[] Mid_by_len(byte[] src, int bgn, int len) {return Mid(src, bgn, bgn + len);}
public static byte[] Mid_by_len_safe(byte[] src, int bgn, int len) {
int src_len = src.length;
if (bgn < 0) bgn = 0;
if (len + bgn > src_len) len = (src_len - bgn);
return Mid(src, bgn, bgn + len);
}
public static String MidByLenToStr(byte[] src, int bgn, int len) {
int end = bgn + len; end = Int_.BoundEnd(end, src.length);
byte[] ary = Bry_.Mid(src, bgn, end);
return String_.new_u8(ary);
}
public static byte[] Mid_safe(byte[] src, int bgn, int end) {
if (src == null) return null;
int src_len = src.length;
if (bgn < 0) bgn = 0;
if (end >= src_len) end = src_len;
if (bgn > end) bgn = end;
else if (end < bgn) end = bgn;
return Mid(src, bgn, end);
}
public static byte[] Mid(byte[] src, int bgn) {return Mid(src, bgn, src.length);}
public static byte[] Mid_or(byte[] src, int bgn, int end, byte[] or) {
int src_len = src.length;
if ( src == null
|| (bgn < 0 || bgn > src_len)
|| (end < 0 || end > src_len)
|| (end < bgn)
)
return or;
return Mid(src, bgn, src.length);
}
public static byte[] Mid(byte[] src, int bgn, int end) {
try {
int len = end - bgn; if (len == 0) return Bry_.Empty;
byte[] rv = new byte[len];
for (int i = bgn; i < end; i++)
rv[i - bgn] = src[i];
return rv;
} catch (Exception e) {Err_.Noop(e); throw Err_.new_("Bry_", "mid failed", "bgn", bgn, "end", end);}
}
public static byte[] Mid_w_trim(byte[] src, int bgn, int end) {
int len = end - bgn; if (len == 0) return Bry_.Empty;
int actl_bgn = bgn, actl_end = end;
// trim at bgn
boolean chars_seen = false;
for (int i = bgn; i < end; ++i) {
switch (src[i]) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
break;
default:
chars_seen = true;
actl_bgn = i;
i = end;
break;
}
}
if (!chars_seen) return Bry_.Empty; // all ws
// trim at end
for (int i = end - 1; i >= actl_bgn; --i) {
switch (src[i]) {
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
break;
default:
actl_end = i + 1;
i = -1;
break;
}
}
// extract mid
len = actl_end - actl_bgn; if (len == 0) return Bry_.Empty;
byte[] rv = new byte[len];
for (int i = actl_bgn; i < actl_end; ++i)
rv[i - actl_bgn] = src[i];
return rv;
}
public static byte[] mask_(int len, byte... itms) {
byte[] rv = new byte[len];
int itms_len = itms.length;
for (int i = 0; i < itms_len; i++) {
byte itm = itms[i];
rv[itm & 0xFF] = itm; // PATCH.JAVA:need to convert to unsigned byte
}
return rv;
}
public static final byte[] Trim_ary_ws = mask_(256, Byte_ascii.Tab, Byte_ascii.Nl, Byte_ascii.Cr, Byte_ascii.Space);
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
int txt_bgn = bgn, txt_end = end;
boolean all_ws = true;
if (trim_bgn) {
for (int i = bgn; i < end; i++) {
byte b = src[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
txt_bgn = i;
i = end;
all_ws = false;
}
}
if (all_ws) return Bry_.Empty;
}
if (trim_end) {
for (int i = end - 1; i > -1; i--) {
byte b = src[i];
if (trim_ary[b & 0xFF] == Byte_ascii.Null) {
txt_end = i + 1;
i = -1;
all_ws = false;
}
}
if (all_ws) return Bry_.Empty;
}
return Bry_.Mid(src, txt_bgn, txt_end);
}
public static byte[] Trim_end(byte[] v, byte trim, int end) {
boolean trimmed = false;
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len
for (; pos > -1; pos--) {
if (v[pos] == trim) {
trimmed = true;
}
else
break;
}
return trimmed ? Bry_.Mid(v, 0, pos + 1) : v;
}
public static int Compare(byte[] lhs, byte[] rhs) {
if (lhs == null) return CompareAble_.More;
else if (rhs == null) return CompareAble_.Less;
else return Compare(lhs, 0, lhs.length, rhs, 0, rhs.length);
}
public static int Compare(byte[] lhs, int lhs_bgn, int lhs_end, byte[] rhs, int rhs_bgn, int rhs_end) {
int lhs_len = lhs_end - lhs_bgn, rhs_len = rhs_end - rhs_bgn;
int min = lhs_len < rhs_len ? lhs_len : rhs_len;
int rv = CompareAble_.Same;
for (int i = 0; i < min; i++) {
rv = (lhs[i + lhs_bgn] & 0xff) - (rhs[i + rhs_bgn] & 0xff); // PATCH.JAVA:need to convert to unsigned byte
if (rv != CompareAble_.Same) return rv > CompareAble_.Same ? CompareAble_.More : CompareAble_.Less; // NOTE: changed from if (rv != CompareAble_.Same) return rv; DATE:2013-04-25
}
return Int_.Compare(lhs_len, rhs_len); // lhs and rhs share same beginning bytes; return len comparisons
}
public static boolean Eq(byte[] src, byte[] val) {return Eq(src, 0, src == null ? 0 : src.length, val);}
public static boolean Eq(byte[] src, int src_bgn, int src_end, byte[] val) {
if (src == null && val == null) return true;
else if (src == null || val == null) return false;
if (src_bgn < 0) return false;
int val_len = val.length;
if (val_len != src_end - src_bgn) return false;
int src_len = src.length;
for (int i = 0; i < val_len; i++) {
int src_pos = i + src_bgn;
if (src_pos == src_len) return false;
if (val[i] != src[src_pos]) return false;
}
return true;
}
public static boolean Eq_ci_a7(byte[] lhs, byte[] rhs, int rhs_bgn, int rhs_end) {
if (lhs == null && rhs == null) return true;
else if (lhs == null || rhs == null) return false;
int lhs_len = lhs.length;
int rhs_len = rhs_end - rhs_bgn;
if (lhs_len != rhs_len) return false;
for (int i = 0; i < lhs_len; i++) {
byte lhs_b = lhs[i]; if (lhs_b > 64 && lhs_b < 91) lhs_b += 32; // lowercase
byte rhs_b = rhs[i + rhs_bgn]; if (rhs_b > 64 && rhs_b < 91) rhs_b += 32; // lowercase
if (lhs_b != rhs_b) return false;
}
return true;
}
public static boolean Match(byte[] src, byte[] find) {return Match(src, 0, src.length, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, byte[] find) {return Match(src, src_bgn, src.length, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find) {return Match(src, src_bgn, src_end, find, 0, find.length);}
public static boolean Match(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end) {
if (src_bgn == -1) return false;
int src_len = src.length;
if (src_end > src_len) src_end = src_len; // must limit src_end to src_len, else ArrayIndexOutOfBounds below; DATE:2015-01-31
int find_len = find_end - find_bgn;
if (find_len != src_end - src_bgn) return false;
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
for (int i = 0; i < find_len; i++) {
int pos = src_bgn + i;
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
if (src[pos] != find[i + find_bgn]) return false;
}
return true;
}
public static boolean Match_w_swap(byte[] src, int src_bgn, int src_end, byte[] find, int find_bgn, int find_end, byte swap_src, byte swap_trg) {// same as above, but used by XOWA for ttl matches;
int src_len = src.length;
if (src_end > src_len) src_end = src_len; // must limit src_end to src_len, else ArrayIndexOutOfBounds below; DATE:2015-01-31
int find_len = find_end - find_bgn;
if (find_len != src_end - src_bgn) return false;
if (find_len == 0) return src_end - src_bgn == 0; // "" only matches ""
for (int i = 0; i < find_len; i++) {
int pos = src_bgn + i;
if (pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc
byte src_byte = src[pos]; if (src_byte == swap_src) src_byte = swap_trg;
byte trg_byte = find[i + find_bgn]; if (trg_byte == swap_src) trg_byte = swap_trg;
if (src_byte != trg_byte) return false;
}
return true;
}
public static boolean Match_bwd_any(byte[] src, int src_end, int src_bgn, byte[] find) { // NOTE: utf8 doesn't matter (matching byte for byte)
int find_len = find.length;
for (int i = 0; i < find_len; i++) {
int src_pos = src_end - i;
int find_pos = find_len - i - 1;
if (src_pos < src_bgn) return false; // ran out of src; exit; EX: src=ab; find=abc
if (src[src_pos] != find[find_pos]) return false;
}
return true;
}
public static int To_int_by_a7(byte[] v) {
int v_len = v.length;
int mod = 8 * (v_len - 1);
int rv = 0;
for (int i = 0; i < v_len; i++) {
rv |= v[i] << mod;
mod -= 8;
}
return rv;
// return ((0xFF & v[0]) << 24)
// | ((0xFF & v[1]) << 16)
// | ((0xFF & v[2]) << 8)
// | (0xFF & v[3]);
}
public static byte[] To_a7_bry(int val, int pad_len) {return To_a7_bry(val, null, 0, pad_len);}
public static byte[] To_a7_bry(int val, byte[] ary, int aryPos, int pad_len) {
int neg = 0;
if (val < 0) {
val *= -1;
neg = 1;
}
int digits = val == 0 ? 0 : Math_.Log10(val);
digits += 1; // digits = log + 1; EX: Log(1-9) = 0, Log(10-99) = 1
int ary_len = digits + neg, aryBgn = aryPos, pad = 0;
if (ary_len < pad_len) { // padding specified
pad = pad_len - ary_len;
ary_len = pad_len;
}
if (ary == null) ary = new byte[ary_len];
long factor = 1; // factor needs to be long to handle 1 billion (for which factor would be 10 billion)
for (int i = 0; i < digits; i++) // calc maxFactor
factor *= 10;
if (neg == 1) ary[0] = Byte_NegSign;
for (int i = 0; i < pad; i++) // fill ary with pad
ary[i + aryBgn] = Byte_ascii.To_a7_str(0);
aryBgn += pad; // advance aryBgn by pad
for (int i = neg; i < ary_len - pad; i++) {
int denominator = (int)(factor / 10); // cache denominator to check for divide by 0
int digit = denominator == 0 ? 0 : (int)((val % factor) / denominator);
ary[aryBgn + i] = Byte_ascii.To_a7_str(digit);
factor /= 10;
}
return ary;
}
public static byte[] new_by_int(int v) {
byte b0 = (byte)(v >> 24);
byte b1 = (byte)(v >> 16);
byte b2 = (byte)(v >> 8);
byte b3 = (byte)(v);
if (b0 != 0) return new byte[] {b0, b1, b2, b3};
else if (b1 != 0) return new byte[] {b1, b2, b3};
else if (b2 != 0) return new byte[] {b2, b3};
else return new byte[] {b3};
}
public static boolean To_bool_by_int(byte[] ary) {
int rv = To_int_or(ary, 0, ary.length, Int_.Min_value, Bool_.Y, null);
switch (rv) {
case 0: return false;
case 1: return true;
default: throw Err_.new_wo_type("could not parse to boolean int", "val", String_.new_u8(ary));
}
}
public static byte To_int_as_byte(byte[] ary, int bgn, int end, byte or) {return (byte)To_int_or(ary, bgn, end, or);}
public static int To_int(byte[] ary) {
int rv = To_int_or(ary, 0, ary.length, Int_.Min_value, Bool_.Y, null);
if (rv == Int_.Min_value) throw Err_.new_wo_type("could not parse to int", "val", String_.new_u8(ary));
return rv;
}
public static int To_int_or_neg1(byte[] ary) {return To_int_or(ary, 0 , ary.length, -1, Bool_.Y, null);}
public static int To_int_or(byte[] ary, int or) {return To_int_or(ary, 0 , ary.length, or, Bool_.Y, null);}
public static int To_int_or(byte[] ary, int bgn, int end, int or) {return To_int_or(ary, bgn , end , or, Bool_.Y, null);}
public static int To_int_or__strict(byte[] ary, int or) {return To_int_or(ary, 0 , ary.length, or, Bool_.N, null);}
private static int To_int_or(byte[] ary, int bgn, int end, int or, boolean sign_is_valid, byte[] ignore_ary) {
if ( ary == null
|| end == bgn // null-len
) return or;
int rv = 0, multiple = 1;
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
rv += multiple * (b - Byte_ascii.Num_0);
multiple *= 10;
break;
case Byte_ascii.Dash:
return i == bgn && sign_is_valid ? rv * -1 : or;
case Byte_ascii.Plus:
return i == bgn && sign_is_valid ? rv : or;
default:
boolean invalid = true;
if (ignore_ary != null) {
int ignore_ary_len = ignore_ary.length;
for (int j = 0; j < ignore_ary_len; j++) {
if (b == ignore_ary[j]) {
invalid = false;
break;
}
}
}
if (invalid) return or;
break;
}
}
return rv;
}
public static int To_int_or__trim_ws(byte[] ary, int bgn, int end, int or) { // NOTE: same as To_int_or, except trims ws at bgn / end; DATE:2014-02-09
if (end == bgn) return or; // null len
int rv = 0, multiple = 1;
boolean numbers_seen = false, ws_seen = false;
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
rv += multiple * (b - Byte_ascii.Num_0);
multiple *= 10;
if (ws_seen) // "number ws number" pattern; invalid ws in middle; see tests
return or;
numbers_seen = true;
break;
case Byte_ascii.Dash:
return i == bgn ? rv * -1 : or;
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr:
if (numbers_seen)
ws_seen = true;
break;
default: return or;
}
}
return rv;
}
public static int To_int_or__lax(byte[] ary, int bgn, int end, int or) {
if (end == bgn) return or; // null-len
int end_num = end;
for (int i = bgn; i < end; i++) {
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
break;
case Byte_ascii.Dash:
if (i != bgn) {
end_num = i;
i = end;
}
break;
default:
end_num = i;
i = end;
break;
}
}
return To_int_or(ary, bgn, end_num, or);
}
public static long To_long_or(byte[] ary, long or) {return To_long_or(ary, null, 0, ary.length, or);}
public static long To_long_or(byte[] ary, byte[] ignore_ary, int bgn, int end, long or) {
if ( ary == null
|| end == bgn // null-len
) return or;
long rv = 0, multiple = 1;
for (int i = end - 1; i >= bgn; i--) { // -1 b/c end will always be next char; EX: {{{1}}}; bgn = 3, end = 4
byte b = ary[i];
switch (b) {
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
rv += multiple * (b - Byte_ascii.Num_0);
multiple *= 10;
break;
case Byte_ascii.Dash:
return i == bgn ? rv * -1 : or;
case Byte_ascii.Plus:
return i == bgn ? rv : or;
default:
boolean invalid = true;
if (ignore_ary != null) {
int ignore_ary_len = ignore_ary.length;
for (int j = 0; j < ignore_ary_len; j++) {
if (b == ignore_ary[j]) {
invalid = false;
break;
}
}
}
if (invalid) return or;
break;
}
}
return rv;
}
public static double To_double(byte[] ary, int bgn, int end) {return Double_.parse(String_.new_u8(ary, bgn, end));}
public static double To_double_or(byte[] bry, double or) {return Double_.parse_or(String_.new_u8(bry, 0, bry.length), or);}
public static double To_double_or(byte[] ary, int bgn, int end, double or) {return Double_.parse_or(String_.new_u8(ary, bgn, end), or);}
public static Decimal_adp To_decimal(byte[] ary, int bgn, int end) {return Decimal_adp_.parse(String_.new_u8(ary, bgn, end));}
public static byte[][] Ary_add(byte[][] lhs, byte[][] rhs) {
int lhs_len = lhs.length, rhs_len = rhs.length;
if (lhs_len == 0) return rhs;
else if (rhs_len == 0) return lhs;
else {
byte[][] rv = new byte[lhs_len + rhs_len][];
for (int i = 0; i < lhs_len; i++)
rv[i] = lhs[i];
for (int i = 0; i < rhs_len; i++)
rv[i + lhs_len] = rhs[i];
return rv;
}
}
public static byte[][] Ary(byte[]... ary) {return ary;}
public static byte[][] Ary(String... ary) {
int ary_len = ary.length;
byte[][] rv = new byte[ary_len][];
for (int i = 0; i < ary_len; i++) {
String itm = ary[i];
rv[i] = itm == null ? null : Bry_.new_u8(itm);
}
return rv;
}
public static byte[][] Ary_obj(Object... ary) {
if (ary == null) return Bry_.Ary_empty;
int ary_len = ary.length;
byte[][] rv = new byte[ary_len][];
for (int i = 0; i < ary_len; i++) {
Object itm = ary[i];
rv[i] = itm == null ? null : Bry_.new_u8(Object_.Xto_str_strict_or_empty(itm));
}
return rv;
}
public static boolean Ary_eq(byte[][] lhs, byte[][] rhs) {
int lhs_len = lhs.length;
int rhs_len = rhs.length;
if (lhs_len != rhs_len) return false;
for (int i = 0; i < lhs_len; ++i)
if (!Bry_.Eq(lhs[i], rhs[i])) return false;
return true;
}
public static final byte Dlm_fld = (byte)'|', Dlm_row = (byte)'\n', Dlm_quote = (byte)'"', Dlm_null = 0, Ascii_zero = 48;
public static final String Fmt_csvDte = "yyyyMMdd HHmmss.fff";
public static DateAdp ReadCsvDte(byte[] ary, Int_obj_ref posRef, byte lkp) {// ASSUME: fmt = yyyyMMdd HHmmss.fff
int y = 0, M = 0, d = 0, H = 0, m = 0, s = 0, f = 0;
int bgn = posRef.Val();
y += (ary[bgn + 0] - Ascii_zero) * 1000;
y += (ary[bgn + 1] - Ascii_zero) * 100;
y += (ary[bgn + 2] - Ascii_zero) * 10;
y += (ary[bgn + 3] - Ascii_zero);
M += (ary[bgn + 4] - Ascii_zero) * 10;
M += (ary[bgn + 5] - Ascii_zero);
d += (ary[bgn + 6] - Ascii_zero) * 10;
d += (ary[bgn + 7] - Ascii_zero);
H += (ary[bgn + 9] - Ascii_zero) * 10;
H += (ary[bgn + 10] - Ascii_zero);
m += (ary[bgn + 11] - Ascii_zero) * 10;
m += (ary[bgn + 12] - Ascii_zero);
s += (ary[bgn + 13] - Ascii_zero) * 10;
s += (ary[bgn + 14] - Ascii_zero);
f += (ary[bgn + 16] - Ascii_zero) * 100;
f += (ary[bgn + 17] - Ascii_zero) * 10;
f += (ary[bgn + 18] - Ascii_zero);
if (ary[bgn + 19] != lkp) throw Err_.new_wo_type("csv date is invalid", "txt", String_.new_u8__by_len(ary, bgn, 20));
posRef.Val_add(19 + 1); // +1=lkp.len
return DateAdp_.new_(y, M, d, H, m, s, f);
}
public static String ReadCsvStr(byte[] ary, Int_obj_ref posRef, byte lkp) {return String_.new_u8(ReadCsvBry(ary, posRef, lkp, true));}
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp) {return ReadCsvBry(ary, posRef, lkp, true);}
public static byte[] ReadCsvBry(byte[] ary, Int_obj_ref posRef, byte lkp, boolean make) {
int bgn = posRef.Val(), aryLen = ary.length;
Bry_bfr bb = null;
if (aryLen > 0 && ary[0] == Dlm_quote) {
int pos = bgn + 1; // +1 to skip quote
if (make) bb = Bry_bfr.new_(16);
while (true) {
if (pos == aryLen) throw Err_.new_wo_type("endOfAry reached, but no quote found", "txt", String_.new_u8__by_len(ary, bgn, pos));
byte b = ary[pos];
if (b == Dlm_quote) {
if (pos == aryLen - 1) throw Err_.new_wo_type("endOfAry reached, quote found but lkp not", "txt", String_.new_u8__by_len(ary, bgn, pos));
byte next = ary[pos + 1];
if (next == Dlm_quote) { // byte followed by quote
if (make) bb.Add_byte(b);
pos += 2;
}
else if (next == lkp) {
posRef.Val_(pos + 2); // 1=endQuote;1=lkp;
return make ? bb.To_bry() : Bry_.Empty;
}
else throw Err_.new_wo_type("quote found, but not doubled", "txt", String_.new_u8__by_len(ary, bgn, pos + 1));
}
else {
if (make) bb.Add_byte(b);
pos++;
}
}
}
else {
for (int i = bgn; i < aryLen; i++) {
if (ary[i] == lkp) {
posRef.Val_(i + 1); // +1 = lkp.Len
return make ? Bry_.Mid(ary, bgn, i) : Bry_.Empty;
}
}
throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "txt", String_.new_u8__by_len(ary, bgn, aryLen));
}
}
public static int ReadCsvInt(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
if (pos == Bry_find_.Not_found) throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "bgn", bgn);
int rv = Bry_.To_int_or(ary, posRef.Val(), pos, -1);
posRef.Val_(pos + 1); // +1 = lkp.Len
return rv;
}
public static double ReadCsvDouble(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
if (pos == Bry_find_.Not_found) throw Err_.new_wo_type("lkp failed", "lkp", (char)lkp, "bgn", bgn);
double rv = Bry_.To_double(ary, posRef.Val(), pos);
posRef.Val_(pos + 1); // +1 = lkp.Len
return rv;
}
public static void ReadCsvNext(byte[] ary, Int_obj_ref posRef, byte lkp) {
int bgn = posRef.Val();
int pos = Bry_find_.Find_fwd(ary, lkp, bgn, ary.length);
posRef.Val_(pos + 1); // +1 = lkp.Len
}
public static byte Byte_NegSign = (byte)'-';
public static byte[] Replace_create(byte[] src, byte find, byte replace) {
byte[] rv = Bry_.Copy(src);
Replace_reuse(rv, find, replace);
return rv;
}
public static void Replace_reuse(byte[] src, byte find, byte replace) {
int src_len = src.length;
for (int i = 0; i < src_len; i++) {
if (src[i] == find) src[i] = replace;
}
}
public static byte[] Replace(byte[] src, byte find, byte replace) {return Replace(src, 0, src.length, find, replace);}
public static byte[] Replace(byte[] src, int bgn, int end, byte find, byte replace) {
int src_len = src.length;
byte[] rv = new byte[src_len];
for (int i = bgn; i < end; ++i) {
byte b = src[i];
rv[i] = b == find ? replace : b;
}
for (int i = end; i < src_len; ++i)
rv[i] = src[i];
return rv;
}
public static byte[] Replace_safe(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {
if (src == null || find == null || repl == null) return null;
return Replace(bfr, src, find, repl, 0, src.length);
}
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl) {return Replace(bfr, src, find, repl, 0, src.length);}
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl, int src_bgn, int src_end) {return Replace(bfr, src, find, repl, src_bgn, src_end, Int_.Max_value);}
public static byte[] Replace(Bry_bfr bfr, byte[] src, byte[] find, byte[] repl, int src_bgn, int src_end, int limit) {
int pos = src_bgn;
boolean dirty = false;
int find_len = find.length;
int bfr_bgn = pos;
int replace_count = 0;
while (pos < src_end) {
int find_pos = Bry_find_.Find_fwd(src, find, pos);
if (find_pos == Bry_find_.Not_found) break;
dirty = true;
bfr.Add_mid(src, bfr_bgn, find_pos);
bfr.Add(repl);
pos = find_pos + find_len;
bfr_bgn = pos;
++replace_count;
if (replace_count == limit) break;
}
if (dirty)
bfr.Add_mid(src, bfr_bgn, src_end);
return dirty ? bfr.To_bry_and_clear() : src;
}
public static byte[] Replace(byte[] src, byte[] find, byte[] replace) {return Replace_between(src, find, null, replace);}
public static byte[] Replace_between(byte[] src, byte[] bgn, byte[] end, byte[] replace) {
Bry_bfr bfr = Bry_bfr.new_();
boolean replace_all = end == null;
int src_len = src.length, bgn_len = bgn.length, end_len = replace_all ? 0 : end.length;
int pos = 0;
while (true) {
if (pos >= src_len) break;
int bgn_pos = Bry_find_.Find_fwd(src, bgn, pos);
if (bgn_pos == Bry_find_.Not_found) {
bfr.Add_mid(src, pos, src_len);
break;
}
else {
int bgn_rhs = bgn_pos + bgn_len;
int end_pos = replace_all ? bgn_rhs : Bry_find_.Find_fwd(src, end, bgn_rhs);
if (end_pos == Bry_find_.Not_found) {
bfr.Add_mid(src, pos, src_len);
break;
}
else {
bfr.Add_mid(src, pos, bgn_pos);
bfr.Add(replace);
pos = end_pos + end_len;
}
}
}
return bfr.To_bry_and_clear();
}
public static int Trim_end_pos(byte[] src, int end) {
for (int i = end - 1; i > -1; i--) {
switch (src[i]) {
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: case Byte_ascii.Space:
break;
default:
return i + 1;
}
}
return 0;
}
public static byte[] Increment_last(byte[] ary) {return Increment_last(ary, ary.length - 1);}
public static byte[] Increment_last(byte[] ary, int end_idx) {
for (int i = end_idx; i > -1; i--) {
byte end_val_old = ary[i];
byte end_val_new = (byte)(end_val_old + 1);
ary[i] = end_val_new;
if (end_val_new > (end_val_old & 0xff)) break; // PATCH.JAVA:need to convert to unsigned byte
}
return ary;
}
public static byte[] Ucase__all(byte[] src) {return Xcase__all(Bool_.Y, src, 0, -1);}
public static byte[] Lcase__all(byte[] src) {return Xcase__all(Bool_.N, src, 0, -1);}
public static byte[] Lcase__all(byte[] src, int bgn, int end) {return Xcase__all(Bool_.N, src, bgn, end);}
private static byte[] Xcase__all(boolean upper, byte[] src, int bgn, int end) {
if (src == null) return null;
int len = end == -1 ? src.length : end - bgn; if (len == 0) return src;
byte[] rv = new byte[len];
for (int i = 0; i < len; ++i) {
byte b = src[i + bgn];
if (upper) {
if (b > 96 && b < 123) b -= 32;
}
else {
if (b > 64 && b < 91) b += 32;
}
rv[i] = b;
}
return rv;
}
public static byte[] Ucase__1st(byte[] src) {return Xcase__1st(Bool_.Y, src);}
public static byte[] Lcase__1st(byte[] src) {return Xcase__1st(Bool_.N, src);}
private static byte[] Xcase__1st(boolean upper, byte[] src) {
if (src == null) return null;
int len = src.length; if (len == 0) return src;
byte[] rv = new byte[len];
byte b = src[0];
if (upper) {
if (b > 96 && b < 123) b -= 32;
}
else {
if (b > 64 && b < 91) b += 32;
}
rv[0] = b;
for (int i = 1; i < len; ++i) {
rv[i] = src[i];
}
return rv;
}
public static byte[] Null_if_empty(byte[] v) {return Len_eq_0(v) ? null : v;}
public static byte[] Escape_ws(byte[] bry) {Bry_bfr bfr = Bry_bfr_.Get(); byte[] rv = Escape_ws(bfr, bry); bfr.Mkr_rls(); return rv;}
public static byte[] Escape_ws(Bry_bfr bfr, byte[] src) {
boolean dirty = false;
int len = src.length;
for (int i = 0; i < len; ++i) {
byte b = src[i];
byte escape = Byte_.Zero;
switch (b) {
case Byte_ascii.Tab: escape = Byte_ascii.Ltr_t; break;
case Byte_ascii.Nl: escape = Byte_ascii.Ltr_n; break;
case Byte_ascii.Cr: escape = Byte_ascii.Ltr_r; break;
default: if (dirty) bfr.Add_byte(b); break;
}
if (escape != Byte_.Zero) {
if (!dirty) {
dirty = true;
bfr.Add_mid(src, 0, i);
}
bfr.Add_byte_backslash().Add_byte(escape);
}
}
return dirty ? bfr.To_bry_and_clear() : src;
}
public static byte[] Resolve_escape(Bry_bfr bfr, byte escape, byte[] raw, int bgn, int end) {
int pos = bgn;
boolean dirty = false;
while (pos < end) {
byte b = raw[pos];
if (b == escape) {
if (!dirty) {
dirty = true;
bfr.Add_mid(raw, bgn, pos);
}
++pos;
if (pos < end) { // check for eos; note that this ignores trailing "\"; EX: "a\" -> "a"
bfr.Add_byte(raw[pos]);
++pos;
}
}
else {
if (dirty) bfr.Add_byte(b);
++pos;
}
}
return dirty ? bfr.To_bry_and_clear() : raw;
}
public static void Clear(byte[] bry) {
int len = bry.length;
for (int i = 0; i < len; ++i)
bry[i] = Byte_.Zero;
}
}