mirror of
https://github.com/gnosygnu/xowa.git
synced 2025-06-13 12:54:14 +00:00
Compare commits
352 Commits
v4.6.0.190
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
2a4abd8f75 | ||
|
17a3b4e7b3 | ||
|
659bca3660 | ||
|
8684783139 | ||
|
7e53c8462d | ||
|
559503786b | ||
|
e117823e60 | ||
|
ff0f92b950 | ||
|
4187dc4a76 | ||
|
1a6a203cfd | ||
|
814e85ea70 | ||
|
0ef5058cfd | ||
|
aeef520228 | ||
|
4a7bd19056 | ||
|
7d357540c7 | ||
|
b1c52aa2b2 | ||
|
845253af79 | ||
|
541f5f6524 | ||
|
067e62dd03 | ||
|
19a315b8cd | ||
|
5c3d6a173b | ||
|
c801e3a20b | ||
|
59d8a42b22 | ||
|
567e03dc1d | ||
|
7550894dda | ||
|
caad4145d5 | ||
|
de841f8ff2 | ||
|
5f2e9c7514 | ||
|
d3896bf547 | ||
|
316c6c6a58 | ||
|
72051f4ce9 | ||
|
f19228c886 | ||
|
1b6324938c | ||
|
9b4ea48753 | ||
|
6ed7659b4d | ||
|
1eea3682ca | ||
|
4f87d1a195 | ||
|
ea9b592cfd | ||
|
3c9fd50ddc | ||
|
619d2f9844 | ||
|
bdae819908 | ||
|
f122a8d8a3 | ||
|
174e93cbfa | ||
|
0aced904a5 | ||
|
dc374fa7fc | ||
|
95e833d70c | ||
|
afed865c84 | ||
|
7b6b3ed09a | ||
|
a0c0b5b2fd | ||
|
062d308128 | ||
|
ad607d952c | ||
|
6592eaf8de | ||
|
45adc036a2 | ||
|
6b2e120fc1 | ||
|
7c0a8c5064 | ||
|
35475d631c | ||
|
efe415d3a3 | ||
|
97b1055b4e | ||
|
b51d224f09 | ||
|
b87e4d07cb | ||
|
b4516f5060 | ||
|
49e18a2255 | ||
|
026288f809 | ||
|
1103674d88 | ||
|
27756f8056 | ||
|
398a1c854a | ||
|
35f2027b20 | ||
|
be072de8d9 | ||
|
f760fd9cd0 | ||
|
3d5ec47aa8 | ||
|
53762288d7 | ||
|
7a0247417d | ||
|
0cdfa0992c | ||
|
dc66b926d3 | ||
|
8c7c9f88ff | ||
|
94b757682a | ||
|
1ebc9d3488 | ||
|
654810d56c | ||
|
b551c1875b | ||
|
ba1d4e0b7c | ||
|
a2fe75f402 | ||
|
a6331f5c89 | ||
|
43866163b9 | ||
|
49f8d4b000 | ||
|
994d405a26 | ||
|
04c499ce3e | ||
|
ebe82bea6a | ||
|
a9367eaca8 | ||
|
ee68162a4a | ||
|
6663b769d5 | ||
|
2dab6a90be | ||
|
b0e02979ac | ||
|
f9cf49c160 | ||
|
0d917bccc7 | ||
|
d1345bf724 | ||
|
3d74406a3e | ||
|
a6b128422e | ||
|
0c3cb1ba3d | ||
|
105446f5ca | ||
|
db73b4302d | ||
|
bd71db3ed6 | ||
|
a4b5f5de5d | ||
|
ecbcf1e707 | ||
|
7b00918941 | ||
|
8807dcfbeb | ||
|
a6ac592212 | ||
|
b05e3cd188 | ||
|
9c8650a4d9 | ||
|
73a56ffab3 | ||
|
e9e5724a2a | ||
|
c3c9d4ad1e | ||
|
5a35f3b05b | ||
|
7ad1291768 | ||
|
17d7a7ebed | ||
|
9809dfd6c7 | ||
|
b56673c56e | ||
|
8629292960 | ||
|
bc30fd8526 | ||
|
c47820b1a9 | ||
|
292726bd13 | ||
|
23eefef91a | ||
|
89d0ba1271 | ||
|
b2a6f7bbf1 | ||
|
ed010f76a8 | ||
|
bc65e9fa61 | ||
|
db01707032 | ||
|
7b3d6e5271 | ||
|
c3d524c493 | ||
|
f33f9c4ae9 | ||
|
02f9b9dae3 | ||
|
891cf53228 | ||
|
f73164d55e | ||
|
3355d03c44 | ||
|
bae9ba9e7a | ||
|
a5cbc4ede9 | ||
|
da87b17902 | ||
|
bfce37f0ba | ||
|
3e9bc6d93a | ||
|
775bff3bac | ||
|
bc2beba148 | ||
|
af337493af | ||
|
ca8afe657e | ||
|
57ad8e459a | ||
|
763c7b52b7 | ||
|
9cb60f2540 | ||
|
c6bca54d90 | ||
|
374de22699 | ||
|
2dee585fc1 | ||
|
898701131d | ||
|
c1b8911a7d | ||
|
f384d40e56 | ||
|
278d55cd62 | ||
|
11447820f2 | ||
|
5e2ce08abb | ||
|
5aec368f8d | ||
|
5f1d9c6f15 | ||
|
e0de779e1d | ||
|
bc5947507f | ||
|
7e2f832c33 | ||
|
357c725798 | ||
|
694c3bb133 | ||
|
3285a3c87d | ||
|
520a73537f | ||
|
9d8ab5d206 | ||
|
d49eda32a8 | ||
|
eca943d7a6 | ||
|
a7114ecb5a | ||
|
ad5613265d | ||
|
734206fbd6 | ||
|
605038d8c6 | ||
|
ae484a8234 | ||
|
cb3b78895c | ||
|
38f670649b | ||
|
9e97a7ea9f | ||
|
966b0eed59 | ||
|
59985227fb | ||
|
c307946bd2 | ||
|
b2864f8c6a | ||
|
41a521850b | ||
|
20c1e32ff2 | ||
|
90363fb9fa | ||
|
46aab7944d | ||
|
5ddf50d5b5 | ||
|
e2aa551feb | ||
|
11810c4fff | ||
|
e9024e057f | ||
|
9483b56121 | ||
|
8653e665cc | ||
|
dbdc558ed5 | ||
|
bdb1945d4f | ||
|
af9d6c3a92 | ||
|
de1b9a3991 | ||
|
d908d4f8b5 | ||
|
79bdab7946 | ||
|
0f8dd4a1f8 | ||
|
cb3f915cb2 | ||
|
a453ebd4cb | ||
|
7971f71dc3 | ||
|
f8bbdb1727 | ||
|
bc976ac300 | ||
|
c67970b5b9 | ||
|
eac055214c | ||
|
866debd51d | ||
|
9f0cfc27bb | ||
|
a10c2cd1dc | ||
|
4955748f6d | ||
|
73eb42c0ba | ||
|
fca507568f | ||
|
1bffdadbaf | ||
|
bb86b026fe | ||
|
88e0398696 | ||
|
e82641f341 | ||
|
597c138b56 | ||
|
fdd05c99a9 | ||
|
742e61b718 | ||
|
1caeea5705 | ||
|
24ea3793a2 | ||
|
ec9b3ee442 | ||
|
ea28172885 | ||
|
d362597d8f | ||
|
924b5fd17b | ||
|
b980351989 | ||
|
518605ece1 | ||
|
115ae8139e | ||
|
b17cb05edf | ||
|
a082e3cf5d | ||
|
5b2db5badf | ||
|
32cb332b18 | ||
|
23cbefdeb8 | ||
|
620f196d4e | ||
|
75105c8397 | ||
|
b67e528088 | ||
|
9e302b19b5 | ||
|
ce5fd232d8 | ||
|
cda21d987f | ||
|
8f029f479b | ||
|
d61fd33a87 | ||
|
1873c7c5f8 | ||
|
88dfc857bd | ||
|
9bc0c2c75d | ||
|
2598dee844 | ||
|
42842f0bcc | ||
|
a7029f8cf1 | ||
|
8c55d2406a | ||
|
0295d816fd | ||
|
80f4a0fbf5 | ||
|
227f7943ff | ||
|
7f3ab5f381 | ||
|
5ac949e8c0 | ||
|
1e254caa79 | ||
|
41e9fc1287 | ||
|
be5c65c24c | ||
|
87163c5104 | ||
|
e213d123f8 | ||
|
dee491a684 | ||
|
2ef6211e87 | ||
|
6449368800 | ||
|
06afe7a7b1 | ||
|
6559a2b858 | ||
|
a421703fb1 | ||
|
a94279c922 | ||
|
19c50b94be | ||
|
55a4891064 | ||
|
b350d95206 | ||
|
f5abfa11da | ||
|
66039fc9b3 | ||
|
a1da02a99f | ||
|
a51906bf4b | ||
|
f38930b63a | ||
|
0854cf9ba1 | ||
|
0280254e8a | ||
|
9dcc571fc5 | ||
|
dea0556df5 | ||
|
436f219477 | ||
|
5c8b70fd76 | ||
|
4547fa541f | ||
|
9bc2bd400c | ||
|
877b305136 | ||
|
0181a42d3d | ||
|
3b5a1f8ffc | ||
|
34dcfdde7d | ||
|
989ccde83a | ||
|
7f76d8128d | ||
|
b65fda764f | ||
|
5055f82d21 | ||
|
e3dce04680 | ||
|
0bfacb2ea5 | ||
|
9b51a7c660 | ||
|
9da8b4dde8 | ||
|
5d886501e8 | ||
|
d4a28d3ffe | ||
|
2526b677fa | ||
|
334bb0a6d0 | ||
|
cbae5d55bb | ||
|
a01e7409eb | ||
|
0cfb0b19ad | ||
|
d812b21dec | ||
|
70d845f438 | ||
|
8ab9bc5444 | ||
|
c459454da3 | ||
|
3b6efe4274 | ||
|
c7f54287af | ||
|
3852d4762b | ||
|
43cc4b15e8 | ||
|
641a17621f | ||
|
a6ce48fffa | ||
|
491d1905c9 | ||
|
3d9491e2de | ||
|
fbe158537e | ||
|
17da6dc17f | ||
|
b48b6def4e | ||
|
ee03d79536 | ||
|
cca043dff6 | ||
|
05e8c11338 | ||
|
b74ca77786 | ||
|
42dbaff1d2 | ||
|
648cd4944a | ||
|
c07e6e25b5 | ||
|
ba35901865 | ||
|
4d9072830c | ||
|
c94090cd09 | ||
|
31c6576b50 | ||
|
3a748eea32 | ||
|
cf94f252e9 | ||
|
5db81504fb | ||
|
4e920af183 | ||
|
0f75a625db | ||
|
f860edf064 | ||
|
4a1b2e25c0 | ||
|
f895259be6 | ||
|
42953aaa0f | ||
|
74b63d5f08 | ||
|
1cde843264 | ||
|
5204d33af7 | ||
|
bc9e017906 | ||
|
a5644dea07 | ||
|
bbbc14eb34 | ||
|
022d551760 | ||
|
73cb63c493 | ||
|
4909799a67 | ||
|
367a3a94b9 | ||
|
f22a0cca43 | ||
|
42b158c165 | ||
|
09d9f93d20 | ||
|
623c7a129e | ||
|
cc8b9810a7 | ||
|
31c7604f03 | ||
|
2fc03f6211 | ||
|
581aa5123c | ||
|
8c1f30039b | ||
|
61cc5e89a7 | ||
|
7bcbdabbfc |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.iml
|
||||
**/.idea/**
|
@ -3,8 +3,9 @@
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="tst"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||
<classpathentry kind="lib" path="lib/commons-compress-1.5.jar"/>
|
||||
<classpathentry kind="lib" path="lib/commons-compress-1.18.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="lib/xz-1.5.jar"/>
|
||||
<classpathentry kind="lib" path="lib/Saxon-HE-9.9.1-2.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,9 +14,10 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
import java.lang.*;
|
||||
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.ios.*;
|
||||
import gplx.langs.htmls.entitys.*;
|
||||
|
||||
import gplx.core.primitives.Int_obj_ref;
|
||||
import gplx.langs.htmls.entitys.Gfh_entity_;
|
||||
|
||||
public class Bry_ {
|
||||
public static final String Cls_val_name = "byte[]";
|
||||
public static final byte[] Empty = new byte[0];
|
||||
@ -154,7 +155,7 @@ public class Bry_ {
|
||||
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);
|
||||
Copy_to(src, src_bgn, src_len, trg, 0);
|
||||
return trg;
|
||||
}
|
||||
public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);}
|
||||
@ -178,14 +179,14 @@ public class Bry_ {
|
||||
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);
|
||||
Copy_to(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);
|
||||
Copy_to(src, 0, src_len, rv, 1);
|
||||
rv[0] = b;
|
||||
return rv;
|
||||
}
|
||||
@ -297,29 +298,30 @@ public class Bry_ {
|
||||
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) {
|
||||
public static void Copy_to(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_pos_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
|
||||
public static void Copy_to_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
|
||||
// copies src to trg, but in reverse order; EX: trg="1" src="432." -> "1.234"
|
||||
int len = src_end - src_bgn;
|
||||
for (int i = 0; i < len; i++)
|
||||
trg[trg_bgn + i] = src[src_end - i - 1];
|
||||
}
|
||||
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);
|
||||
public static byte[] Replace_one(byte[] orig, byte[] find, byte[] repl) {
|
||||
// find val
|
||||
int orig_len = orig.length;
|
||||
int find_pos = Bry_find_.Find(orig, find, 0, orig_len, true);
|
||||
if (find_pos == Bry_find_.Not_found) return orig; // nothing found; exit
|
||||
|
||||
// do copy
|
||||
int find_len = find.length, repl_len = repl.length;
|
||||
int rv_len = orig_len + repl_len - find_len;
|
||||
byte[] rv = new byte[rv_len];
|
||||
Copy_to(orig, 0 , find_pos, rv, 0 ); // copy orig before repl
|
||||
Copy_to(repl, 0 , repl_len, rv, find_pos ); // copy repl
|
||||
Copy_to(orig, find_pos + find_len, orig_len, rv, find_pos + repl_len); // copy orig after repl
|
||||
return rv;
|
||||
}
|
||||
public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);}
|
||||
@ -437,9 +439,9 @@ public class Bry_ {
|
||||
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) {
|
||||
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws, true);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws, true);}
|
||||
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary, boolean reuse_bry_if_noop) {
|
||||
int txt_bgn = bgn, txt_end = end;
|
||||
boolean all_ws = true;
|
||||
if (trim_bgn) {
|
||||
@ -465,7 +467,8 @@ public class Bry_ {
|
||||
if (all_ws) return Bry_.Empty;
|
||||
}
|
||||
|
||||
if ( bgn == 0 && end == src.length // Trim is called on entire bry, not subset
|
||||
if ( reuse_bry_if_noop
|
||||
&& bgn == 0 && end == src.length // Trim is called on entire bry, not subset
|
||||
&& bgn == txt_bgn && end == txt_end // Trim hasn't trimmed anything
|
||||
) {
|
||||
return src;
|
||||
@ -473,6 +476,19 @@ public class Bry_ {
|
||||
else
|
||||
return Bry_.Mid(src, txt_bgn, txt_end);
|
||||
}
|
||||
public static byte[] Trim_bgn(byte[] v, byte trim, int bgn) {
|
||||
boolean trimmed = false;
|
||||
int len = v.length;
|
||||
int pos = bgn;
|
||||
for (; pos < len; pos++) {
|
||||
if (v[pos] == trim) {
|
||||
trimmed = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return trimmed ? Bry_.Mid(v, pos, len) : v;
|
||||
}
|
||||
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
|
||||
@ -977,6 +993,43 @@ public class Bry_ {
|
||||
}
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
public static byte[] Replace_many(byte[] src, byte[] find, byte[] repl) {
|
||||
Bry_bfr bfr = null;
|
||||
int src_len = src.length;
|
||||
int find_len = find.length;
|
||||
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
// find find_bgn
|
||||
int find_bgn = Bry_find_.Find_fwd(src, find, pos, src_len);
|
||||
|
||||
// exit if nothing found
|
||||
if (find_bgn == Bry_find_.Not_found)
|
||||
break;
|
||||
|
||||
// lazy-instantiation
|
||||
if (bfr == null)
|
||||
bfr = Bry_bfr_.New();
|
||||
|
||||
// add everything up to find_bgn
|
||||
bfr.Add_mid(src, pos, find_bgn);
|
||||
|
||||
// add repl
|
||||
bfr.Add(repl);
|
||||
|
||||
// move pos forward
|
||||
pos = find_bgn + find_len;
|
||||
}
|
||||
|
||||
// nothing found; return src
|
||||
if (bfr == null)
|
||||
return src;
|
||||
else {
|
||||
// add rest
|
||||
bfr.Add_mid(src, pos, src_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]) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,7 +14,11 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.tests.*;
|
||||
|
||||
import gplx.core.primitives.Int_obj_ref;
|
||||
import gplx.core.tests.Gftest;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Bry__tst {
|
||||
private final Bry__fxt fxt = new Bry__fxt();
|
||||
@Test public void new_ascii_() {
|
||||
@ -256,6 +260,12 @@ public class Bry__tst {
|
||||
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
|
||||
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
|
||||
}
|
||||
@Test public void Trim_bgn() {
|
||||
fxt.Test_trim_bgn(" a" , Byte_ascii.Space, "a"); // trim.one
|
||||
fxt.Test_trim_bgn(" a" , Byte_ascii.Space, "a"); // trim.many
|
||||
fxt.Test_trim_bgn("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_bgn("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@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
|
||||
@ -288,6 +298,10 @@ class Bry__fxt {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_end(raw_bry, trim, raw_bry.length)));
|
||||
}
|
||||
public void Test_trim_bgn(String raw, byte trim, String expd) {
|
||||
byte[] raw_bry = Bry_.new_a7(raw);
|
||||
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_bgn(raw_bry, trim, 0)));
|
||||
}
|
||||
public void Test_new_u8(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_u8(raw));}
|
||||
public void Test_new_a7(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_a7(raw));}
|
||||
public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));}
|
||||
|
@ -79,7 +79,7 @@ public class Bry_bfr {
|
||||
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);
|
||||
Bry_.Copy_to(val, 0, val_len, bfr, bfr_len);
|
||||
// Array_.Copy_to(val, 0, bfr, bfr_len, val_len);
|
||||
bfr_len += val_len;
|
||||
return this;
|
||||
@ -88,7 +88,7 @@ public class Bry_bfr {
|
||||
int len = end - bgn;
|
||||
if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
|
||||
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
|
||||
Bry_.Copy_by_pos(val, bgn, end, bfr, bfr_len);
|
||||
Bry_.Copy_to(val, bgn, end, bfr, bfr_len);
|
||||
// Array_.Copy_to(val, bgn, bfr, bfr_len, len);
|
||||
bfr_len += len;
|
||||
return this;
|
||||
@ -97,7 +97,7 @@ public class Bry_bfr {
|
||||
int len = end - bgn;
|
||||
if (len < 0) throw Err_.new_wo_type("negative len", "bgn", bgn, "end", end, "excerpt", String_.new_u8__by_len(val, bgn, bgn + 16)); // NOTE: check for invalid end < bgn, else difficult to debug errors later; DATE:2014-05-11
|
||||
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
|
||||
Bry_.Copy_by_pos_reversed(val, bgn, end, bfr, bfr_len);
|
||||
Bry_.Copy_to_reversed(val, bgn, end, bfr, bfr_len);
|
||||
// Array_.Copy_to(val, bgn, bfr, bfr_len, len);
|
||||
bfr_len += len;
|
||||
return this;
|
||||
@ -118,7 +118,7 @@ public class Bry_bfr {
|
||||
public Bry_bfr Add_bfr_and_preserve(Bry_bfr src) {
|
||||
int len = src.bfr_len;
|
||||
if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2);
|
||||
Bry_.Copy_by_pos(src.bfr, 0, len, bfr, bfr_len);
|
||||
Bry_.Copy_to(src.bfr, 0, len, bfr, bfr_len);
|
||||
// Array_.Copy_to(src.bfr, 0, bfr, bfr_len, len);
|
||||
bfr_len += len;
|
||||
return this;
|
||||
@ -163,7 +163,7 @@ public class Bry_bfr {
|
||||
if (all_ws) return this;
|
||||
}
|
||||
src_len = src_end - src_bgn;
|
||||
Bry_.Copy_by_pos(src.bfr, src_bgn, src_end, bfr, bfr_len);
|
||||
Bry_.Copy_to(src.bfr, src_bgn, src_end, bfr, bfr_len);
|
||||
// Array_.Copy_to(src.bfr, src_bgn, bfr, bfr_len, src_len);
|
||||
bfr_len += src_len;
|
||||
src.Clear();
|
||||
@ -304,10 +304,10 @@ public class Bry_bfr {
|
||||
Add_mid(val, bgn, end);
|
||||
return this;
|
||||
}
|
||||
public Bry_bfr Add_bry_many(byte[]... ary) {
|
||||
int len = ary.length;
|
||||
public Bry_bfr Add_bry_many(byte[]... val) {
|
||||
int len = val.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
byte[] bry = ary[i];
|
||||
byte[] bry = val[i];
|
||||
if (bry != null && bry.length > 0)
|
||||
this.Add(bry);
|
||||
}
|
||||
@ -338,10 +338,10 @@ public class Bry_bfr {
|
||||
}
|
||||
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
|
||||
}
|
||||
public Bry_bfr Add_str_u8_many(String... ary) {
|
||||
int len = ary.length;
|
||||
public Bry_bfr Add_str_u8_many(String... val) {
|
||||
int len = val.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
Add_str_u8(ary[i]);
|
||||
Add_str_u8(val[i]);
|
||||
return this;
|
||||
}
|
||||
public Bry_bfr Add_str_u8_fmt(String fmt, Object... args) {
|
||||
@ -364,6 +364,10 @@ public class Bry_bfr {
|
||||
}
|
||||
catch (Exception e) {throw Err_.new_exc(e, "core", "invalid UTF-8 sequence", "s", str);}
|
||||
}
|
||||
public Bry_bfr Add_str_mid(String src, int bgn, int end) {
|
||||
this.Add_str_u8(String_.Mid(src, bgn, end));
|
||||
return this;
|
||||
}
|
||||
public Bry_bfr Add_kv_dlm(boolean line, String key, Object val) {
|
||||
this.Add_str_a7(key).Add_byte_colon().Add_byte_space();
|
||||
this.Add(Bry_.new_u8(Object_.Xto_str_strict_or_null_mark(val)));
|
||||
@ -495,16 +499,16 @@ public class Bry_bfr {
|
||||
}
|
||||
public boolean Match_end_byt(byte b) {return bfr_len == 0 ? false : bfr[bfr_len - 1] == b;}
|
||||
public boolean Match_end_byt_nl_or_bos() {return bfr_len == 0 ? true : bfr[bfr_len - 1] == Byte_ascii.Nl;}
|
||||
public boolean Match_end_ary(byte[] ary) {return Bry_.Match(bfr, bfr_len - ary.length, bfr_len, ary);}
|
||||
public boolean Match_end_ary(byte[] val) {return Bry_.Match(bfr, bfr_len - val.length, bfr_len, val);}
|
||||
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);
|
||||
Bry_.Copy_to (bfr , 0, add_pos, new_bfr, 0);
|
||||
Bry_.Copy_to (add_bry, add_bgn, add_end, new_bfr, add_pos);
|
||||
Bry_.Copy_to (bfr , add_pos, bfr_len, new_bfr, add_pos + add_len);
|
||||
bfr = new_bfr;
|
||||
bfr_len += add_len;
|
||||
bfr_max = new_max;
|
||||
@ -514,7 +518,7 @@ public class Bry_bfr {
|
||||
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);
|
||||
Bry_.Copy_to(bfr, rng_end, bfr_len, bfr, rng_bgn);
|
||||
bfr_len -= rng_len;
|
||||
return this;
|
||||
}
|
||||
@ -564,10 +568,10 @@ public class Bry_bfr {
|
||||
rv[11] = true;
|
||||
return rv;
|
||||
}
|
||||
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];
|
||||
public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... val) {
|
||||
int val_len = val.length;
|
||||
for (int i = 0; i < val_len; i++) {
|
||||
byte[] itm = val[i];
|
||||
boolean itm_has_bytes = Bry_.Len_gt_0(itm);
|
||||
if ( i != 0
|
||||
&& itm_has_bytes
|
||||
@ -584,7 +588,7 @@ public class Bry_bfr {
|
||||
public byte[] To_bry() {return bfr_len == 0 ? Bry_.Empty : Bry_.Mid(bfr, 0, bfr_len);}
|
||||
public byte[] To_bry_and_clear_and_trim() {return To_bry_and_clear_and_trim(true, true, Bry_.Trim_ary_ws);}
|
||||
public byte[] To_bry_and_clear_and_trim(boolean trim_bgn, boolean trim_end, byte[] trim_bry) {
|
||||
byte[] rv = Bry_.Trim(bfr, 0, bfr_len, trim_bgn, trim_end, trim_bry);
|
||||
byte[] rv = Bry_.Trim(bfr, 0, bfr_len, trim_bgn, trim_end, trim_bry, false); // NOTE: must not reuse bry; ISSUE#:562; DATE:2019-09-02
|
||||
this.Clear();
|
||||
return rv;
|
||||
}
|
||||
|
@ -219,6 +219,20 @@ public class Bry_bfr_tst {
|
||||
fxt.Test__to_bry_ary_and_clear("a\nb\nc" , "a", "b", "c"); // lines=n
|
||||
fxt.Test__to_bry_ary_and_clear("a\n" , "a"); // nl at end
|
||||
}
|
||||
@Test public void To_bry_ary_and_clear_and_trim__memory_reference_bug() {// PURPOSE:test that bry isn't reused; ISSUE#:562; DATE:2019-09-02
|
||||
String str_a = "aaaaaaaaaaaaaaaa" // NOTE: length is 16 b/c bry_bfr init's to 16 len
|
||||
, str_b = "bbbbbbbbbbbbbbbb";
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
bfr.Add_str_a7(str_a);
|
||||
byte[] bry_a = bfr.To_bry_and_clear_and_trim();
|
||||
Gftest.Eq__str(str_a, String_.new_u8(bry_a));
|
||||
|
||||
bfr.Add_str_a7(str_b);
|
||||
byte[] bry_b = bfr.To_bry_and_clear_and_trim();
|
||||
Gftest.Eq__str(str_b, String_.new_u8(bry_b));
|
||||
|
||||
Gftest.Eq__str(str_a, String_.new_u8(bry_a)); // fais if bry_b
|
||||
}
|
||||
}
|
||||
class ByteAryBfr_fxt {
|
||||
private final Bry_bfr bfr = Bry_bfr_.Reset(16);
|
||||
|
@ -17,7 +17,7 @@ package gplx;
|
||||
public class Byte_ascii {
|
||||
public static final byte
|
||||
Null = 0 , Backfeed = 8, Tab = 9
|
||||
, Nl = 10, Formfeed = 12, Cr = 13
|
||||
, Nl = 10, Vertical_tab = 11, Formfeed = 12, Cr = 13
|
||||
, Escape = 27
|
||||
, Space = 32, Bang = 33, Quote = 34
|
||||
, Hash = 35, Dollar = 36, Percent = 37, Amp = 38, Apos = 39
|
||||
@ -114,6 +114,7 @@ public class Byte_ascii {
|
||||
, Lt_bry = new byte[] {Byte_ascii.Lt}
|
||||
, Gt_bry = new byte[] {Byte_ascii.Gt}
|
||||
, Question_bry = new byte[] {Byte_ascii.Question}
|
||||
, Backslash_bry = new byte[] {Byte_ascii.Backslash}
|
||||
, Brack_bgn_bry = new byte[] {Byte_ascii.Brack_bgn}
|
||||
, Brack_end_bry = new byte[] {Byte_ascii.Brack_end}
|
||||
, Apos_bry = new byte[] {Byte_ascii.Apos}
|
||||
@ -127,3 +128,11 @@ public class Byte_ascii {
|
||||
, Num_1_bry = new byte[] {Byte_ascii.Num_1}
|
||||
;
|
||||
}
|
||||
/*
|
||||
SYMBOLS
|
||||
-------
|
||||
Byte_ascii.Bang | Byte_ascii.Slash | 33 -> 47 | !"#$%&'()*+,-./
|
||||
Byte_ascii.Colon | Byte_ascii.At | 58 -> 64 | :;<=>?@
|
||||
Byte_ascii.Brack_bgn | Byte_ascii.Tick | 91 -> 96 | [\]^_`
|
||||
Byte_ascii.Curly_bgn | Byte_ascii.Tilde | 123 -> 126 | {|}~
|
||||
*/
|
||||
|
@ -56,13 +56,14 @@ public class Char_ {
|
||||
if (itm == match) return true;
|
||||
return false;
|
||||
}
|
||||
public static int To_int_or(char c, int or) {
|
||||
public static int To_digit_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 int To_int(char c) {return (int)c;}
|
||||
public static String To_str(char[] ary, int pos, int length) {return new String(ary, pos, length);}
|
||||
public static String To_str(int b) {return To_str((char)b);}
|
||||
public static String To_str(char c) {return String.valueOf(c);}
|
||||
|
@ -85,6 +85,9 @@ public class DateAdp implements CompareAble, Gfo_invk {
|
||||
: Timezone_offset_test
|
||||
;
|
||||
}
|
||||
public String Timezone_id() {
|
||||
return "UTC"; // under.getTimeZone().getID(); // NOTE: timezone is always UTC, unless over-ridden by tests
|
||||
}
|
||||
public DateAdp XtoUtc() {
|
||||
java.util.Date date = under.getTime();
|
||||
java.util.TimeZone tz = under.getTimeZone();
|
||||
@ -109,6 +112,7 @@ public class DateAdp implements CompareAble, Gfo_invk {
|
||||
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);}
|
||||
@ -147,5 +151,17 @@ public class DateAdp implements CompareAble, Gfo_invk {
|
||||
this.under = new GregorianCalendar(year, month - Month_base0adj, day, hour, minute, second);
|
||||
under.set(Calendar.MILLISECOND, frac);
|
||||
}
|
||||
protected DateAdp(int year, int month, int day, int hour, int minute, int second, int frac, TimeZone timeZone) {
|
||||
this.under = new GregorianCalendar(timeZone);
|
||||
under.set(year, month - Month_base0adj, day, hour, minute, second);
|
||||
under.set(Calendar.MILLISECOND, frac);
|
||||
}
|
||||
public void SetTzOffset(int offset) {
|
||||
java.util.Date date = under.getTime();
|
||||
long msFromEpochGmt = date.getTime();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(msFromEpochGmt - offset*1000);
|
||||
under = cal;
|
||||
}
|
||||
public static final int Month_base0adj = 1;
|
||||
}
|
||||
|
@ -66,11 +66,13 @@ public class DateAdp_ implements Gfo_invk {
|
||||
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;
|
||||
public static int DaysInMonth(DateAdp date) {return DaysInMonth(date.Month(), date.Year());}
|
||||
public static int DaysInMonth(int month, int year) {
|
||||
int rv = DaysInMonth_ary[month - Int_.Base1];
|
||||
if (rv == 28 && IsLeapYear(year)) rv = 29;
|
||||
return rv;
|
||||
} static int [] DaysInMonth_ary = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
}
|
||||
private 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;
|
||||
@ -114,10 +116,29 @@ public class DateAdp_ implements Gfo_invk {
|
||||
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 DateAdp New_w_tz(int y, int m, int d, int h, int i, int s, int us, String tz_id) {
|
||||
TimeZone tz = String_.Eq(tz_id, "UTC") ? TIME_ZONE__UTC : TimeZone.getTimeZone(tz_id);
|
||||
return new DateAdp(y, m, d, h, i, s, us/1000, tz);
|
||||
}
|
||||
private static TimeZone TIME_ZONE__UTC = TimeZone.getTimeZone("UTC");
|
||||
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_tz = 10, SegIdx__max = 11;
|
||||
public static String Xto_str_fmt_or(DateAdp v, String fmt, String or) {
|
||||
return v == null ? or : v.XtoStr_fmt(fmt);
|
||||
}
|
||||
public static DateAdp FirstDayofYear(int year) {
|
||||
return new DateAdp(year, 1, 1, 0, 0, 0, 0);
|
||||
}
|
||||
public static DateAdp DateByDayofYear(int year, int day) {
|
||||
return new DateAdp(year, 1, day, 0, 0, 0, 0);
|
||||
}
|
||||
public static DateAdp DateByBits(int y, int m, int d, int h, int i, int s, int us, int tz_ofs, byte[] tz_abbr) {
|
||||
DateAdp dte = new DateAdp(y, m, d, h, i, s, us/1000);
|
||||
if (tz_ofs != 0)
|
||||
dte.SetTzOffset(tz_ofs);
|
||||
return dte;
|
||||
}
|
||||
public static final String
|
||||
Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss"
|
||||
, Fmt__yyyyMMdd = "yyyyMMdd";
|
||||
|
@ -60,6 +60,9 @@ public class DateAdp__tst {
|
||||
@Test public void XtoUtc() {
|
||||
fxt.Test__to_utc("2012-01-01 00:00", "2012-01-01 05:00"); //4=Wed
|
||||
}
|
||||
@Test public void Timezone_id() {
|
||||
fxt.Test__timezone_id("2015-12-26T10:03:53Z", "UTC");
|
||||
}
|
||||
}
|
||||
class DateAdp__fxt {
|
||||
public void Test__parse_gplx(String raw, String expd) {
|
||||
@ -83,4 +86,7 @@ class DateAdp__fxt {
|
||||
public void Test__to_utc(String raw, String expd) {
|
||||
Tfds.Eq(expd, DateAdp_.parse_gplx(raw).XtoUtc().XtoStr_fmt_yyyy_MM_dd_HH_mm());
|
||||
}
|
||||
public void Test__timezone_id(String raw, String expd) {
|
||||
Gftest.Eq__str(expd, DateAdp_.parse_gplx(raw).XtoUtc().Timezone_id());
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
public class Decimal_adp implements CompareAble {
|
||||
public int compareTo(Object obj) {Decimal_adp comp = (Decimal_adp)obj; return under.compareTo(comp.under);}
|
||||
public Decimal_adp Floor() {return Decimal_adp_.int_(this.To_int());}
|
||||
protected Decimal_adp(BigDecimal v) {this.under = v;} private final BigDecimal under;
|
||||
protected Decimal_adp(int v) {this.under = new BigDecimal(v);}
|
||||
public Object Under() {return under;}
|
||||
@ -79,6 +80,9 @@ public class Decimal_adp implements CompareAble {
|
||||
}
|
||||
return new Decimal_adp(new_val);
|
||||
}
|
||||
public Decimal_adp Round_to_default_precision() {
|
||||
return new Decimal_adp(under.round(Decimal_adp_.Gplx_rounding_context));
|
||||
}
|
||||
public boolean Comp_gte(Decimal_adp v) {return under.doubleValue() >= v.under.doubleValue();}
|
||||
public boolean Comp_gte(int v) {return under.doubleValue() >= v;}
|
||||
public boolean Comp_lte(Decimal_adp v) {return under.doubleValue() <= v.under.doubleValue();}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,10 +14,15 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class Decimal_adp_ {
|
||||
public static final String Cls_val_name = "decimal";
|
||||
public static final Class<?> Cls_ref_type = Decimal_adp.class;
|
||||
@ -53,17 +58,34 @@ public class Decimal_adp_ {
|
||||
return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
|
||||
}
|
||||
public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
|
||||
public static Decimal_adp divide_(long lhs, long rhs) {
return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
}
public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp divide_(long lhs, long rhs) {
|
||||
return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
|
||||
}
|
||||
public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
|
||||
public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
|
||||
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
public static Decimal_adp parse(String raw) {
|
||||
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
|
||||
public static Decimal_adp parse(String raw) {
|
||||
try {
|
||||
DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US); // always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
|
||||
nf.setParseBigDecimal(true);
|
||||
// 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
|
||||
if (raw.contains("e")) {
|
||||
raw = raw.replace("e", "E");
|
||||
}
|
||||
// 2021-02-13|ISSUE#:838|Parse '.' as '0.'; PAGE:en.w:2019_FIVB_Volleyball_Women%27s_Challenger_Cup#Pool_A
|
||||
if (raw.startsWith(".")) {
|
||||
raw = "0" + raw;
|
||||
}
|
||||
BigDecimal bd = (BigDecimal)nf.parse(raw);
|
||||
return new Decimal_adp(bd);
|
||||
} catch (ParseException e) {
|
||||
throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw);
|
||||
}
|
||||
}
public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
|
||||
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31
}
|
||||
}
|
||||
public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
|
||||
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
|
||||
public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,7 +14,9 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class Decimal_adp__tst {
|
||||
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt();
|
||||
@Test public void divide_() {
|
||||
@ -37,6 +39,11 @@ public class Decimal_adp__tst {
|
||||
fxt.Test_parse("1", "1");
|
||||
fxt.Test_parse("1.2", "1.2");
|
||||
fxt.Test_parse("0.1", "0.1");
|
||||
fxt.Test_parse("1.2E1", "12");
|
||||
fxt.Test_parse("1.2e1", "12"); // 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
|
||||
}
|
||||
@Test public void parse_dot() {
|
||||
fxt.Test_parse(".", "0"); // 2021-02-13|ISSUE#:838|Parse '.' as '0.'; PAGE:en.w:2019_FIVB_Volleyball_Women%27s_Challenger_Cup#Pool_A
|
||||
}
|
||||
@Test public void Truncate_decimal() {
|
||||
fxt.Test_truncate_decimal("1", "1");
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,6 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
|
||||
public class Double_ {
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
@ -42,7 +43,9 @@ public class Double_ {
|
||||
int v_as_int = (int)v;
|
||||
return v == v_as_int
|
||||
? Int_.To_str(v_as_int) // convert to int, and call print String to eliminate any trailing decimal places
|
||||
: Float_.To_str((float)v); // calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d; DATE:2014-07-29
|
||||
// DATE:2014-07-29; calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d
|
||||
// DATE:2020-08-12; calling ToStrByPrintF b/c better at removing trailing 0s; ISSUE#:697;
|
||||
: gplx.objects.primitives.Double_.ToStrByPrintF(v);
|
||||
}
|
||||
public static int Compare(double lhs, double rhs) {
|
||||
if (lhs == rhs) return CompareAble_.Same;
|
||||
|
@ -28,6 +28,7 @@ public class Err_ {
|
||||
}
|
||||
public static Err new_unhandled(Object val) {return new Err(Bool_.Y, Trace_null, Type__gplx, "val is not in switch/if", "val", val);}
|
||||
public static Err new_unhandled_default(Object val) {return new Err(Bool_.Y, Trace_null, Type__gplx, "val is not in switch", "val", val);}
|
||||
public static Err new_unhandled_default_w_msg(Object val, String msg) {return new Err(Bool_.Y, Trace_null, Type__gplx, "val is not in switch", "val", val, "msg", msg);}
|
||||
public static Err new_unsupported() {return new Err(Bool_.Y, Trace_null, Type__gplx, "method not supported");}
|
||||
public static Err new_unimplemented() {return new Err(Bool_.Y, Trace_null, Type__gplx, "method not implemented");}
|
||||
public static Err new_unimplemented_w_msg(String msg, Object... args) {return new Err(Bool_.Y, Trace_null, Type__gplx, msg, args);}
|
||||
|
@ -72,6 +72,16 @@ public class GfoMsg_ {
|
||||
rv.Add("", vals[i]);
|
||||
return rv;
|
||||
}
|
||||
public static Hash_adp Read_str_ary_as_hash(GfoMsg m, String k) {
|
||||
String[] ary = m.ReadStrAry(k, "|");
|
||||
int ary_len = ary.length;
|
||||
if (ary_len == 0) return Hash_adp_.Noop;
|
||||
Hash_adp rv = Hash_adp_.New();
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
rv.Add_if_dupe_use_1st(ary[i], ary[i]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class GfoMsg_wtr extends GfoMsg_base {
|
||||
@Override protected Object ReadOr(String k, Object defaultOr) {
|
||||
|
@ -27,7 +27,7 @@ public class Gfo_usr_dlg_ {
|
||||
}
|
||||
public static String Test__list__term__get_1st() {
|
||||
Instance = Noop;
|
||||
String[] rv = ((Gfo_usr_dlg__gui_test)test__list.Gui_wkr()).Warns().To_str_ary_and_clear();
|
||||
String[] rv = ((Gfo_usr_dlg__gui_mock)test__list.Gui_wkr()).Warns().To_str_ary_and_clear();
|
||||
return rv.length == 0 ? "" : rv[0];
|
||||
}
|
||||
public static void Test__show__init() {
|
||||
|
@ -18,7 +18,7 @@ import gplx.core.consoles.*; import gplx.core.lists.rings.*;
|
||||
public class Gfo_usr_dlg__gui_ {
|
||||
public static final Gfo_usr_dlg__gui Noop = new Gfo_usr_dlg__gui_noop();
|
||||
public static final Gfo_usr_dlg__gui Console = new Gfo_usr_dlg__gui_console();
|
||||
public static final Gfo_usr_dlg__gui Test = new Gfo_usr_dlg__gui_test();
|
||||
public static final Gfo_usr_dlg__gui Test = new Gfo_usr_dlg__gui_mock();
|
||||
public static final Gfo_usr_dlg__gui Mem = new Gfo_usr_dlg__gui_mem_string();
|
||||
public static String Mem_file() {return ((Gfo_usr_dlg__gui_mem_string)Mem).file;}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.lists.rings.*;
|
||||
public class Gfo_usr_dlg__gui_test implements Gfo_usr_dlg__gui {
|
||||
public class Gfo_usr_dlg__gui_mock implements Gfo_usr_dlg__gui {
|
||||
public List_adp Warns() {return warns;} private final List_adp warns = List_adp_.New();
|
||||
public List_adp Msgs() {return msgs;} private final List_adp msgs = List_adp_.New();
|
||||
public Ring__string Prog_msgs() {return ring;} private final Ring__string ring = new Ring__string().Max_(0);
|
@ -16,8 +16,9 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx;
|
||||
public interface Gfo_usr_dlg__log extends Gfo_invk {
|
||||
boolean Enabled(); void Enabled_(boolean v);
|
||||
boolean Queue_enabled(); void Queue_enabled_(boolean v);
|
||||
Io_url Log_dir(); void Log_dir_(Io_url v);
|
||||
void Queue_enabled_(boolean v);
|
||||
Io_url Log_dir();
|
||||
void Log_dir_(Io_url v);
|
||||
Io_url Session_dir();
|
||||
Io_url Session_fil();
|
||||
void Log_msg_to_url_fmt(Io_url url, String fmt, Object... args);
|
||||
|
@ -16,10 +16,12 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.core.consoles.*; import gplx.core.brys.fmtrs.*;
|
||||
public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
|
||||
private final Object thread_lock = new Object();
|
||||
private int archive_dirs_max = 8;
|
||||
private Io_url log_dir, err_fil;
|
||||
private Ordered_hash queued_list = Ordered_hash_.New();
|
||||
private Bry_fmtr fmtr = Bry_fmtr.New__tmp(); private Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
|
||||
private final Ordered_hash queued_list = Ordered_hash_.New();
|
||||
private final Bry_fmtr fmtr = Bry_fmtr.New__tmp();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
|
||||
public boolean Queue_enabled() {return queue_enabled;} public void Queue_enabled_(boolean v) {queue_enabled = v; if (!v) this.Flush();} private boolean queue_enabled;
|
||||
public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled = true;
|
||||
public Io_url Session_dir() {return session_dir;} private Io_url session_dir;
|
||||
@ -31,18 +33,23 @@ public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
|
||||
if (fil.Url() == null) {
|
||||
fil.Url_(session_dir.GenSubFil("session.txt"));
|
||||
}
|
||||
fil.Flush();
|
||||
fil.Flush(enabled);
|
||||
}
|
||||
}
|
||||
public Io_url Log_dir() {return log_dir;}
|
||||
public void Log_dir_(Io_url log_dir) {
|
||||
this.log_dir = log_dir;
|
||||
if (enabled) {
|
||||
session_dir = log_dir.GenSubDir(Datetime_now.Get().XtoStr_fmt_yyyyMMdd_HHmmss_fff());
|
||||
session_fil = session_dir.GenSubFil("session.txt");
|
||||
err_fil = session_dir.GenSubFil("err.txt");
|
||||
}
|
||||
}
|
||||
public void Log_term() {
|
||||
if (!enabled) return;
|
||||
if (!enabled) {
|
||||
Io_mgr.Instance.DeleteDirDeep(log_dir);
|
||||
return;
|
||||
}
|
||||
Io_url[] archive_dirs = Io_mgr.Instance.QueryDir_args(log_dir).DirInclude_().DirOnly_().ExecAsUrlAry();
|
||||
int archive_dirs_len = archive_dirs.length;
|
||||
int session_cutoff = archive_dirs_len - archive_dirs_max;
|
||||
@ -79,8 +86,13 @@ public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
|
||||
}
|
||||
catch (Exception e) {Err_.Noop(e);} // java.lang.StringBuilder can throw exceptions in some situations when called on a different thread; ignore errors
|
||||
} private String_bldr sb = String_bldr_.new_thread(); // NOTE: use java.lang.StringBuffer to try to avoid random exceptions when called on a different thread
|
||||
private String Bld_msg(String s) {return sb.Add(Datetime_now.Get_force().XtoUtc().XtoStr_fmt_yyyyMMdd_HHmmss_fff()).Add(" ").Add(s).Add_char_nl().To_str_and_clear();}
|
||||
private String Bld_msg(String s) {
|
||||
synchronized (thread_lock) { // THREAD:synchronized neded b/c multiple threads can still mutate the same sb; ISSUE#:646; DATE:2020-03-16
|
||||
return sb.Add(Datetime_now.Get_force().XtoUtc().XtoStr_fmt_yyyyMMdd_HHmmss_fff()).Add(" ").Add(s).Add_char_nl().To_str_and_clear();
|
||||
}
|
||||
}
|
||||
private void Log_msg(Io_url url, String txt) {
|
||||
synchronized (thread_lock) { // THREAD:synchronized neded b/c queued_list can be accessible by multiple threads; ISSUE#:646; DATE:2020-01-09
|
||||
if (queue_enabled) {
|
||||
String url_raw = url == null ? "mem" : url.Raw();
|
||||
Usr_log_fil fil = (Usr_log_fil)queued_list.Get_by(url_raw);
|
||||
@ -90,24 +102,30 @@ public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
|
||||
}
|
||||
fil.Add(txt);
|
||||
}
|
||||
else
|
||||
else {
|
||||
if (enabled)
|
||||
Io_mgr.Instance.AppendFilStr(url, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_archive_dirs_max_)) archive_dirs_max = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_log_dir_)) log_dir = m.ReadIoUrl("v");
|
||||
if (ctx.Match(k, "enabled_")) enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, "archive_dirs_max_")) archive_dirs_max = m.ReadInt("v");
|
||||
else if (ctx.Match(k, "log_dir_")) log_dir = m.ReadIoUrl("v");
|
||||
else return Gfo_invk_.Rv_unhandled;
|
||||
return this;
|
||||
} public static final String Invk_enabled_ = "enabled_", Invk_archive_dirs_max_ = "archive_dirs_max_", Invk_log_dir_ = "log_dir_";
|
||||
static final String Dir_name_log = "log";
|
||||
}
|
||||
public static final Gfo_usr_dlg__log_base Instance = new Gfo_usr_dlg__log_base();
|
||||
}
|
||||
class Usr_log_fil {
|
||||
public Usr_log_fil(Io_url url) {this.url = url;}
|
||||
public Io_url Url() {return url;} public Usr_log_fil Url_(Io_url v) {url = v; return this;} Io_url url;
|
||||
public void Add(String text) {sb.Add(text);} String_bldr sb = String_bldr_.new_();
|
||||
public void Flush() {
|
||||
private final String_bldr sb = String_bldr_.new_();
|
||||
public Usr_log_fil(Io_url url) {
|
||||
this.url = url;
|
||||
}
|
||||
public Io_url Url() {return url;} public Usr_log_fil Url_(Io_url v) {url = v; return this;} private Io_url url;
|
||||
public void Add(String text) {sb.Add(text);}
|
||||
public void Flush(boolean enabled) {
|
||||
if (!enabled) return;
|
||||
if (sb.Count() == 0) return;
|
||||
try {
|
||||
Io_mgr.Instance.AppendFilStr(url, sb.To_str_and_clear());
|
||||
|
@ -21,6 +21,7 @@ public interface Hash_adp extends gplx.core.lists.EnumerAble {
|
||||
Object Get_by_or_fail(Object key);
|
||||
void Add(Object key, Object val);
|
||||
Hash_adp Add_and_more(Object key, Object val);
|
||||
Hash_adp Add_many_as_key_and_val(Object... ary);
|
||||
void Add_as_key_and_val(Object val);
|
||||
boolean Add_if_dupe_use_1st(Object key, Object val);
|
||||
void Add_if_dupe_use_nth(Object key, Object val);
|
||||
|
@ -27,6 +27,7 @@ class Hash_adp_noop implements Hash_adp {
|
||||
public Object Get_by_or_fail(Object key) {throw Err_.new_missing_key(Object_.Xto_str_strict_or_null_mark(key));}
|
||||
public void Add(Object key, Object val) {}
|
||||
public Hash_adp Add_and_more(Object key, Object val) {return this;}
|
||||
public Hash_adp Add_many_as_key_and_val(Object... ary) {return this;}
|
||||
public void Add_as_key_and_val(Object val) {}
|
||||
public void Add_if_dupe_use_nth(Object key, Object val) {}
|
||||
public boolean Add_if_dupe_use_1st(Object key, Object val) {return false;}
|
||||
|
@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx;
|
||||
import gplx.core.strings.*; import gplx.langs.gfs.*;
|
||||
public class Int_ {
|
||||
// -------- BASELIB_COPY --------
|
||||
public static final String Cls_val_name = "int";
|
||||
public static final Class<?> Cls_ref_type = Integer.class;
|
||||
|
||||
@ -27,6 +28,7 @@ public class Int_ {
|
||||
, Null = Int_.Min_value
|
||||
, Base1 = 1 // for super 1 lists / arrays; EX: PHP; [a, b, c]; [1] => a
|
||||
, Offset_1 = 1 // common symbol for + 1 after current pos; EX: String_.Mid(lhs + Offset_1, rhs)
|
||||
, Zero = 0
|
||||
;
|
||||
|
||||
public static int Cast(Object obj) {
|
||||
@ -37,6 +39,72 @@ public class Int_ {
|
||||
throw Err_.new_type_mismatch_w_exc(exc, int.class, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static String To_str(int v) {return new Integer(v).toString();}
|
||||
public static int Parse_or(String raw, int or) {
|
||||
// process args
|
||||
if (raw == null) return or;
|
||||
int raw_len = String_.Len(raw);
|
||||
if (raw_len == 0) return or;
|
||||
|
||||
// loop backwards from nth to 0th char
|
||||
int rv = 0, power_of_10 = 1;
|
||||
for (int idx = raw_len - 1; idx >= 0; idx--) {
|
||||
char cur = String_.CharAt(raw, idx);
|
||||
int digit = -1;
|
||||
switch (cur) {
|
||||
// numbers -> assign digit
|
||||
case '0': digit = 0; break; case '1': digit = 1; break; case '2': digit = 2; break; case '3': digit = 3; break; case '4': digit = 4; break;
|
||||
case '5': digit = 5; break; case '6': digit = 6; break; case '7': digit = 7; break; case '8': digit = 8; break; case '9': digit = 9; break;
|
||||
|
||||
// negative sign
|
||||
case '-':
|
||||
if (idx != 0) { // invalid if not 1st
|
||||
return or;
|
||||
}
|
||||
else { // is first; multiply by -1
|
||||
rv *= -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// anything else
|
||||
default:
|
||||
return or;
|
||||
}
|
||||
rv += (digit * power_of_10);
|
||||
power_of_10 *= 10;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static int[] Log10Ary = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, Int_.Max_value};
|
||||
public static int Log10AryLen = 11;
|
||||
public static int Log10(int v) {
|
||||
if (v == 0) return 0;
|
||||
int sign = 1;
|
||||
if (v < 0) {
|
||||
if (v == Int_.Min_value) return -9; // NOTE: Int_.Min_value * -1 = Int_.Min_value
|
||||
v *= -1;
|
||||
sign = -1;
|
||||
}
|
||||
int rv = Log10AryLen - 2; // rv will only happen when v == Int_.Max_value
|
||||
int bgn = 0;
|
||||
if (v > 1000) { // optimization to reduce number of ops to < 5
|
||||
bgn = 3;
|
||||
if (v > 1000000) bgn = 6;
|
||||
}
|
||||
for (int i = bgn; i < Log10AryLen; i++) {
|
||||
if (v < Log10Ary[i]) {rv = i - 1; break;}
|
||||
}
|
||||
return rv * sign;
|
||||
}
|
||||
|
||||
public static int DigitCount(int v) {
|
||||
int log10 = Log10(v);
|
||||
return v > -1 ? log10 + 1 : log10 * -1 + 2;
|
||||
}
|
||||
|
||||
// -------- TO_MIGRATE --------
|
||||
public static int Cast_or(Object obj, int or) {
|
||||
try {
|
||||
return (Integer)obj;
|
||||
@ -55,23 +123,7 @@ public class Int_ {
|
||||
}
|
||||
|
||||
public static int Parse(String raw) {try {return Integer.parseInt(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, int.class, raw);}}
|
||||
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 By_double(double v) {return (int)v;}
|
||||
public static int By_hex_bry(byte[] src) {return By_hex_bry(src, 0, src.length);}
|
||||
@ -99,7 +151,6 @@ public class Int_ {
|
||||
}
|
||||
|
||||
public static byte[] To_bry(int v) {return Bry_.new_a7(To_str(v));}
|
||||
public static String To_str(int v) {return new Integer(v).toString();}
|
||||
public static String To_str_fmt(int v, String fmt) {return new java.text.DecimalFormat(fmt).format(v);}
|
||||
public static String To_str_pad_bgn_space(int val, int reqd_len) {return To_str_pad(val, reqd_len, Bool_.Y, Byte_ascii.Space);} // EX: 1, 3 returns " 1"
|
||||
public static String To_str_pad_bgn_zero (int val, int reqd_len) {return To_str_pad(val, reqd_len, Bool_.Y, Byte_ascii.Num_0);} // EX: 1, 3 returns "001"
|
||||
@ -190,31 +241,4 @@ public class Int_ {
|
||||
float product = ((float)v * multiplier); // WORKAROUND (DotNet): (int)((float)v * multiplier) returns 0 for 100 and .01f
|
||||
return (int)product;
|
||||
}
|
||||
|
||||
public static int[] Log10Ary = new int[] {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, Int_.Max_value};
|
||||
public static int Log10AryLen = 11;
|
||||
public static int Log10(int v) {
|
||||
if (v == 0) return 0;
|
||||
int sign = 1;
|
||||
if (v < 0) {
|
||||
if (v == Int_.Min_value) return -9; // NOTE: Int_.Min_value * -1 = Int_.Min_value
|
||||
v *= -1;
|
||||
sign = -1;
|
||||
}
|
||||
int rv = Log10AryLen - 2; // rv will only happen when v == Int_.Max_value
|
||||
int bgn = 0;
|
||||
if (v > 1000) { // optimization to reduce number of ops to < 5
|
||||
bgn = 3;
|
||||
if (v > 1000000) bgn = 6;
|
||||
}
|
||||
for (int i = bgn; i < Log10AryLen; i++) {
|
||||
if (v < Log10Ary[i]) {rv = i - 1; break;}
|
||||
}
|
||||
return rv * sign;
|
||||
}
|
||||
|
||||
public static int DigitCount(int v) {
|
||||
int log10 = Log10(v);
|
||||
return v > -1 ? log10 + 1 : log10 * -1 + 2;
|
||||
}
|
||||
}
|
||||
|
@ -25,72 +25,10 @@ public class Int__tst {
|
||||
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_.To_str_pad_bgn_zero(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_.To_str_fmt(v, "#,###"));}
|
||||
@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_.Max_value, 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_.Min_value, -9);
|
||||
tst_Log10(Int_.Min_value + 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_.To_str(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_.Max_value, 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_.By_hex_bry(Bry_.new_a7(raw)));}
|
||||
|
@ -25,6 +25,15 @@ public class Int_ary_ {//RF:DATE:2017-10-09
|
||||
trg[i] = src[i];
|
||||
}
|
||||
|
||||
public static int[] Mid(int[] src, int bgn, int end) {
|
||||
int len = end - bgn + 1;
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = src[i + bgn];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static String To_str(String spr, int... ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
int len = ary.length;
|
||||
|
@ -14,7 +14,8 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
import gplx.core.primitives.*; import gplx.core.ios.*; /*IoItmFil, IoItmDir..*/ import gplx.core.ios.streams.*; import gplx.core.ios.loaders.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.core.ios.*; /*IoItmFil, IoItmDir..*/ import gplx.core.ios.streams.*; import gplx.core.ios.loaders.*; import gplx.core.ios.atrs.*;
|
||||
public class Io_mgr implements Gfo_evt_mgr_owner { // exists primarily to gather all cmds under gplx namespace; otherwise need to use gplx.core.ios whenever copying/deleting file
|
||||
public Io_mgr() {evt_mgr = new Gfo_evt_mgr(this);}
|
||||
public Gfo_evt_mgr Evt_mgr() {return evt_mgr;} private final Gfo_evt_mgr evt_mgr;
|
||||
@ -57,6 +58,7 @@ public class Io_mgr implements Gfo_evt_mgr_owner { // exists primarily to gather
|
||||
}
|
||||
public Io_url[] QueryDir_fils(Io_url dir) {return QueryDir_args(dir).ExecAsUrlAry();}
|
||||
public IoEngine_xrg_queryDir QueryDir_args(Io_url dir) {return IoEngine_xrg_queryDir.new_(dir);}
|
||||
public Io_itm_atr_req Query_itm_atrs(Io_url url, Io_itm_atr_req req) {return IoEnginePool.Instance.Get_by(url.Info().EngineKey()).Query_itm_atrs(url, req);}
|
||||
public void DeleteDirSubs(Io_url url) {IoEngine_xrg_deleteDir.new_(url).Exec();}
|
||||
public IoEngine_xrg_deleteDir DeleteDir_cmd(Io_url url) {return IoEngine_xrg_deleteDir.new_(url);}
|
||||
public void DeleteDirDeep(Io_url url) {IoEngine_xrg_deleteDir.new_(url).Recur_().Exec();}
|
||||
@ -149,11 +151,13 @@ public class Io_mgr implements Gfo_evt_mgr_owner { // exists primarily to gather
|
||||
}
|
||||
public boolean DownloadFil(String src, Io_url trg) {return IoEngine_xrg_downloadFil.new_(src, trg).Exec();}
|
||||
public IoEngine_xrg_downloadFil DownloadFil_args(String src, Io_url trg) {return IoEngine_xrg_downloadFil.new_(src, trg);}
|
||||
public boolean Query_read_only(Io_url url, int read_only_type) {return IoEngineUtl.Query_read_only(IoEnginePool.Instance.Get_by(url.Info().EngineKey()), url, read_only_type);}
|
||||
public static final Io_mgr Instance = new Io_mgr();
|
||||
public static final int Len_kb = 1024, Len_mb = 1048576, Len_gb = 1073741824, Len_gb_2 = 2147483647;
|
||||
public static final long Len_mb_long = Len_mb;
|
||||
public static final long Len_null = -1;
|
||||
public static final String Evt__fil_created = "fil_created";
|
||||
public static final int Read_only__basic__file = 1, Read_only__basic__file_and_dirs = 2, Read_only__perms__file = 3;
|
||||
}
|
||||
class Io_mgr_ {
|
||||
public static int Delete_dir_empty(Io_url url) {
|
||||
|
@ -24,7 +24,9 @@ public class Io_url__tst {
|
||||
class Io_url__fxt {
|
||||
public void Clear() {Io_mgr.Instance.InitEngine_mem();}
|
||||
public void Test__New__http_or_null(boolean os_is_wnt, String raw, String expd) {
|
||||
int curTid = Op_sys.Cur().Tid();
|
||||
Op_sys.Cur_(os_is_wnt ? Op_sys.Tid_wnt : Op_sys.Tid_lnx);
|
||||
Gftest.Eq__obj_or_null(expd, Io_url_.New__http_or_null(raw));
|
||||
Op_sys.Cur_(curTid);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class Long_ {
|
||||
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_.Min_value);
|
||||
tmp = Char_.To_digit_or(String_.CharAt(raw, i - 1), Int_.Min_value);
|
||||
if (tmp == Int_.Min_value) return or;
|
||||
rv += (tmp * factor);
|
||||
factor *= 10;
|
||||
|
@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx;
|
||||
public class Math_ {
|
||||
public static double Pow(double val, double exponent) {return java.lang.Math.pow(val, exponent);}
|
||||
public static int Pow_int(int val, int exponent) {return (int)java.lang.Math.pow(val, exponent);}
|
||||
public static double Pi = java.lang.Math.PI;
|
||||
public static double E = java.lang.Math.E;
|
||||
public static int Ceil_as_int(double v) {return (int)Ceil(v);}
|
||||
|
@ -21,14 +21,14 @@ public class Ordered_hash_base extends Hash_adp_base implements Ordered_hash, Gf
|
||||
@Override protected void Add_base(Object key, Object val) {
|
||||
super.Add_base(key, val);
|
||||
ordered.Add(val);
|
||||
AssertCounts();
|
||||
AssertCounts("Add_base", key);
|
||||
}
|
||||
@Override public void Del(Object key) {
|
||||
if (!this.Has_base(key)) return;
|
||||
Object val = this.Fetch_base(key);
|
||||
this.Del_base(key);
|
||||
ordered.Del(val);
|
||||
AssertCounts();
|
||||
AssertCounts("Del", key);
|
||||
}
|
||||
protected Object Get_at_base(int index) {return ordered.Get_at(index);}
|
||||
protected int IndexOf_base(Object obj) {return ordered.Idx_of(obj);}
|
||||
@ -50,7 +50,7 @@ public class Ordered_hash_base extends Hash_adp_base implements Ordered_hash, Gf
|
||||
if (locked) Lock_fail();
|
||||
super.Add_base(key, val);
|
||||
ordered.Add_at(i, val);
|
||||
AssertCounts();
|
||||
AssertCounts("Add_at", key);
|
||||
}
|
||||
public Ordered_hash Add_many_str(String... ary) {
|
||||
int ary_len = ary.length;
|
||||
@ -61,8 +61,8 @@ public class Ordered_hash_base extends Hash_adp_base implements Ordered_hash, Gf
|
||||
}
|
||||
return this;
|
||||
}
|
||||
void AssertCounts() {
|
||||
if (super.Count() != ordered.Count()) throw Err_.new_wo_type("counts do not match", "hash", super.Count(), "list", ordered.Count());
|
||||
private void AssertCounts(String proc, Object key) {
|
||||
if (super.Count() != ordered.Count()) throw Err_.new_wo_type("counts do not match; same key is either added twice, or delete failed", "proc", proc, "key", Object_.Xto_str_strict_or_null_mark(key), "hash", super.Count(), "list", ordered.Count());
|
||||
}
|
||||
public void Resize_bounds(int i) {if (locked) Lock_fail(); ordered.Resize_bounds(i);}
|
||||
public void Lock() {locked = true;} private boolean locked = false;
|
||||
|
@ -17,8 +17,17 @@ package gplx;
|
||||
import java.lang.*;
|
||||
import gplx.core.strings.*; import gplx.langs.gfs.*; import gplx.core.envs.*;
|
||||
public class String_ {
|
||||
// -------- BASELIB_COPY --------
|
||||
public static final Class<?> Cls_ref_type = String.class;
|
||||
public static final String Cls_val_name = "str" + "ing";
|
||||
public static final int Find_none = -1, Pos_neg1 = -1;
|
||||
public static final String Empty = "", Null_mark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n", Nl = "\n";
|
||||
|
||||
public static boolean Eq(String lhs, String rhs) {return lhs == null ? rhs == null : lhs.equals(rhs);}
|
||||
public static int Len(String s) {return s.length();}
|
||||
public static char CharAt(String s, int i) {return s.charAt(i);}
|
||||
|
||||
public static String new_u8(byte[] v) {return v == null ? null : new_u8(v, 0, v.length);}
|
||||
public static String new_u8(byte[] v, int bgn, int end) {
|
||||
try {
|
||||
return v == null
|
||||
@ -28,10 +37,62 @@ public class String_ {
|
||||
catch (Exception e) {Err_.Noop(e); throw Err_.new_("core", "unsupported encoding", "bgn", bgn, "end", end);}
|
||||
}
|
||||
|
||||
public static final Class<?> Cls_ref_type = String.class;
|
||||
public static final String Cls_val_name = "str" + "ing";
|
||||
public static final int Find_none = -1, Pos_neg1 = -1;
|
||||
public static final String Null = null, Empty = "", Null_mark = "<<NULL>>", Tab = "\t", Lf = "\n", CrLf = "\r\n";
|
||||
// use C# flavor ("a {0}") rather than Java format ("a %s"); also: (a) don't fail on format errors; (b) escape brackets by doubling
|
||||
private static final char FORMAT_ITM_LHS = '{', FORMAT_ITM_RHS = '}';
|
||||
public static String Format(String fmt, Object... args) {
|
||||
// method vars
|
||||
int args_len = Array_.Len_obj(args);
|
||||
if (args_len == 0) return fmt; // nothing to format
|
||||
int fmt_len = Len(fmt);
|
||||
|
||||
// loop vars
|
||||
int pos = 0; String arg_idx_str = ""; boolean inside_brackets = false;
|
||||
String_bldr bfr = String_bldr_.new_();
|
||||
while (pos < fmt_len) { // loop over every char; NOTE: UT8-SAFE b/c only checking for "{"; "}"
|
||||
char c = CharAt(fmt, pos);
|
||||
if (inside_brackets) {
|
||||
if (c == FORMAT_ITM_LHS) { // first FORMAT_ITM_LHS is fake; add FORMAT_ITM_LHS and whatever is in arg_idx_str
|
||||
bfr.Add(FORMAT_ITM_LHS).Add(arg_idx_str);
|
||||
arg_idx_str = "";
|
||||
}
|
||||
else if (c == FORMAT_ITM_RHS) { // itm completed
|
||||
int args_idx = Int_.Parse_or(arg_idx_str, Int_.Min_value);
|
||||
String itm = args_idx != Int_.Min_value && Int_.Between(args_idx, 0, args_len - 1) // check (a) args_idx is num; (b) args_idx is in bounds
|
||||
? Object_.Xto_str_strict_or_empty(args[args_idx]) // valid; add itm
|
||||
: String_.Concat_any(FORMAT_ITM_LHS, arg_idx_str, FORMAT_ITM_RHS); // not valid; just add String
|
||||
bfr.Add(itm);
|
||||
inside_brackets = false;
|
||||
arg_idx_str = "";
|
||||
}
|
||||
else
|
||||
arg_idx_str += c;
|
||||
}
|
||||
else {
|
||||
if (c == FORMAT_ITM_LHS || c == FORMAT_ITM_RHS) {
|
||||
boolean pos_is_end = pos == fmt_len - 1;
|
||||
if (pos_is_end) // last char is "{" or "}" (and not inside_brackets); ignore and just ad
|
||||
bfr.Add(c);
|
||||
else {
|
||||
char next = CharAt(fmt, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
bfr.Add(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
inside_brackets = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
bfr.Add(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (Len(arg_idx_str) > 0) // unclosed bracket; add FORMAT_ITM_LHS and whatever is in arg_idx_str; ex: "{0"
|
||||
bfr.Add(FORMAT_ITM_LHS).Add(arg_idx_str);
|
||||
return bfr.To_str();
|
||||
}
|
||||
|
||||
// -------- TO_MIGRATE --------
|
||||
public static String cast(Object v) {return (String)v;}
|
||||
public static String as_(Object obj) {return obj instanceof String ? (String)obj : null;}
|
||||
public static String new_a7(byte[] v) {return v == null ? null : new_a7(v, 0, v.length);}
|
||||
@ -43,7 +104,6 @@ public class String_ {
|
||||
}
|
||||
catch (Exception e) {throw Err_.new_exc(e, "core", "unsupported encoding");}
|
||||
}
|
||||
public static String new_u8(byte[] v) {return v == null ? null : new_u8(v, 0, v.length);}
|
||||
public static String new_u8__by_len(byte[] v, int bgn, int len) {
|
||||
int v_len = v.length;
|
||||
if (bgn + len > v_len) len = v_len - bgn;
|
||||
@ -111,7 +171,6 @@ public class String_ {
|
||||
} 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;
|
||||
@ -267,7 +326,6 @@ public class String_ {
|
||||
if (pos < 0 || pos >= String_.Len(s)) throw Err_.new_wo_type("String_.Insert failed; pos invalid", "pos", pos, "s", s, "toInsert", toInsert);
|
||||
return s.substring(0, pos) + toInsert + s.substring(pos);
|
||||
}
|
||||
public static String Format(String fmt, Object... args) {return Format_do(fmt, args);}
|
||||
public static String FormatOrEmptyStrIfNull(String fmt, Object arg) {return arg == null ? "" : Format(fmt, arg);}
|
||||
public static String Concat(char... ary) {return new String(ary);}
|
||||
public static String Concat(String s1, String s2, String s3) {return s1 + s2 + s3;}
|
||||
@ -381,57 +439,6 @@ public class String_ {
|
||||
public static String[] SplitLines_any(String s) {return Split_do(s, Op_sys.Lnx.Nl_str(), true);}
|
||||
public static String[] Split_lang(String s, char c) {return s.split(Character.toString(c));}
|
||||
|
||||
static String Format_do(String s, Object[] ary) {
|
||||
int aryLength = Array_.Len_obj(ary); if (aryLength == 0) return s; // nothing to format
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
char bracketBgn = '{', bracketEnd = '}';
|
||||
String aryVal = null; char c, next;
|
||||
int pos = 0; int textLength = Len(s); String numberStr = ""; boolean bracketsOn = false;
|
||||
while (true) {
|
||||
if (pos == textLength) break;
|
||||
c = CharAt(s, pos);
|
||||
if (bracketsOn) { // mode=bracketsOn
|
||||
if (c == bracketBgn) { // first bracketBgn is fake; add bracketBgn and whatever is in numberStr
|
||||
sb.Add(bracketBgn).Add(numberStr);
|
||||
numberStr = "";
|
||||
}
|
||||
else if (c == bracketEnd) {
|
||||
int aryIdx = Int_.Parse_or(numberStr, Int_.Min_value);
|
||||
if (aryIdx != Int_.Min_value && Int_.Between(aryIdx, 0, aryLength - 1)) // check (a) aryIdx is num; (b) aryIdx is in bounds
|
||||
aryVal = Object_.Xto_str_strict_or_empty(ary[aryIdx]);
|
||||
else
|
||||
aryVal = String_.Concat_any(bracketBgn, numberStr, bracketEnd); // not valid, just add String
|
||||
sb.Add(aryVal);
|
||||
bracketsOn = false;
|
||||
numberStr = "";
|
||||
}
|
||||
else // char=anythingElse
|
||||
numberStr += c;
|
||||
}
|
||||
else { // mode=bracketsOff
|
||||
if (c == bracketBgn || c == bracketEnd) {
|
||||
boolean isEnd = pos == textLength - 1;
|
||||
if (isEnd)
|
||||
sb.Add(c);
|
||||
else {
|
||||
next = CharAt(s, pos + 1);
|
||||
if (next == c) { // "{{" or "}}": escape by doubling
|
||||
sb.Add(c);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
bracketsOn = true;
|
||||
}
|
||||
}
|
||||
else // char=anythingElse
|
||||
sb.Add(c);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (Len(numberStr) > 0) // unclosed bracket; add bracketBgn and whatever is in numberStr; ex: "{0"
|
||||
sb.Add(bracketBgn).Add(numberStr);
|
||||
return sb.To_str();
|
||||
}
|
||||
static String[] Split_do(String s, String spr, boolean skipChar13) {
|
||||
if (String_.Eq(s, "") // "".Split('a') return array with one member: ""
|
||||
|| String_.Eq(spr, "")) // "a".Split('\0') returns array with one member: "a"
|
||||
|
@ -16,11 +16,6 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
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");
|
||||
@ -120,20 +115,6 @@ public class String__tst {
|
||||
@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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -14,6 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
|
||||
public class Type_ {//RF:2017-10-08
|
||||
public static Class<?> Type_by_obj(Object o) {return o.getClass();}
|
||||
public static Class<?> Type_by_primitive(Object o) {
|
||||
@ -45,6 +46,11 @@ public class Type_ {//RF:2017-10-08
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
public static String SimpleName_by_obj(Object obj) {return obj == null ? String_.Null_mark : SimpleName(Type_by_obj(obj));}
|
||||
public static String SimpleName(Class<?> type) {
|
||||
return type.getSimpleName();
|
||||
}
|
||||
|
||||
public static boolean Is_array(Class<?> t) {
|
||||
return t.isArray();
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx;
|
||||
public class UsrMsgWkr_test implements UsrMsgWkr {
|
||||
public class UsrMsgWkr_mock implements UsrMsgWkr {
|
||||
public void ExecUsrMsg(int type, UsrMsg m) {
|
||||
msgs.Add(m);
|
||||
}
|
||||
@ -25,8 +25,8 @@ public class UsrMsgWkr_test implements UsrMsgWkr {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static UsrMsgWkr_test RegAll(UsrDlg dlg) {
|
||||
UsrMsgWkr_test wkr = new UsrMsgWkr_test();
|
||||
public static UsrMsgWkr_mock RegAll(UsrDlg dlg) {
|
||||
UsrMsgWkr_mock wkr = new UsrMsgWkr_mock();
|
||||
dlg.Reg(UsrMsgWkr_.Type_Note, wkr);
|
||||
dlg.Reg(UsrMsgWkr_.Type_Stop, wkr);
|
||||
dlg.Reg(UsrMsgWkr_.Type_Warn, wkr);
|
@ -33,6 +33,9 @@ public class Bitmask_ {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int Set_or_add(int val, int flag) {
|
||||
return val == 0 ? flag : val | flag;
|
||||
}
|
||||
public static boolean Has_byte(byte val, byte find) {return find == (val & find);}
|
||||
public static byte Add_byte(byte flag, byte itm) {return (byte)(flag | itm);}
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ public class Bry_fmtr {
|
||||
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;
|
||||
boolean dirty_disable = true;
|
||||
List_adp list = List_adp_.New();
|
||||
fmt_args_exist = false;
|
||||
while (true) {
|
||||
@ -180,6 +181,7 @@ public class Bry_fmtr {
|
||||
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
|
||||
dirty_disable = false; // eval allows args to retrigger compiles; this is probably not used, but just in case, do not disable dirty; TEST: Tfds.Eq("012~{<>3<>}4", fmtr.Bld_str_many("1"));
|
||||
fmt_pos = Compile_eval_cmd(fmt, fmt_len, eval_lhs_bgn, list);
|
||||
continue;
|
||||
}
|
||||
@ -210,6 +212,8 @@ public class Bry_fmtr {
|
||||
if (trg_pos > 0) {list.Add(Bry_fmtr_itm.dat_(trg_bry, trg_pos)); trg_pos = 0;}
|
||||
itms = (Bry_fmtr_itm[])list.To_ary(Bry_fmtr_itm.class);
|
||||
itms_len = itms.length;
|
||||
if (dirty_disable)
|
||||
dirty = false; // ISSUE#:575; DATE:2019-09-16
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
157
100_core/src/gplx/core/caches/Lru_cache.java
Normal file
157
100_core/src/gplx/core/caches/Lru_cache.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
public class Lru_cache {
|
||||
private final Hash_adp map = Hash_adp_.New();
|
||||
private Lru_node head, tail;
|
||||
private long cur, min, max, evicts;
|
||||
public Lru_cache(boolean auto_reg, String key, long min, long max) {
|
||||
this.key = key;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
if (auto_reg) Lru_cache_root.Instance.Add(this);
|
||||
}
|
||||
public String Key() {return key;} private final String key;
|
||||
public long Evicts() {return evicts;}
|
||||
public long Cur() {return cur;}
|
||||
public void Min_max_(long min, long max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
public Object Get_or_null(Object key) {
|
||||
Lru_node nde = (Lru_node)map.Get_by(key);
|
||||
if (nde == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Del_node_from_linked_list(nde);
|
||||
Add_to_tail(nde);
|
||||
|
||||
return nde.Val();
|
||||
}
|
||||
public void Set(Object key, Object val, long size) {
|
||||
Lru_node nde = (Lru_node)map.Get_by(key);
|
||||
if (nde != null) {
|
||||
nde.Val_(val);
|
||||
|
||||
Del_node_from_linked_list(nde);
|
||||
Add_to_tail(nde);
|
||||
}
|
||||
else {
|
||||
this.Clear_min(size);
|
||||
|
||||
nde = new Lru_node(key, val, size);
|
||||
Add_to_tail(nde);
|
||||
map.Add(key, nde);
|
||||
cur += size;
|
||||
}
|
||||
}
|
||||
public void Del(Object key) {
|
||||
Lru_node nde = (Lru_node)map.Get_by(key);
|
||||
if (nde != null) {
|
||||
Del_node_from_this(nde);
|
||||
}
|
||||
}
|
||||
public void Clear_all() {
|
||||
synchronized (map) {
|
||||
map.Clear();
|
||||
head = null;
|
||||
tail = null;
|
||||
cur = 0;
|
||||
}
|
||||
}
|
||||
public void Clear_min(long size) {
|
||||
synchronized (map) {
|
||||
long threshold = min >= 0 ? min : max;
|
||||
while (cur + size > threshold) {
|
||||
Del_node_from_this(head);
|
||||
evicts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Del_node_from_this(Lru_node nde) {
|
||||
synchronized (map) {
|
||||
map.Del(nde.Key());
|
||||
cur -= nde.Size();
|
||||
Del_node_from_linked_list(nde);
|
||||
}
|
||||
}
|
||||
private void Del_node_from_linked_list(Lru_node nde) {
|
||||
synchronized (map) {
|
||||
if (nde.Prv() == null)
|
||||
head = nde.Nxt();
|
||||
else
|
||||
nde.Prv().Nxt_(nde.Nxt());
|
||||
|
||||
if (nde.Nxt() == null)
|
||||
tail = nde.Prv();
|
||||
else
|
||||
nde.Nxt().Prv_(nde.Prv());
|
||||
}
|
||||
}
|
||||
private void Add_to_tail(Lru_node nde) {
|
||||
synchronized (map) {
|
||||
if (tail != null)
|
||||
tail.Nxt_(nde);
|
||||
|
||||
nde.Prv_(tail);
|
||||
nde.Nxt_(null);
|
||||
tail = nde;
|
||||
|
||||
if (head == null)
|
||||
head = tail;
|
||||
}
|
||||
}
|
||||
public void To_str(Bry_bfr bfr, boolean grps_only_or_both) {
|
||||
bfr.Add_str_a7("g");
|
||||
bfr.Add_byte_pipe().Add_str_u8(key);
|
||||
bfr.Add_byte_pipe().Add_long_variable(cur);
|
||||
bfr.Add_byte_pipe().Add_long_variable(min);
|
||||
bfr.Add_byte_pipe().Add_long_variable(max);
|
||||
bfr.Add_byte_nl();
|
||||
if (grps_only_or_both) {
|
||||
Lru_node nde = head;
|
||||
while (nde != null) {
|
||||
nde.To_str(bfr);
|
||||
nde = nde.Nxt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Lru_node {
|
||||
private final Object key;
|
||||
private Object val;
|
||||
private final long size;
|
||||
private Lru_node prv;
|
||||
private Lru_node nxt;
|
||||
|
||||
public Lru_node(Object key, Object val, long size) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
this.size = size;
|
||||
}
|
||||
public Object Key() {return key;}
|
||||
public Object Val() {return val;} public void Val_(Object v) {this.val = v;}
|
||||
public long Size() {return size;}
|
||||
public Lru_node Prv() {return prv;} public void Prv_(Lru_node v) {this.prv = v;}
|
||||
public Lru_node Nxt() {return nxt;} public void Nxt_(Lru_node v) {this.nxt = v;}
|
||||
public void To_str(Bry_bfr bfr) {
|
||||
bfr.Add_str_a7("i");
|
||||
bfr.Add_byte_pipe().Add_str_u8(Object_.Xto_str_strict_or_null_mark(key));
|
||||
bfr.Add_byte_pipe().Add_long_variable(size);
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
}
|
50
100_core/src/gplx/core/caches/Lru_cache_root.java
Normal file
50
100_core/src/gplx/core/caches/Lru_cache_root.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
public class Lru_cache_root {
|
||||
private final Ordered_hash hash = Ordered_hash_.New();
|
||||
public Lru_cache Get_by_key(String key) {return (Lru_cache)hash.Get_by(key);}
|
||||
public void Add(Lru_cache grp) {
|
||||
hash.Add(grp.Key(), grp);
|
||||
}
|
||||
public void Del(String key) {
|
||||
hash.Del(key);
|
||||
}
|
||||
public void Clear_caches_all() {
|
||||
int len = hash.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Lru_cache grp = (Lru_cache)hash.Get_at(i);
|
||||
grp.Clear_all();
|
||||
}
|
||||
}
|
||||
public void Clear_caches_min() {
|
||||
int len = hash.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Lru_cache grp = (Lru_cache)hash.Get_at(i);
|
||||
grp.Clear_min(0);
|
||||
}
|
||||
}
|
||||
public String Print_contents(boolean grps_only_or_both) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
int len = hash.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Lru_cache grp = (Lru_cache)hash.Get_at(i);
|
||||
grp.To_str(bfr, grps_only_or_both);
|
||||
}
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
public static final Lru_cache_root Instance = new Lru_cache_root();
|
||||
}
|
104
100_core/src/gplx/core/caches/Lru_cache_tst.java
Normal file
104
100_core/src/gplx/core/caches/Lru_cache_tst.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.caches; import gplx.*; import gplx.core.*;
|
||||
import org.junit.*; import gplx.core.tests.*;
|
||||
public class Lru_cache_tst {
|
||||
private final Lru_cache_fxt fxt = new Lru_cache_fxt();
|
||||
@Test public void Get_one() {
|
||||
fxt.Exec__set("a", 5);
|
||||
fxt.Test__get_y("a");
|
||||
}
|
||||
@Test public void Pop_one() {
|
||||
fxt.Exec__set("a", 10);
|
||||
fxt.Exec__set("b", 10);
|
||||
fxt.Test__get_n("a");
|
||||
fxt.Test__get_y("b");
|
||||
}
|
||||
@Test public void Add_many() {
|
||||
fxt.Exec__set("a", 4);
|
||||
fxt.Exec__set("b", 3);
|
||||
fxt.Exec__set("c", 2);
|
||||
fxt.Exec__set("d", 1);
|
||||
fxt.Test__get_y("a", "b", "c", "d");
|
||||
}
|
||||
@Test public void Pop_many() {
|
||||
fxt.Exec__set("a", 4);
|
||||
fxt.Exec__set("b", 3);
|
||||
fxt.Exec__set("c", 2);
|
||||
fxt.Exec__set("d", 1);
|
||||
fxt.Exec__set("e", 6);
|
||||
fxt.Test__get_y("c", "d", "e");
|
||||
fxt.Test__get_n("a", "b");
|
||||
}
|
||||
@Test public void Set_repeatedly() {
|
||||
fxt.Exec__set("a", "a1", 10);
|
||||
fxt.Exec__set("a", "a2", 10);
|
||||
fxt.Exec__set("a", "a3", 10);
|
||||
fxt.Test__get_val("a", "a3");
|
||||
}
|
||||
@Test public void Set_bumps_priority() {
|
||||
fxt.Exec__set("a", 2);
|
||||
fxt.Exec__set("b", 3);
|
||||
fxt.Exec__set("c", 2);
|
||||
fxt.Exec__set("a", 2);
|
||||
fxt.Exec__set("d", 7);
|
||||
fxt.Test__get_y("a", "d");
|
||||
fxt.Test__get_n("b", "c");
|
||||
}
|
||||
@Test public void Del() {
|
||||
fxt.Exec__set("a", 2);
|
||||
fxt.Exec__set("b", 2);
|
||||
fxt.Exec__del("b");
|
||||
fxt.Test__get_y("a");
|
||||
fxt.Test__get_n("b");
|
||||
}
|
||||
@Test public void Clear() {
|
||||
fxt.Exec__set("a", 2);
|
||||
fxt.Exec__set("b", 2);
|
||||
fxt.Exec__clear();
|
||||
fxt.Test__get_n("a", "b");
|
||||
}
|
||||
}
|
||||
class Lru_cache_fxt {
|
||||
private final Lru_cache cache = new Lru_cache(Bool_.N, "test", -1, 10);
|
||||
public void Exec__set(String key, long size) {
|
||||
cache.Set(key, key, size);
|
||||
}
|
||||
public void Exec__set(String key, String val, long size) {
|
||||
cache.Set(key, val, size);
|
||||
}
|
||||
public void Exec__del(String key) {
|
||||
cache.Del(key);
|
||||
}
|
||||
public void Exec__clear() {
|
||||
cache.Clear_all();
|
||||
}
|
||||
public void Test__get_y(String... keys) {
|
||||
for (String key : keys)
|
||||
Test__get(key, key);
|
||||
}
|
||||
public void Test__get_n(String... keys) {
|
||||
for (String key : keys)
|
||||
Test__get(key, null);
|
||||
}
|
||||
public void Test__get_val(String key, String val) {
|
||||
Test__get(key, val);
|
||||
}
|
||||
private void Test__get(String key, String expd) {
|
||||
Object actl = cache.Get_or_null(key);
|
||||
Gftest.Eq__obj_or_null(expd, actl);
|
||||
}
|
||||
}
|
@ -128,18 +128,22 @@ public class Hex_utl_ {
|
||||
}
|
||||
public static boolean Is_hex_many(byte... ary) {
|
||||
for (byte itm : ary) {
|
||||
if (!Is_hex(itm))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static boolean Is_hex(byte itm) {
|
||||
switch (itm) {
|
||||
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
|
||||
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
|
||||
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E: case Byte_ascii.Ltr_F:
|
||||
case Byte_ascii.Ltr_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:
|
||||
break;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static int To_int(char c) {
|
||||
switch (c) {
|
||||
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4;
|
||||
|
34
100_core/src/gplx/core/encoders/Oct_utl_.java
Normal file
34
100_core/src/gplx/core/encoders/Oct_utl_.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.encoders; import gplx.*; import gplx.core.*;
|
||||
public class Oct_utl_ {
|
||||
public static int Parse_or(byte[] src, int or) {return Parse_or(src, 0, src.length, or);}
|
||||
public static int Parse_or(byte[] src, int bgn, int end, int or) {
|
||||
int rv = 0; int factor = 1;
|
||||
byte b = Byte_.Max_value_127;
|
||||
for (int i = end - 1; i >= bgn; i--) {
|
||||
switch (src[i]) {
|
||||
case Byte_ascii.Num_0: b = 0; break; case Byte_ascii.Num_1: b = 1; break; case Byte_ascii.Num_2: b = 2; break; case Byte_ascii.Num_3: b = 3; break; case Byte_ascii.Num_4: b = 4; break;
|
||||
case Byte_ascii.Num_5: b = 5; break; case Byte_ascii.Num_6: b = 6; break; case Byte_ascii.Num_7: b = 7; break;
|
||||
default: b = Byte_.Max_value_127; break;
|
||||
}
|
||||
if (b == Byte_.Max_value_127) return or;
|
||||
rv += b * factor;
|
||||
factor *= 8;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
@ -132,4 +132,13 @@ public class Utf16_ {
|
||||
else if (c < 65536) return 3; // 1 << 16
|
||||
else throw Err_.new_wo_type("UTF-16 int must be between 0 and 65536", "char", c);
|
||||
}
|
||||
public static final int // REF: https://en.wikipedia.org/wiki/Universal_Character_Set_characters
|
||||
Surrogate_hi_bgn = 0xD800 // 55,296: Surrogate high start
|
||||
, Surrogate_hi_end = 0xDBFF // 56,319: Surrogate high end
|
||||
, Surrogate_lo_bgn = 0xDC00 // 56,320: Surrogate low start
|
||||
, Surrogate_lo_end = 0xDFFF // 57,343: Surrogate low end
|
||||
, Surrogate_cp_bgn = 0x010000 // 65,536: Surrogate codepoint start
|
||||
, Surrogate_cp_end = 0x10FFFF // 1,114,111: Surrogate codepoint end
|
||||
, Surrogate_range = 0x400 // 1,024: Surrogate range (end - start) for high / low
|
||||
;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.consoles.*; import gplx.core.criterias.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
import gplx.core.ios.streams.*; import gplx.core.ios.atrs.*;
|
||||
public interface IoEngine {
|
||||
String Key();
|
||||
boolean ExistsFil_api(Io_url url);
|
||||
@ -32,6 +32,7 @@ public interface IoEngine {
|
||||
void XferFil(IoEngine_xrg_xferFil args);
|
||||
void RecycleFil(IoEngine_xrg_recycleFil xrg);
|
||||
boolean Truncate_fil(Io_url url, long size);
|
||||
Io_itm_atr_req Query_itm_atrs(Io_url url, Io_itm_atr_req req);
|
||||
|
||||
boolean ExistsDir(Io_url url);
|
||||
void CreateDir(Io_url url); // creates all folder levels (EX: C:\a\b\c\ will create C:\a\ and C:\a\b\). will not fail if called on already existing folders.
|
||||
@ -47,108 +48,3 @@ public interface IoEngine {
|
||||
boolean DownloadFil(IoEngine_xrg_downloadFil xrg);
|
||||
Io_stream_rdr DownloadFil_as_rdr(IoEngine_xrg_downloadFil xrg);
|
||||
}
|
||||
class IoEngineUtl {
|
||||
public int BufferLength() {return bufferLength;} public void BufferLength_set(int v) {bufferLength = v;} int bufferLength = 4096; // 0x1000
|
||||
public void DeleteRecycleGplx(IoEngine engine, IoEngine_xrg_recycleFil xrg) {
|
||||
Io_url recycleUrl = xrg.RecycleUrl();
|
||||
if (recycleUrl.Type_fil())
|
||||
engine.MoveFil(IoEngine_xrg_xferFil.move_(xrg.Url(), recycleUrl).Overwrite_(false).ReadOnlyFails_(true));
|
||||
else
|
||||
engine.MoveDirDeep(IoEngine_xrg_xferDir.move_(xrg.Url(), recycleUrl).Overwrite_(false).ReadOnlyFails_(true));
|
||||
}
|
||||
public void DeleteDirDeep(IoEngine engine, Io_url dirUrl, IoEngine_xrg_deleteDir args) {
|
||||
Console_adp usrDlg = args.UsrDlg();
|
||||
IoItmDir dir = engine.QueryDir(dirUrl); if (!dir.Exists()) return;
|
||||
for (Object subDirObj : dir.SubDirs()) {
|
||||
IoItmDir subDir = (IoItmDir)subDirObj;
|
||||
if (!args.SubDirScanCrt().Matches(subDir)) continue;
|
||||
if (args.Recur()) DeleteDirDeep(engine, subDir.Url(), args);
|
||||
}
|
||||
for (Object subFilObj : dir.SubFils()) {
|
||||
IoItmFil subFil = (IoItmFil)subFilObj;
|
||||
if (!args.MatchCrt().Matches(subFil)) continue;
|
||||
Io_url subFilUrl = subFil.Url();
|
||||
try {engine.DeleteFil_api(IoEngine_xrg_deleteFil.new_(subFilUrl).ReadOnlyFails_(args.ReadOnlyFails()));}
|
||||
catch (Exception exc) {usrDlg.Write_fmt_w_nl(Err_.Message_lang(exc));}
|
||||
}
|
||||
// all subs deleted; now delete dir
|
||||
if (!args.MatchCrt().Matches(dir)) return;
|
||||
try {engine.DeleteDir(dir.Url());}
|
||||
catch (Exception exc) {usrDlg.Write_fmt_w_nl(Err_.Message_lang(exc));}
|
||||
}
|
||||
public void XferDir(IoEngine srcEngine, Io_url src, IoEngine trgEngine, Io_url trg, IoEngine_xrg_xferDir args) {
|
||||
trgEngine.CreateDir(trg);
|
||||
IoItmDir srcDir = QueryDirDeep(srcEngine, IoEngine_xrg_queryDir.new_(src).Recur_(false));
|
||||
for (Object subSrcObj : srcDir.SubDirs()) {
|
||||
IoItmDir subSrc = (IoItmDir)subSrcObj;
|
||||
if (!args.SubDirScanCrt().Matches(subSrc)) continue;
|
||||
if (!args.MatchCrt().Matches(subSrc)) continue;
|
||||
Io_url subTrg = trg.GenSubDir_nest(subSrc.Url().NameOnly()); //EX: C:\abc\def\ -> C:\123\ + def\
|
||||
if (args.Recur()) XferDir(srcEngine, subSrc.Url(), trgEngine, subTrg, args);
|
||||
}
|
||||
IoItmList srcFils = IoItmList.list_(src.Info().CaseSensitive());
|
||||
for (Object srcFilObj : srcDir.SubFils()) {
|
||||
IoItmFil srcFil = (IoItmFil)srcFilObj;
|
||||
if (args.MatchCrt().Matches(srcFil)) srcFils.Add(srcFil);
|
||||
}
|
||||
for (Object srcFilObj : srcFils) {
|
||||
IoItmFil srcFil = (IoItmFil)srcFilObj;
|
||||
Io_url srcFilPath = srcFil.Url();
|
||||
Io_url trgFilPath = trg.GenSubFil(srcFilPath.NameAndExt()); //EX: C:\abc\fil.txt -> C:\123\ + fil.txt
|
||||
IoEngine_xrg_xferFil xferArgs = args.Type_move() ? IoEngine_xrg_xferFil.move_(srcFilPath, trgFilPath).Overwrite_(args.Overwrite()) : IoEngine_xrg_xferFil.copy_(srcFilPath, trgFilPath).Overwrite_(args.Overwrite());
|
||||
XferFil(srcEngine, xferArgs);
|
||||
}
|
||||
if (args.Type_move()) srcEngine.DeleteDirDeep(IoEngine_xrg_deleteDir.new_(src).Recur_(args.Recur()).ReadOnlyFails_(args.ReadOnlyFails()));// this.DeleteDirDeep(srcEngine, src, IoEngine_xrg_deleteItm.new_(src).Recur_(args.Recur()).ReadOnlyIgnored_(args.ReadOnlyIgnored()));
|
||||
}
|
||||
public void XferFil(IoEngine srcEngine, IoEngine_xrg_xferFil args) {
|
||||
Io_url src = args.Src(), trg = args.Trg();
|
||||
if (String_.Eq(srcEngine.Key(), trg.Info().EngineKey())) {
|
||||
if (args.Type_move())
|
||||
srcEngine.MoveFil(args);
|
||||
else
|
||||
srcEngine.CopyFil(args);
|
||||
}
|
||||
else {
|
||||
TransferStream(src, trg);
|
||||
if (args.Type_move()) srcEngine.DeleteFil_api(IoEngine_xrg_deleteFil.new_(src));
|
||||
}
|
||||
}
|
||||
public IoItmDir QueryDirDeep(IoEngine engine, IoEngine_xrg_queryDir args) {
|
||||
IoItmDir rv = IoItmDir_.top_(args.Url());
|
||||
rv.Exists_set(QueryDirDeepCore(rv, args.Url(), engine, args.Recur(), args.SubDirScanCrt(), args.DirCrt(), args.FilCrt(), args.UsrDlg(), args.DirInclude()));
|
||||
return rv;
|
||||
}
|
||||
static boolean QueryDirDeepCore(IoItmDir ownerDir, Io_url url, IoEngine engine, boolean recur, Criteria subDirScanCrt, Criteria dirCrt, Criteria filCrt, Console_adp usrDlg, boolean dirInclude) {
|
||||
if (usrDlg.Canceled_chk()) return false;
|
||||
if (usrDlg.Enabled()) usrDlg.Write_tmp(String_.Concat("scan: ", url.Raw()));
|
||||
IoItmDir scanDir = engine.QueryDir(url);
|
||||
for (Object subDirObj : scanDir.SubDirs()) {
|
||||
IoItmDir subDir = (IoItmDir)subDirObj;
|
||||
if (!subDirScanCrt.Matches(subDir)) continue;
|
||||
if (dirCrt.Matches(subDir)) {
|
||||
ownerDir.SubDirs().Add(subDir); // NOTE: always add subDir; do not use dirCrt here, else its subFils will be added to non-existent subDir
|
||||
}
|
||||
if (recur)
|
||||
QueryDirDeepCore(subDir, subDir.Url(), engine, recur, subDirScanCrt, dirCrt, filCrt, usrDlg, dirInclude);
|
||||
}
|
||||
for (Object subFilObj : scanDir.SubFils()) {
|
||||
IoItmFil subFil = (IoItmFil)subFilObj;
|
||||
if (filCrt.Matches(subFil)) ownerDir.SubFils().Add(subFil);
|
||||
}
|
||||
return scanDir.Exists();
|
||||
}
|
||||
void TransferStream(Io_url src, Io_url trg) {
|
||||
IoStream srcStream = null;
|
||||
IoStream trgStream = null;
|
||||
try {
|
||||
srcStream = IoEnginePool.Instance.Get_by(src.Info().EngineKey()).OpenStreamRead(src);
|
||||
trgStream = IoEngine_xrg_openWrite.new_(trg).Exec();
|
||||
srcStream.Transfer(trgStream, bufferLength);
|
||||
}
|
||||
finally {
|
||||
if (srcStream != null) srcStream.Rls();
|
||||
if (trgStream != null) trgStream.Rls();
|
||||
}
|
||||
}
|
||||
public static IoEngineUtl new_() {return new IoEngineUtl();} IoEngineUtl() {}
|
||||
}
|
||||
|
175
100_core/src/gplx/core/ios/IoEngineUtl.java
Normal file
175
100_core/src/gplx/core/ios/IoEngineUtl.java
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.ios.streams.*; import gplx.core.ios.atrs.*;
|
||||
import gplx.core.consoles.*; import gplx.core.criterias.*; import gplx.core.caches.*;
|
||||
import gplx.core.envs.*;
|
||||
public class IoEngineUtl {
|
||||
public int BufferLength() {return bufferLength;} public void BufferLength_set(int v) {bufferLength = v;} int bufferLength = 4096; // 0x1000
|
||||
public void DeleteRecycleGplx(IoEngine engine, IoEngine_xrg_recycleFil xrg) {
|
||||
Io_url recycleUrl = xrg.RecycleUrl();
|
||||
if (recycleUrl.Type_fil())
|
||||
engine.MoveFil(IoEngine_xrg_xferFil.move_(xrg.Url(), recycleUrl).Overwrite_(false).ReadOnlyFails_(true));
|
||||
else
|
||||
engine.MoveDirDeep(IoEngine_xrg_xferDir.move_(xrg.Url(), recycleUrl).Overwrite_(false).ReadOnlyFails_(true));
|
||||
}
|
||||
public void DeleteDirDeep(IoEngine engine, Io_url dirUrl, IoEngine_xrg_deleteDir args) {
|
||||
Console_adp usrDlg = args.UsrDlg();
|
||||
IoItmDir dir = engine.QueryDir(dirUrl); if (!dir.Exists()) return;
|
||||
for (Object subDirObj : dir.SubDirs()) {
|
||||
IoItmDir subDir = (IoItmDir)subDirObj;
|
||||
if (!args.SubDirScanCrt().Matches(subDir)) continue;
|
||||
if (args.Recur()) DeleteDirDeep(engine, subDir.Url(), args);
|
||||
}
|
||||
for (Object subFilObj : dir.SubFils()) {
|
||||
IoItmFil subFil = (IoItmFil)subFilObj;
|
||||
if (!args.MatchCrt().Matches(subFil)) continue;
|
||||
Io_url subFilUrl = subFil.Url();
|
||||
try {engine.DeleteFil_api(IoEngine_xrg_deleteFil.new_(subFilUrl).ReadOnlyFails_(args.ReadOnlyFails()));}
|
||||
catch (Exception exc) {usrDlg.Write_fmt_w_nl(Err_.Message_lang(exc));}
|
||||
}
|
||||
// all subs deleted; now delete dir
|
||||
if (!args.MatchCrt().Matches(dir)) return;
|
||||
try {engine.DeleteDir(dir.Url());}
|
||||
catch (Exception exc) {usrDlg.Write_fmt_w_nl(Err_.Message_lang(exc));}
|
||||
}
|
||||
public void XferDir(IoEngine srcEngine, Io_url src, IoEngine trgEngine, Io_url trg, IoEngine_xrg_xferDir args) {
|
||||
trgEngine.CreateDir(trg);
|
||||
IoItmDir srcDir = QueryDirDeep(srcEngine, IoEngine_xrg_queryDir.new_(src).Recur_(false));
|
||||
for (Object subSrcObj : srcDir.SubDirs()) {
|
||||
IoItmDir subSrc = (IoItmDir)subSrcObj;
|
||||
if (!args.SubDirScanCrt().Matches(subSrc)) continue;
|
||||
if (!args.MatchCrt().Matches(subSrc)) continue;
|
||||
Io_url subTrg = trg.GenSubDir_nest(subSrc.Url().NameOnly()); //EX: C:\abc\def\ -> C:\123\ + def\
|
||||
if (args.Recur()) XferDir(srcEngine, subSrc.Url(), trgEngine, subTrg, args);
|
||||
}
|
||||
IoItmList srcFils = IoItmList.list_(src.Info().CaseSensitive());
|
||||
for (Object srcFilObj : srcDir.SubFils()) {
|
||||
IoItmFil srcFil = (IoItmFil)srcFilObj;
|
||||
if (args.MatchCrt().Matches(srcFil)) srcFils.Add(srcFil);
|
||||
}
|
||||
for (Object srcFilObj : srcFils) {
|
||||
IoItmFil srcFil = (IoItmFil)srcFilObj;
|
||||
Io_url srcFilPath = srcFil.Url();
|
||||
Io_url trgFilPath = trg.GenSubFil(srcFilPath.NameAndExt()); //EX: C:\abc\fil.txt -> C:\123\ + fil.txt
|
||||
IoEngine_xrg_xferFil xferArgs = args.Type_move() ? IoEngine_xrg_xferFil.move_(srcFilPath, trgFilPath).Overwrite_(args.Overwrite()) : IoEngine_xrg_xferFil.copy_(srcFilPath, trgFilPath).Overwrite_(args.Overwrite());
|
||||
XferFil(srcEngine, xferArgs);
|
||||
}
|
||||
if (args.Type_move()) srcEngine.DeleteDirDeep(IoEngine_xrg_deleteDir.new_(src).Recur_(args.Recur()).ReadOnlyFails_(args.ReadOnlyFails()));// this.DeleteDirDeep(srcEngine, src, IoEngine_xrg_deleteItm.new_(src).Recur_(args.Recur()).ReadOnlyIgnored_(args.ReadOnlyIgnored()));
|
||||
}
|
||||
public void XferFil(IoEngine srcEngine, IoEngine_xrg_xferFil args) {
|
||||
Io_url src = args.Src(), trg = args.Trg();
|
||||
if (String_.Eq(srcEngine.Key(), trg.Info().EngineKey())) {
|
||||
if (args.Type_move())
|
||||
srcEngine.MoveFil(args);
|
||||
else
|
||||
srcEngine.CopyFil(args);
|
||||
}
|
||||
else {
|
||||
TransferStream(src, trg);
|
||||
if (args.Type_move()) srcEngine.DeleteFil_api(IoEngine_xrg_deleteFil.new_(src));
|
||||
}
|
||||
}
|
||||
public IoItmDir QueryDirDeep(IoEngine engine, IoEngine_xrg_queryDir args) {
|
||||
IoItmDir rv = IoItmDir_.top_(args.Url());
|
||||
rv.Exists_set(QueryDirDeepCore(rv, args.Url(), engine, args.Recur(), args.SubDirScanCrt(), args.DirCrt(), args.FilCrt(), args.UsrDlg(), args.DirInclude()));
|
||||
return rv;
|
||||
}
|
||||
static boolean QueryDirDeepCore(IoItmDir ownerDir, Io_url url, IoEngine engine, boolean recur, Criteria subDirScanCrt, Criteria dirCrt, Criteria filCrt, Console_adp usrDlg, boolean dirInclude) {
|
||||
if (usrDlg.Canceled_chk()) return false;
|
||||
if (usrDlg.Enabled()) usrDlg.Write_tmp(String_.Concat("scan: ", url.Raw()));
|
||||
IoItmDir scanDir = engine.QueryDir(url);
|
||||
for (Object subDirObj : scanDir.SubDirs()) {
|
||||
IoItmDir subDir = (IoItmDir)subDirObj;
|
||||
if (!subDirScanCrt.Matches(subDir)) continue;
|
||||
if (dirCrt.Matches(subDir)) {
|
||||
ownerDir.SubDirs().Add(subDir); // NOTE: always add subDir; do not use dirCrt here, else its subFils will be added to non-existent subDir
|
||||
}
|
||||
if (recur)
|
||||
QueryDirDeepCore(subDir, subDir.Url(), engine, recur, subDirScanCrt, dirCrt, filCrt, usrDlg, dirInclude);
|
||||
}
|
||||
for (Object subFilObj : scanDir.SubFils()) {
|
||||
IoItmFil subFil = (IoItmFil)subFilObj;
|
||||
if (filCrt.Matches(subFil)) ownerDir.SubFils().Add(subFil);
|
||||
}
|
||||
return scanDir.Exists();
|
||||
}
|
||||
void TransferStream(Io_url src, Io_url trg) {
|
||||
IoStream srcStream = null;
|
||||
IoStream trgStream = null;
|
||||
try {
|
||||
srcStream = IoEnginePool.Instance.Get_by(src.Info().EngineKey()).OpenStreamRead(src);
|
||||
trgStream = IoEngine_xrg_openWrite.new_(trg).Exec();
|
||||
srcStream.Transfer(trgStream, bufferLength);
|
||||
}
|
||||
finally {
|
||||
if (srcStream != null) srcStream.Rls();
|
||||
if (trgStream != null) trgStream.Rls();
|
||||
}
|
||||
}
|
||||
private static final Lru_cache Dir_cache = new Lru_cache(Bool_.Y, "gplx.ios.dir_cache", 128, 256);
|
||||
public static boolean Query_read_only(IoEngine engine, Io_url url, int read_only_type) {
|
||||
switch (read_only_type) {
|
||||
case Io_mgr.Read_only__basic__file:
|
||||
return engine.QueryFil(url).Attrib().ReadOnly();
|
||||
case Io_mgr.Read_only__basic__file_and_dirs:
|
||||
if (Op_sys.Cur().Tid_is_wnt()) // only examine owner_dirs if wnt
|
||||
return Query_read_only__file_and_dirs(engine, url);
|
||||
else
|
||||
return engine.QueryFil(url).Attrib().ReadOnly();
|
||||
case Io_mgr.Read_only__perms__file:
|
||||
return engine.Query_itm_atrs(url, Io_itm_atr_req.New__read_only()).Is_read_only();
|
||||
default:
|
||||
throw Err_.new_unhandled_default(read_only_type);
|
||||
}
|
||||
}
|
||||
private static boolean Query_read_only__file_and_dirs(IoEngine engine, Io_url url) {
|
||||
// if fil
|
||||
if (url.Type_fil()) {
|
||||
IoItmFil fil = engine.QueryFil(url);
|
||||
// if read-only, return true
|
||||
if (fil.ReadOnly())
|
||||
return true;
|
||||
// else, set to owner dir
|
||||
else
|
||||
url = url.OwnerDir();
|
||||
}
|
||||
|
||||
// loop until top
|
||||
while (url != Io_url_.Empty) {
|
||||
String dir_key = url.Raw();
|
||||
|
||||
// check cache first
|
||||
IoItmDir dir = (IoItmDir)Dir_cache.Get_or_null(dir_key);
|
||||
if (dir == null) {
|
||||
// not in cache; query file_system
|
||||
dir = engine.QueryDir(url);
|
||||
Dir_cache.Set(dir_key, dir, 1);
|
||||
}
|
||||
|
||||
// if read-only, return true
|
||||
if (dir.ReadOnly())
|
||||
return true;
|
||||
// else, set to owner dir
|
||||
else
|
||||
url = url.OwnerDir();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IoEngineUtl new_() {return new IoEngineUtl();} IoEngineUtl() {}
|
||||
}
|
@ -14,7 +14,8 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
import gplx.core.ios.streams.*; import gplx.core.ios.atrs.*;
|
||||
import gplx.core.caches.*;
|
||||
public abstract class IoEngine_base implements IoEngine {
|
||||
public abstract String Key();
|
||||
public abstract boolean ExistsFil_api(Io_url url);
|
||||
@ -24,6 +25,7 @@ public abstract class IoEngine_base implements IoEngine {
|
||||
public abstract void CopyFil(IoEngine_xrg_xferFil args);
|
||||
public abstract void MoveFil(IoEngine_xrg_xferFil args);
|
||||
public abstract IoItmFil QueryFil(Io_url url);
|
||||
public abstract Io_itm_atr_req Query_itm_atrs(Io_url url, Io_itm_atr_req req);
|
||||
public abstract void UpdateFilAttrib(Io_url url, IoItmAttrib atr); // will fail if file does not exists
|
||||
public abstract void UpdateFilModifiedTime(Io_url url, DateAdp modified);
|
||||
public abstract IoStream OpenStreamRead(Io_url url);
|
||||
|
@ -14,7 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
import gplx.core.ios.streams.*; import gplx.core.ios.atrs.*;
|
||||
public class IoEngine_memory extends IoEngine_base {
|
||||
@Override public String Key() {return key;} private String key = IoEngine_.MemKey;
|
||||
@Override public boolean ExistsFil_api(Io_url url) {return FetchFil(url) != IoItmFil_mem.Null;}
|
||||
@ -190,6 +190,9 @@ public class IoEngine_memory extends IoEngine_base {
|
||||
byte[] bry = Bry_.new_u8(FetchFil(Io_url_.mem_fil_(xrg.Src())).Text());
|
||||
return Io_stream_rdr_.New__mem(bry);
|
||||
}
|
||||
@Override public Io_itm_atr_req Query_itm_atrs(Io_url url, Io_itm_atr_req req) {
|
||||
return req;
|
||||
}
|
||||
|
||||
IoItmHash dirs = IoItmHash.new_();
|
||||
IoEngineUtl utl = IoEngineUtl.new_();
|
||||
|
@ -21,12 +21,8 @@ import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.print.FlavorException;
|
||||
import javax.tools.JavaCompiler;
|
||||
import gplx.core.criterias.*; import gplx.core.bits.*; import gplx.core.envs.*;
|
||||
import gplx.core.ios.streams.*;
|
||||
import gplx.core.ios.streams.*; import gplx.core.ios.atrs.*;
|
||||
import gplx.core.progs.*;
|
||||
public class IoEngine_system extends IoEngine_base {
|
||||
@Override public String Key() {return IoEngine_.SysKey;}
|
||||
@ -42,6 +38,9 @@ public class IoEngine_system extends IoEngine_base {
|
||||
if (!Fil_Exists(fil)) return;
|
||||
MarkFileWritable(fil, url, args.ReadOnlyFails(), "DeleteFile");
|
||||
DeleteFil_lang(fil, url);
|
||||
}
|
||||
@Override public Io_itm_atr_req Query_itm_atrs(Io_url url, Io_itm_atr_req req) {
|
||||
return Io_itm_atr_wkr.New(url).Process(req);
|
||||
}
|
||||
@Override public boolean ExistsFil_api(Io_url url) {
|
||||
File f = new File(url.Xto_api());
|
||||
@ -158,7 +157,9 @@ public class IoEngine_system extends IoEngine_base {
|
||||
&& String_.Eq(url.OwnerDir().Raw(), String_.Empty) // folder is drive; EX: "C:"
|
||||
)
|
||||
url_api = url_api + "\\"; // add "\\"; else listFiles will return working folder's files, not C:; DATE:2016-04-07
|
||||
|
||||
File dirInfo = new File(url_api);
|
||||
rv.ReadOnly_(!dirInfo.canWrite()); // get read-only flag for directories; ISSUE#:509; DATE:2019-07-11
|
||||
if (!dirInfo.exists()) {
|
||||
rv.Exists_set(false);
|
||||
return rv;
|
||||
|
@ -18,6 +18,7 @@ import gplx.core.criterias.*;
|
||||
public class IoItmDir extends IoItm_base {
|
||||
public boolean Exists() {return exists;} public void Exists_set(boolean v) {exists = v;} private boolean exists = true;
|
||||
@Override public int TypeId() {return Type_Dir;} @Override public boolean Type_dir() {return true;} @Override public boolean Type_fil() {return false;} public static final int Type_Dir = 1;
|
||||
public boolean ReadOnly() {return readOnly;} public IoItmDir ReadOnly_(boolean val) {this.readOnly = val; return this;} private boolean readOnly;
|
||||
@gplx.New public IoItmDir XtnProps_set(String key, Object val) {return (IoItmDir)super.XtnProps_set(key, val);}
|
||||
public IoItmList SubDirs() {return subDirs;} IoItmList subDirs;
|
||||
public IoItmList SubFils() {return subFils;} IoItmList subFils;
|
||||
|
35
100_core/src/gplx/core/ios/atrs/Io_itm_atr_req.java
Normal file
35
100_core/src/gplx/core/ios/atrs/Io_itm_atr_req.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios.atrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
|
||||
public class Io_itm_atr_req {
|
||||
Io_itm_atr_req(boolean ignore_errors, boolean check_read_only) {
|
||||
this.ignore_errors = ignore_errors;
|
||||
this.check_read_only = check_read_only;
|
||||
}
|
||||
public boolean Check_read_only() {return check_read_only;} private final boolean check_read_only;
|
||||
public boolean Is_read_only() {return is_read_only;} public void Is_read_only_(boolean v) {this.is_read_only = v;} private boolean is_read_only;
|
||||
public boolean Ignore_errors() {return ignore_errors;} private final boolean ignore_errors;
|
||||
public String To_str() {
|
||||
Keyval[] ary = new Keyval[2];
|
||||
ary[0] = Keyval_.new_("check_read_only", check_read_only);
|
||||
ary[1] = Keyval_.new_("is_read_only", is_read_only);
|
||||
return Keyval_.Ary_to_str(ary);
|
||||
}
|
||||
|
||||
public static Io_itm_atr_req New__read_only() {
|
||||
return new Io_itm_atr_req(true, true);
|
||||
}
|
||||
}
|
63
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr.java
Normal file
63
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr.java
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios.atrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.AclFileAttributeView;
|
||||
import java.nio.file.attribute.PosixFileAttributeView;
|
||||
import java.util.Set;
|
||||
public abstract class Io_itm_atr_wkr {
|
||||
private final Path path;
|
||||
public Io_itm_atr_wkr(Path path) {
|
||||
this.path = path;
|
||||
}
|
||||
public Io_itm_atr_req Process(Io_itm_atr_req req) {
|
||||
try {
|
||||
if (req.Check_read_only())
|
||||
req.Is_read_only_(this.Is_read_only());
|
||||
}
|
||||
catch (Exception e) {
|
||||
Err err = Err_.new_wo_type("query_itm_atrs failed", "url", path.toString(), "atrs", req.To_str(), "e", Err_.Message_gplx_log(e));
|
||||
if (req.Ignore_errors()) { // https://stackoverflow.com/questions/25163174/get-generic-folder-permissions-like-generic-all-using-javas-aclfileattributev
|
||||
Gfo_usr_dlg_.Instance.Warn_many("", "", err.To_str__log());
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
public abstract boolean Is_read_only();
|
||||
public static Io_itm_atr_wkr New(Io_url url) {
|
||||
File fil = new File(url.Xto_api());
|
||||
Path path = fil.toPath();
|
||||
Set<String> supported_views = path.getFileSystem().supportedFileAttributeViews();
|
||||
if (supported_views.contains("posix")) {
|
||||
return new Io_itm_atr_wkr__psx(path);
|
||||
}
|
||||
// WNT
|
||||
else if (supported_views.contains("acl")) {
|
||||
return new Io_itm_atr_wkr__acl(path);
|
||||
}
|
||||
else {
|
||||
String set_string = "";
|
||||
for (String view : supported_views) {
|
||||
set_string += view + ";";
|
||||
}
|
||||
throw Err_.new_unhandled(set_string);
|
||||
}
|
||||
}
|
||||
}
|
93
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr__acl.java
Normal file
93
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr__acl.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios.atrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.AclEntry;
|
||||
import java.nio.file.attribute.AclEntryPermission;
|
||||
import java.nio.file.attribute.AclEntryType;
|
||||
import java.nio.file.attribute.AclFileAttributeView;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import gplx.core.primitives.Bool_obj_val;
|
||||
class Io_itm_atr_wkr__acl extends Io_itm_atr_wkr { private final AclFileAttributeView view;
|
||||
public Io_itm_atr_wkr__acl(Path path) {
|
||||
super(path);
|
||||
this.view = Files.getFileAttributeView(path, AclFileAttributeView.class);
|
||||
}
|
||||
@Override public boolean Is_read_only() {
|
||||
try {
|
||||
// convert AclEntry to Acl_entry
|
||||
List<AclEntry> list = view.getAcl();
|
||||
int len = list.size();
|
||||
Acl_entry[] ary = new Acl_entry[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
AclEntry under = list.get(i);
|
||||
ary[i] = new Acl_entry(under.principal().toString(), under.type(), under.permissions());
|
||||
}
|
||||
return !Is_permitted(ary, AclEntryPermission.WRITE_DATA);
|
||||
} catch (Exception e) {
|
||||
throw Err_.new_exc(e, "", "Is_read_only failed", "e", Err_.Message_lang(e));
|
||||
}
|
||||
}
|
||||
public static boolean Is_permitted(Acl_entry[] ary, AclEntryPermission permission) {
|
||||
boolean rv = false;
|
||||
Hash_adp principals = Hash_adp_.New();
|
||||
for (Acl_entry itm : ary) {
|
||||
Set<AclEntryPermission> permissions = itm.Permissions();
|
||||
switch (itm.Type()) {
|
||||
// If multiple ALLOW entries
|
||||
// * for same principal, return false if any of them do not have permission
|
||||
// * for diff principals, return true if any of them does have permissions
|
||||
case ALLOW: {
|
||||
// if current principal is forbidden, ignore entry; want to skip lists like Everyone:Forbidden:C:/folder;Everyone:Allowed;C:/
|
||||
Bool_obj_val forbidden = (Bool_obj_val)principals.Get_by(itm.Principal());
|
||||
if (forbidden != null) {
|
||||
continue;
|
||||
}
|
||||
if (!permissions.contains(permission) && !rv) {
|
||||
rv = false;
|
||||
principals.Add(itm.Principal(), Bool_obj_val.False);
|
||||
}
|
||||
else {
|
||||
rv = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// If any DENY entries, return false on first entry
|
||||
case DENY: {
|
||||
if (permissions.contains(permission)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Acl_entry {
|
||||
public Acl_entry(String principal, AclEntryType type, Set<AclEntryPermission> permissions) {
|
||||
this.principal = principal;
|
||||
this.type = type;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
public String Principal() {return principal;} private final String principal;
|
||||
public AclEntryType Type() {return type;} private final AclEntryType type;
|
||||
public Set<AclEntryPermission> Permissions() {return permissions;} private final Set<AclEntryPermission> permissions;
|
||||
}
|
||||
//#}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios.atrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
|
||||
import org.junit.*; import gplx.core.tests.*;
|
||||
|
||||
import java.nio.file.attribute.AclEntryPermission;
|
||||
import java.nio.file.attribute.AclEntryType;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
public class Io_itm_atr_wkr__acl__tst {
|
||||
private final Io_itm_attrib_wkr__acl__fxt fxt = new Io_itm_attrib_wkr__acl__fxt();
|
||||
@Test public void Perm_exists() {
|
||||
fxt.Test__Is_permitted
|
||||
( Bool_.Y, AclEntryPermission.WRITE_DATA
|
||||
, fxt.Make__acl("Everyone", AclEntryType.ALLOW, AclEntryPermission.WRITE_DATA)
|
||||
);
|
||||
}
|
||||
@Test public void Perm_missing() {
|
||||
fxt.Test__Is_permitted
|
||||
( Bool_.N, AclEntryPermission.WRITE_DATA
|
||||
, fxt.Make__acl("Everyone", AclEntryType.ALLOW, AclEntryPermission.READ_DATA)
|
||||
);
|
||||
}
|
||||
@Test public void Deny_over_allow() {
|
||||
fxt.Test__Is_permitted
|
||||
( Bool_.N, AclEntryPermission.WRITE_DATA
|
||||
, fxt.Make__acl("Everyone", AclEntryType.ALLOW, AclEntryPermission.WRITE_DATA)
|
||||
, fxt.Make__acl("Everyone", AclEntryType.DENY , AclEntryPermission.WRITE_DATA)
|
||||
);
|
||||
}
|
||||
@Test public void Same_principal__perm_missing_over_perm_exists() {
|
||||
/*
|
||||
EX: SD card wherein acl_list has 2 entries
|
||||
* Entry[0] | //MACHINE/SHARE | Everyone:READ_DATA/READ_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/READ_ACL/SYNCHRONIZE:ALLOW
|
||||
* Entry[1] | DRIVE_NAME:/ | Everyone:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
|
||||
*/
|
||||
fxt.Test__Is_permitted
|
||||
( Bool_.N, AclEntryPermission.WRITE_DATA
|
||||
, fxt.Make__acl("Everyone", AclEntryType.ALLOW, AclEntryPermission.READ_DATA)
|
||||
, fxt.Make__acl("Everyone", AclEntryType.ALLOW, AclEntryPermission.READ_DATA, AclEntryPermission.WRITE_DATA)
|
||||
);
|
||||
}
|
||||
@Test public void Diff_principals__perm_exists_over_perm_missing() {
|
||||
/*
|
||||
EX: C drive wherein acl_list has 2 entries
|
||||
* Entry[0] | C:/ | Administrators:READ_DATA/WRITE_DATA
|
||||
* Entry[1] | C:/ | Everyone:READ_DATA
|
||||
*/
|
||||
fxt.Test__Is_permitted
|
||||
( Bool_.Y, AclEntryPermission.WRITE_DATA
|
||||
, fxt.Make__acl("Administrators", AclEntryType.ALLOW, AclEntryPermission.WRITE_DATA)
|
||||
, fxt.Make__acl("Users" , AclEntryType.ALLOW, AclEntryPermission.READ_DATA)
|
||||
);
|
||||
}
|
||||
}
|
||||
class Io_itm_attrib_wkr__acl__fxt {
|
||||
public void Test__Is_permitted(boolean expd, AclEntryPermission permission, Acl_entry... entries) {
|
||||
boolean actl = Io_itm_atr_wkr__acl.Is_permitted(entries, permission);
|
||||
Gftest.Eq__bool(expd, actl);
|
||||
}
|
||||
public Acl_entry Make__acl(String principal, AclEntryType type, AclEntryPermission... perms) {
|
||||
Set<AclEntryPermission> perm_set = new HashSet<AclEntryPermission>();
|
||||
for (AclEntryPermission perm : perms)
|
||||
perm_set.add(perm);
|
||||
return new Acl_entry(principal, type, perm_set);
|
||||
}
|
||||
}
|
52
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr__psx.java
Normal file
52
100_core/src/gplx/core/ios/atrs/Io_itm_atr_wkr__psx.java
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.ios.atrs; import gplx.*; import gplx.core.*; import gplx.core.ios.*;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.PosixFileAttributeView;
|
||||
import java.nio.file.attribute.PosixFileAttributes;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.Set;
|
||||
class Io_itm_atr_wkr__psx extends Io_itm_atr_wkr { private final PosixFileAttributeView view;
|
||||
public Io_itm_atr_wkr__psx(Path path) {
|
||||
super(path);
|
||||
this.view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
|
||||
}
|
||||
@Override public boolean Is_read_only() {
|
||||
try {
|
||||
// ASSUME:a file is read-only if it is read-only; Note that the directory may need write-access, but not handling it now; REF:https://superuser.com/a/114611
|
||||
Set<PosixFilePermission> perms = view.readAttributes().permissions();
|
||||
int perm_flag = Psx__permissions_to_int(perms);
|
||||
return perm_flag == 0444;
|
||||
} catch (Exception e) {
|
||||
throw Err_.new_exc(e, "", "Is_read_only failed", "e", Err_.Message_lang(e));
|
||||
}
|
||||
}
|
||||
public static int Psx__permissions_to_int(Set<PosixFilePermission> psx_perms) {
|
||||
int rv = 0;
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OWNER_READ)) ? 1 << 8 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OWNER_WRITE)) ? 1 << 7 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OWNER_EXECUTE)) ? 1 << 6 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.GROUP_READ)) ? 1 << 5 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.GROUP_WRITE)) ? 1 << 4 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.GROUP_EXECUTE)) ? 1 << 3 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OTHERS_READ)) ? 1 << 2 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OTHERS_WRITE)) ? 1 << 1 : 0);
|
||||
rv |= ((psx_perms.contains(PosixFilePermission.OTHERS_EXECUTE)) ? 1 : 0);
|
||||
return rv;
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ public class IoStream_mock implements IoStream {
|
||||
if (bytes_read > read_limit) bytes_read = read_limit; // stream may limit maximum read; EX: bfr_len of 16k but only 2k will be filled
|
||||
int bytes_left = data_bry_len - data_bry_pos;
|
||||
if (bytes_read > bytes_left) bytes_read = bytes_left; // not enough bytes left in data_bry; bytes_read = whatever is left
|
||||
Bry_.Copy_by_pos(data_bry, data_bry_pos, data_bry_pos + bytes_read, bfr, bfr_bgn);
|
||||
Bry_.Copy_to(data_bry, data_bry_pos, data_bry_pos + bytes_read, bfr, bfr_bgn);
|
||||
data_bry_pos += bytes_read;
|
||||
return bytes_read;
|
||||
}
|
||||
|
@ -20,6 +20,11 @@ public abstract class Hash_adp_base implements Hash_adp {
|
||||
public Object Get_by_or_fail(Object key) {return Get_by_or_fail_base(key);}
|
||||
public void Add(Object key, Object val) {Add_base(key, val);}
|
||||
public Hash_adp Add_and_more(Object key, Object val) {Add_base(key, val); return this;}
|
||||
public Hash_adp Add_many_as_key_and_val(Object... ary) {
|
||||
for (Object itm : ary)
|
||||
Add_base(itm, itm);
|
||||
return this;
|
||||
}
|
||||
public void Add_as_key_and_val(Object val) {Add_base(val, val);}
|
||||
public void Add_if_dupe_use_nth(Object key, Object val) {
|
||||
Object existing = Fetch_base(key); if (existing != null) Del(key); // overwrite if exists
|
||||
|
@ -22,6 +22,11 @@ public class Sorted_hash implements Hash_adp {
|
||||
public Object Get_by_or_fail(Object key) {return Get_by_or_fail_base(key);}
|
||||
public void Add(Object key, Object val) {Add_base(key, val);}
|
||||
public Hash_adp Add_and_more(Object key, Object val) {Add_base(key, val); return this;}
|
||||
public Hash_adp Add_many_as_key_and_val(Object... ary) {
|
||||
for (Object itm : ary)
|
||||
Add_base(itm, itm);
|
||||
return this;
|
||||
}
|
||||
public void Add_as_key_and_val(Object val) {Add_base(val, val);}
|
||||
public void Add_if_dupe_use_nth(Object key, Object val) {
|
||||
Object existing = Fetch_base(key); if (existing != null) Del(key); // overwrite if exists
|
||||
|
25
100_core/src/gplx/core/primitives/ObjectWrapperRef.java
Normal file
25
100_core/src/gplx/core/primitives/ObjectWrapperRef.java
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.primitives;
|
||||
|
||||
import gplx.Object_;
|
||||
|
||||
public class ObjectWrapperRef {
|
||||
public ObjectWrapperRef() {}
|
||||
public Object Val() {return val;} public ObjectWrapperRef Val_(Object v) {val = v; return this;} private Object val;
|
||||
public ObjectWrapperRef Val_null_() {return Val_(null);}
|
||||
@Override public String toString() {return Object_.Xto_str_strict_or_null(val);}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import gplx.core.consoles.*; import gplx.core.ios.streams.*; /*IoStream*/
|
||||
import gplx.core.texts.*; /*Base32Converter*/ import gplx.core.progs.*;
|
||||
public class Hash_algo_ {
|
||||
public static Hash_algo New__md5() {return new Hash_algo__md5();}
|
||||
public static Hash_algo New__sha1() {return new Hash_algo__sha1();}
|
||||
public static Hash_algo New__sha2_256() {return new Hash_algo__sha2_256();}
|
||||
public static Hash_algo New__tth_192() {return new Hash_algo__tth_192();}
|
||||
public static Hash_algo New_by_tid(byte tid) {
|
||||
switch (tid) {
|
||||
case Tid__md5: return New__md5();
|
||||
case Tid__sha1: return New__sha1();
|
||||
case Tid__sha2_256: return New__sha2_256();
|
||||
case Tid__tth_192: return New__tth_192();
|
||||
default: throw Err_.new_unhandled_default(tid);
|
||||
}
|
||||
}
|
||||
public static Hash_algo New(String key) {
|
||||
if (key == Hash_algo__md5.KEY) return New__md5();
|
||||
else if (key == Hash_algo__sha1.KEY) return New__sha1();
|
||||
else if (key == Hash_algo__sha2_256.KEY) return New__sha2_256();
|
||||
else if (key == Hash_algo__tth_192.KEY) return New__tth_192();
|
||||
else throw Err_.new_unhandled(key);
|
||||
}
|
||||
public static final byte Tid__md5 = 0, Tid__sha1 = 1, Tid__sha2_256 = 2, Tid__tth_192 = 3;
|
||||
}
|
||||
abstract class Hash_algo_base implements Hash_algo {
|
||||
private final MessageDigest md;
|
||||
private final byte[] trg_bry;
|
||||
private byte[] tmp_bfr; private final int tmp_bfr_len = 4096;
|
||||
public Hash_algo_base(MessageDigest md, int trg_bry_len) {
|
||||
this.md = md; this.trg_bry = new byte[trg_bry_len];
|
||||
}
|
||||
public String Hash_bry_as_str(byte[] src) {return String_.new_a7(Hash_bry_as_bry(src));}
|
||||
public byte[] Hash_bry_as_bry(byte[] src) {
|
||||
Hash_algo_utl_.Hash_bry(md, src, src.length, trg_bry);
|
||||
return Bry_.Copy(trg_bry); // NOTE: must copy to return different instances to callers; else callers may hash same instance with different values
|
||||
}
|
||||
public String Hash_stream_as_str(Console_adp console, IoStream stream) {return String_.new_a7(Hash_stream_as_bry(console, stream));}
|
||||
public byte[] Hash_stream_as_bry(Console_adp console, IoStream stream) {
|
||||
if (tmp_bfr == null) tmp_bfr = new byte[4096];
|
||||
Hash_algo_utl_.Hash_stream(console, stream, md, tmp_bfr, tmp_bfr_len, trg_bry);
|
||||
return trg_bry;
|
||||
}
|
||||
public byte[] Hash_stream_as_bry(Gfo_prog_ui prog_ui, IoStream stream) {
|
||||
if (tmp_bfr == null) tmp_bfr = new byte[4096];
|
||||
Hash_algo_utl_.Hash_stream(prog_ui, stream, md, tmp_bfr, tmp_bfr_len, trg_bry);
|
||||
return trg_bry;
|
||||
}
|
||||
protected static MessageDigest Get_message_digest(String key) {
|
||||
try {return MessageDigest.getInstance(key);}
|
||||
catch (NoSuchAlgorithmException e) {throw Err_.new_missing_key(key);}
|
||||
}
|
||||
}
|
||||
class Hash_algo__md5 extends Hash_algo_base {
|
||||
public Hash_algo__md5() {super(Get_message_digest_instance(), 32);}
|
||||
public String Key() {return KEY;} public static final String KEY = "md5";
|
||||
|
||||
private static MessageDigest Get_message_digest_instance() {
|
||||
if (md__md5 == null)
|
||||
md__md5 = Get_message_digest(KEY);
|
||||
return md__md5;
|
||||
} private static MessageDigest md__md5;
|
||||
}
|
||||
class Hash_algo__sha1 extends Hash_algo_base {
|
||||
public Hash_algo__sha1() {super(Get_message_digest_instance(), 40);}
|
||||
public String Key() {return KEY;} public static final String KEY = "sha1";
|
||||
|
||||
private static MessageDigest Get_message_digest_instance() {
|
||||
if (md__sha1 == null)
|
||||
md__sha1 = Get_message_digest(KEY);
|
||||
return md__sha1;
|
||||
} private static MessageDigest md__sha1;
|
||||
}
|
||||
class Hash_algo__sha2_256 extends Hash_algo_base {
|
||||
public Hash_algo__sha2_256() {super(Get_message_digest_instance(), 64);}
|
||||
public String Key() {return KEY;} public static final String KEY = "sha-256";
|
||||
|
||||
private static MessageDigest Get_message_digest_instance() {
|
||||
if (md__sha2_256 == null)
|
||||
md__sha2_256 = Get_message_digest(KEY);
|
||||
return md__sha2_256;
|
||||
} private static MessageDigest md__sha2_256;
|
||||
}
|
||||
class Hash_algo_utl_ {
|
||||
public static void Hash_bry(MessageDigest md, byte[] src_bry, int src_len, byte[] trg_bry) {
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
if (pos == src_len) break;
|
||||
int len = 4096;
|
||||
if (pos + len > src_len) {
|
||||
len = src_len - pos;
|
||||
}
|
||||
md.update(src_bry, pos, len);
|
||||
pos += len;
|
||||
}
|
||||
byte[] md_bry = md.digest();
|
||||
gplx.core.encoders.Hex_utl_.Encode_bry(md_bry, trg_bry);
|
||||
}
|
||||
public static void Hash_stream(Console_adp dialog, IoStream stream, MessageDigest md, byte[] tmp_bfr, int tmp_bfr_len, byte[] trg_bry) {
|
||||
// long pos = 0, len = stream.Len(); // pos and len must be long, else will not hash files > 2 GB
|
||||
while (true) {
|
||||
int read = stream.Read(tmp_bfr, 0, tmp_bfr_len); // read stream into tmp_bfr
|
||||
if (read < 1) break;
|
||||
md.update(tmp_bfr, 0, read);
|
||||
// pos += read;
|
||||
}
|
||||
byte[] md_bry = md.digest();
|
||||
gplx.core.encoders.Hex_utl_.Encode_bry(md_bry , trg_bry);
|
||||
}
|
||||
public static void Hash_stream(Gfo_prog_ui prog_ui, IoStream stream, MessageDigest md, byte[] tmp_bfr, int tmp_bfr_len, byte[] trg_bry) {
|
||||
long pos = prog_ui.Prog_data_cur(), len = prog_ui.Prog_data_end(); // pos and len must be long, else will not hash files > 2 GB
|
||||
try {
|
||||
while (true) {
|
||||
int read = stream.Read(tmp_bfr, 0, tmp_bfr_len); // read stream into tmp_bfr
|
||||
if (read < 1) break;
|
||||
md.update(tmp_bfr, 0, read);
|
||||
if (prog_ui.Prog_notify_and_chk_if_suspended(pos, len)) return;
|
||||
pos += read;
|
||||
}
|
||||
}
|
||||
finally {stream.Rls();}
|
||||
byte[] md_bry = md.digest();
|
||||
gplx.core.encoders.Hex_utl_.Encode_bry(md_bry , trg_bry);
|
||||
}
|
||||
public static String To_base_32_str(byte[] ary) {return Base32Converter.Encode(ary);}
|
||||
}
|
66
100_core/src/gplx/core/security/Security_utl_.java
Normal file
66
100_core/src/gplx/core/security/Security_utl_.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.security.Provider.Service;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
public class Security_utl_ {
|
||||
private static final void List_algos(Provider prov, Class<?> typeClass) {
|
||||
String type = typeClass.getSimpleName();
|
||||
|
||||
List<Service> algos = new ArrayList<Service>();
|
||||
|
||||
Set<Service> services = prov.getServices();
|
||||
for (Service service : services) {
|
||||
if (service.getType().equalsIgnoreCase(type)) {
|
||||
algos.add(service);
|
||||
}
|
||||
}
|
||||
|
||||
if (!algos.isEmpty()) {
|
||||
System.out.printf(" --- Provider %s, version %.2f --- %n", prov.getName(), prov.getVersion());
|
||||
for (Service service : algos) {
|
||||
String algo = service.getAlgorithm();
|
||||
System.out.printf("Algorithm name: \"%s\"%n", algo);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// --- find aliases (inefficiently)
|
||||
Set<Object> keys = prov.keySet();
|
||||
for (Object key : keys) {
|
||||
final String prefix = "Alg.Alias." + type + ".";
|
||||
if (key.toString().startsWith(prefix)) {
|
||||
String value = prov.get(key.toString()).toString();
|
||||
System.out.printf("Alias: \"%s\" -> \"%s\"%n",
|
||||
key.toString().substring(prefix.length()),
|
||||
value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Provider[] providers = Security.getProviders();
|
||||
for (Provider provider : providers) {
|
||||
List_algos(provider, MessageDigest.class);
|
||||
}
|
||||
}
|
||||
}
|
22
100_core/src/gplx/core/security/algos/Hash_algo.java
Normal file
22
100_core/src/gplx/core/security/algos/Hash_algo.java
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
public interface Hash_algo {// THREAD.UNSAFE
|
||||
String Key();
|
||||
void Update_digest(byte[] src, int bgn, int end);
|
||||
byte[] To_hash_bry();
|
||||
Hash_algo Clone_hash_algo(); // factory method; note that MessageDigest's are member variables, so always create a new instance
|
||||
}
|
41
100_core/src/gplx/core/security/algos/Hash_algo_.java
Normal file
41
100_core/src/gplx/core/security/algos/Hash_algo_.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
import gplx.core.consoles.*; import gplx.core.ios.streams.*; /*IoStream*/
|
||||
import gplx.core.security.algos.jre.*; import gplx.core.security.algos.gplx_crypto.*;
|
||||
public class Hash_algo_ {
|
||||
public static Hash_algo New__md5() {return Jre_hash_factory.Instance.New_hash_algo(Jre_hash_factory.Key__md5);}
|
||||
public static Hash_algo New__sha1() {return Jre_hash_factory.Instance.New_hash_algo(Jre_hash_factory.Key__sha1);}
|
||||
public static Hash_algo New__sha2_256() {return Jre_hash_factory.Instance.New_hash_algo(Jre_hash_factory.Key__sha2_256);}
|
||||
public static Hash_algo New__tth_192() {return new Hash_algo__tth_192();}
|
||||
public static Hash_algo New_by_tid(byte tid) {
|
||||
switch (tid) {
|
||||
case Tid__md5: return New__md5();
|
||||
case Tid__sha1: return New__sha1();
|
||||
case Tid__sha2_256: return New__sha2_256();
|
||||
case Tid__tth_192: return New__tth_192();
|
||||
default: throw Err_.new_unhandled_default(tid);
|
||||
}
|
||||
}
|
||||
public static Hash_algo New(String key) {
|
||||
if (key == Jre_hash_factory.Key__md5) return New__md5();
|
||||
else if (key == Jre_hash_factory.Key__sha1) return New__sha1();
|
||||
else if (key == Jre_hash_factory.Key__sha2_256) return New__sha2_256();
|
||||
else if (key == Hash_algo__tth_192.KEY) return New__tth_192();
|
||||
else throw Err_.new_unhandled(key);
|
||||
}
|
||||
public static final byte Tid__md5 = 0, Tid__sha1 = 1, Tid__sha2_256 = 2, Tid__tth_192 = 3;
|
||||
}
|
24
100_core/src/gplx/core/security/algos/Hash_algo__fxt.java
Normal file
24
100_core/src/gplx/core/security/algos/Hash_algo__fxt.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
public class Hash_algo__fxt {
|
||||
private final Hash_algo algo;
|
||||
public Hash_algo__fxt(Hash_algo algo) {this.algo = algo;}
|
||||
public void Test__hash(String expd, String raw) {
|
||||
Tfds.Eq(expd, Hash_algo_utl.Calc_hash_as_str(algo, Bry_.new_u8(raw)));
|
||||
Tfds.Eq(expd, Hash_algo_utl.Calc_hash_w_prog_as_str(algo, gplx.core.ios.streams.IoStream_.mem_txt_(Io_url_.Empty, raw), gplx.core.consoles.Console_adp_.Noop));
|
||||
}
|
||||
}
|
@ -13,8 +13,7 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.mediawiki.includes.exception; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
|
||||
public class XomwMWException extends Err {
|
||||
public XomwMWException(String msg) {super(true, "", "", msg);
|
||||
}
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
public interface Hash_algo_factory {
|
||||
Hash_algo New_hash_algo(String key);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
public class Hash_algo_factory__composite implements Hash_algo_factory {
|
||||
private boolean dirty = true;
|
||||
private final Ordered_hash hash = Ordered_hash_.New();
|
||||
private String[] algo_keys;
|
||||
public String[] Algo_keys() {
|
||||
if (dirty) {
|
||||
dirty = false;
|
||||
int len = hash.Len();
|
||||
algo_keys = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
algo_keys[i] = ((Hash_algo)hash.Get_at(i)).Key();
|
||||
}
|
||||
}
|
||||
return algo_keys;
|
||||
}
|
||||
public Hash_algo New_hash_algo(String key) {
|
||||
Hash_algo rv = (Hash_algo)hash.Get_by(key);
|
||||
if (rv == null) {
|
||||
throw Err_.new_wo_type("hash_algo unknown; key=" + key);
|
||||
}
|
||||
return rv.Clone_hash_algo();
|
||||
}
|
||||
|
||||
public Hash_algo_factory__composite Reg_many(Hash_algo_factory factory, String... algo_keys) {
|
||||
dirty = true;
|
||||
for (String algo_key : algo_keys) {
|
||||
if (hash.Has(algo_key)) {
|
||||
throw Err_.new_wo_type("hash_algo already registered; key=" + algo_key);
|
||||
}
|
||||
hash.Add(algo_key, factory.New_hash_algo(algo_key));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public Hash_algo_factory__composite Reg_one(Hash_algo_factory factory, String src_key, String trg_key) {
|
||||
if (hash.Has(trg_key)) {
|
||||
throw Err_.new_wo_type("hash_algo already registered; name=" + trg_key);
|
||||
}
|
||||
hash.Add(trg_key, factory.New_hash_algo(src_key));
|
||||
return this;
|
||||
}
|
||||
}
|
59
100_core/src/gplx/core/security/algos/Hash_algo_utl.java
Normal file
59
100_core/src/gplx/core/security/algos/Hash_algo_utl.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
import gplx.core.consoles.*; import gplx.core.progs.*; import gplx.core.ios.streams.*;
|
||||
import gplx.core.encoders.*;
|
||||
public class Hash_algo_utl {
|
||||
public static String Calc_hash_as_str(Hash_algo algo, byte[] bry) {return String_.new_u8(Calc_hash_as_bry(algo, bry));}
|
||||
public static byte[] Calc_hash_as_bry(Hash_algo algo, byte[] bry) {
|
||||
if (Type_.Is_assignable_from_by_obj(algo, Hash_algo_w_prog.class)) {
|
||||
Hash_algo_w_prog algo_w_prog = (Hash_algo_w_prog)algo;
|
||||
return Bry_.new_u8(algo_w_prog.Calc_hash_w_prog_as_str(IoStream_.ary_(bry), Console_adp_.Noop));
|
||||
}
|
||||
|
||||
algo.Update_digest(bry, 0, bry.length);
|
||||
return algo.To_hash_bry();
|
||||
}
|
||||
public static String Calc_hash_w_prog_as_str(Hash_algo algo, IoStream stream, Console_adp console) {return String_.new_u8(Calc_hash_w_prog_as_bry(algo, stream, console));}
|
||||
public static byte[] Calc_hash_w_prog_as_bry(Hash_algo algo, IoStream stream, Console_adp console) {
|
||||
if (Type_.Is_assignable_from_by_obj(algo, Hash_algo_w_prog.class)) {
|
||||
Hash_algo_w_prog algo_w_prog = (Hash_algo_w_prog)algo;
|
||||
return Bry_.new_u8(algo_w_prog.Calc_hash_w_prog_as_str(stream, console));
|
||||
}
|
||||
return Calc_hash_w_prog_as_bry(algo, stream, Gfo_prog_ui_.Noop);
|
||||
}
|
||||
public static byte[] Calc_hash_w_prog_as_bry(Hash_algo algo, IoStream stream, Gfo_prog_ui prog_ui) {
|
||||
int tmp_bry_len = 4096;
|
||||
byte[] tmp_bry = new byte[4096];
|
||||
|
||||
// pos and len must be long, else will not hash files > 2 GB
|
||||
long pos = prog_ui.Prog_data_cur();
|
||||
long len = prog_ui.Prog_data_end();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
int read = stream.Read(tmp_bry, 0, tmp_bry_len); // read stream into tmp_bry
|
||||
if (read < 1) break;
|
||||
algo.Update_digest(tmp_bry, 0, read);
|
||||
if (prog_ui.Prog_notify_and_chk_if_suspended(pos, len)) return null;
|
||||
pos += read;
|
||||
}
|
||||
}
|
||||
finally {stream.Rls();}
|
||||
byte[] rv = algo.To_hash_bry();
|
||||
return rv;
|
||||
}
|
||||
}
|
20
100_core/src/gplx/core/security/algos/Hash_algo_w_prog.java
Normal file
20
100_core/src/gplx/core/security/algos/Hash_algo_w_prog.java
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
|
||||
import gplx.core.consoles.*; import gplx.core.ios.streams.*;
|
||||
public interface Hash_algo_w_prog {
|
||||
String Calc_hash_w_prog_as_str(IoStream stream, Console_adp console);
|
||||
}
|
@ -13,16 +13,16 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.gplx_crypto; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import gplx.core.consoles.*; import gplx.core.ios.streams.*; /*IoStream*/
|
||||
import gplx.core.progs.*;
|
||||
public class Hash_algo__tth_192 implements Hash_algo {
|
||||
public class Hash_algo__tth_192 implements Hash_algo, Hash_algo_w_prog {
|
||||
public String Key() {return KEY;} public static final String KEY = "tth192";
|
||||
public Hash_algo Clone_hash_algo() {return new Hash_algo__tth_192();}
|
||||
public int BlockSize() {return blockSize;} public void BlockSize_set(int v) {blockSize = v;} int blockSize = 1024;
|
||||
public String Hash_bry_as_str(byte[] src) {return String_.new_a7(Hash_bry_as_bry(src));}
|
||||
public byte[] Hash_bry_as_bry(byte[] v) {return Bry_.new_a7(Hash_stream_as_str(Console_adp_.Noop, gplx.core.ios.streams.IoStream_.ary_(v)));}
|
||||
public byte[] Hash_stream_as_bry(Gfo_prog_ui prog_ui, IoStream stream) {return Bry_.new_a7(Hash_stream_as_str(Console_adp_.Noop, stream));}
|
||||
public String Hash_stream_as_str(Console_adp dialog, IoStream stream) {
|
||||
public void Update_digest(byte[] src, int bgn, int end) {throw Err_.new_unimplemented();}
|
||||
public byte[] To_hash_bry() {throw Err_.new_unimplemented();}
|
||||
public String Calc_hash_w_prog_as_str(IoStream stream, Console_adp dialog) {
|
||||
int leafCount = (int)(stream.Len() / blockSize);
|
||||
HashDlgWtr dialogWtr = HashDlgWtr_.Current;
|
||||
dialogWtr.Bgn(dialog, stream.Url(), CalcWorkUnits(stream.Len()));
|
||||
@ -35,7 +35,7 @@ public class Hash_algo__tth_192 implements Hash_algo {
|
||||
hashMainCount = 0;
|
||||
HashAllBytes(dialogWtr, stream, leafCount);
|
||||
byte[] rv = HashAllHashes(dialogWtr);
|
||||
return Hash_algo_utl_.To_base_32_str(rv);
|
||||
return gplx.core.texts.Base32Converter.Encode(rv);
|
||||
}
|
||||
byte[] CalcHash_next(IoStream stream) {
|
||||
if (blockA == null || blockA.length != blockSize) blockA = new byte[blockSize];
|
@ -13,7 +13,7 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.gplx_crypto; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*; import gplx.core.consoles.*; import gplx.core.ios.*; /*IoStream*/
|
||||
public class Hash_algo__tth_192__tst { // REF: http://open-content.net/specs/draft-jchapweske-thex-02.html; DC++ 0.698
|
||||
private final Hash_algo__fxt fxt = new Hash_algo__fxt(Hash_algo_.New__tth_192());
|
@ -13,7 +13,7 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.gplx_crypto; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*;
|
||||
public class Hash_algo__tth_192_tree_tst {
|
||||
@Test public void CalcRecursiveHalves() {
|
@ -13,27 +13,33 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.gplx_crypto; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*; import gplx.core.consoles.*; import gplx.core.ios.streams.*; /*IoStream*/
|
||||
public class Hash_console_wtr_tst {
|
||||
@Before public void setup() {
|
||||
Hash_algo__tth_192 algo = new Hash_algo__tth_192();
|
||||
algo.BlockSize_set(10);
|
||||
calc = algo;
|
||||
}
|
||||
private final Hash_console_wtr_fxt fxt = new Hash_console_wtr_fxt();
|
||||
@Test public void Basic() {
|
||||
tst_Status(10, stringAry_(" - hash: 100%"));
|
||||
tst_Status(11, stringAry_(" - hash: 66%"));
|
||||
tst_Status(30, stringAry_(" - hash: 40%", " - hash: 60%", " - hash: 100%"));
|
||||
fxt.Test__Status(10, " - hash: 100%");
|
||||
fxt.Test__Status(11, " - hash: 66%");
|
||||
fxt.Test__Status(30, " - hash: 40%", " - hash: 60%", " - hash: 100%");
|
||||
}
|
||||
void tst_Status(int count, String[] expdWritten) {
|
||||
Console_adp__mem dialog = Console_adp_.Dev();
|
||||
}
|
||||
class Hash_console_wtr_fxt {
|
||||
private Hash_algo__tth_192 algo;
|
||||
public Hash_console_wtr_fxt() {
|
||||
this.algo = new Hash_algo__tth_192();
|
||||
algo.BlockSize_set(10);
|
||||
}
|
||||
public void Test__Status(int count, String... expd) {
|
||||
// init
|
||||
Console_adp__mem console = Console_adp_.Dev();
|
||||
|
||||
// exec
|
||||
String data = String_.Repeat("A", count);
|
||||
IoStream stream = IoStream_.mem_txt_(Io_url_.Empty, data);
|
||||
calc.Hash_stream_as_str(dialog, stream);
|
||||
String[] actlWritten = dialog.Written().To_str_ary();
|
||||
Tfds.Eq_ary(actlWritten, expdWritten);
|
||||
algo.Calc_hash_w_prog_as_str(stream, console);
|
||||
|
||||
// test
|
||||
String[] actl = console.Written().To_str_ary();
|
||||
Tfds.Eq_ary(actl, expd);
|
||||
}
|
||||
String[] stringAry_(String... ary) {return ary;}
|
||||
Hash_algo calc;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import java.util.zip.Checksum;
|
||||
public class Jre_checksum_algo implements Hash_algo {
|
||||
private final Jre_checksum_factory factory;
|
||||
private final Checksum checksum;
|
||||
public Jre_checksum_algo(Jre_checksum_factory factory, String key) {
|
||||
this.factory = factory;
|
||||
this.key = key;
|
||||
this.checksum = factory.New_Checksum(key);
|
||||
}
|
||||
public String Key() {return key;} private final String key;
|
||||
public Hash_algo Clone_hash_algo() {return new Jre_checksum_algo(factory, key);}
|
||||
public void Update_digest(byte[] bry, int bgn, int end) {checksum.update(bry, bgn, end - bgn);}
|
||||
public byte[] To_hash_bry() {
|
||||
long val = checksum.getValue();
|
||||
String rv = Long.toHexString(val);
|
||||
return Bry_.new_u8(rv.length() < 8 ? String_.PadBgn(rv, 8, "0") : rv);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
import java.util.zip.Adler32;
|
||||
public class Jre_checksum_factory implements Hash_algo_factory {
|
||||
public Hash_algo New_hash_algo(String key) {
|
||||
return new Jre_checksum_algo(this, key);
|
||||
}
|
||||
|
||||
public Checksum New_Checksum(String key) {
|
||||
if (String_.Eq(key, Key__adler32)) return new Adler32();
|
||||
else if (String_.Eq(key, Key__crc32)) return new CRC32();
|
||||
else throw Err_.new_unhandled(key);
|
||||
}
|
||||
|
||||
public static String
|
||||
Key__adler32 = "adler32", Key__crc32 = "crc32"
|
||||
;
|
||||
public static final Jre_checksum_factory Instance = new Jre_checksum_factory(); Jre_checksum_factory() {}
|
||||
}
|
33
100_core/src/gplx/core/security/algos/jre/Jre_hash_algo.java
Normal file
33
100_core/src/gplx/core/security/algos/jre/Jre_hash_algo.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import java.security.MessageDigest;
|
||||
public class Jre_hash_algo implements Hash_algo {
|
||||
private final Jre_hash_factory factory;
|
||||
private final MessageDigest md;
|
||||
public Jre_hash_algo(Jre_hash_factory factory, String key) {
|
||||
this.factory = factory;
|
||||
this.key = key;
|
||||
this.md = factory.New_algo_under(key);
|
||||
}
|
||||
public String Key() {return key;} private final String key;
|
||||
public Hash_algo Clone_hash_algo() {return new Jre_hash_algo(factory, key);}
|
||||
public void Update_digest(byte[] bry, int bgn, int end) {md.update(bry, bgn, end - bgn);}
|
||||
public byte[] To_hash_bry() {
|
||||
byte[] md_bry = md.digest();
|
||||
return gplx.core.encoders.Hex_utl_.Encode_bry(md_bry);
|
||||
}
|
||||
}
|
@ -13,9 +13,9 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*;
|
||||
public class Hash_algo__md5__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors
|
||||
public class Jre_hash_algo__md5__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/hash/md5/Md5-128.unverified.test-vectors
|
||||
private final Hash_algo__fxt fxt = new Hash_algo__fxt(Hash_algo_.New__md5());
|
||||
@Test public void Empty() {fxt.Test__hash("d41d8cd98f00b204e9800998ecf8427e", "");}
|
||||
@Test public void a() {fxt.Test__hash("0cc175b9c0f1b6a831c399e269772661", "a");}
|
||||
@ -29,11 +29,3 @@ public class Hash_algo__md5__tst { // REF: https://www.cosic.esat.kuleuven.be/ne
|
||||
//@Test
|
||||
public void A__x_1million() {fxt.Test__hash("7707d6ae4e027c70eea2a935c2296f21", String_.Repeat("a", 1000000));}
|
||||
}
|
||||
class Hash_algo__fxt {
|
||||
private final Hash_algo algo;
|
||||
public Hash_algo__fxt(Hash_algo algo) {this.algo = algo;}
|
||||
public void Test__hash(String expd, String raw) {
|
||||
Tfds.Eq(expd, algo.Hash_bry_as_str(Bry_.new_u8(raw)));
|
||||
Tfds.Eq(expd, algo.Hash_stream_as_str(gplx.core.consoles.Console_adp_.Noop, gplx.core.ios.streams.IoStream_.mem_txt_(Io_url_.Empty, raw)));
|
||||
}
|
||||
}
|
@ -13,9 +13,9 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*;
|
||||
public class Hash_algo__sha1__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/
|
||||
public class Jre_hash_algo__sha1__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/
|
||||
private final Hash_algo__fxt fxt = new Hash_algo__fxt(Hash_algo_.New__sha1());
|
||||
@Test public void Empty() {fxt.Test__hash("da39a3ee5e6b4b0d3255bfef95601890afd80709", "");}
|
||||
@Test public void a() {fxt.Test__hash("86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a");}
|
@ -13,9 +13,9 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import org.junit.*;
|
||||
public class Hash_algo__sha2_256__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/
|
||||
public class Jre_hash_algo__sha2_256__tst { // REF: https://www.cosic.esat.kuleuven.be/nessie/testvectors/
|
||||
private final Hash_algo__fxt fxt = new Hash_algo__fxt(Hash_algo_.New__sha2_256());
|
||||
@Test public void Empty() {fxt.Test__hash("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "");}
|
||||
@Test public void a() {fxt.Test__hash("ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", "a");}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.security.algos.jre; import gplx.*; import gplx.core.*; import gplx.core.security.*; import gplx.core.security.algos.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
public class Jre_hash_factory implements Hash_algo_factory {
|
||||
public Hash_algo New_hash_algo(String key) {
|
||||
return new Jre_hash_algo(this, key);
|
||||
}
|
||||
|
||||
public MessageDigest New_algo_under(String key) {
|
||||
try {return MessageDigest.getInstance(key);}
|
||||
catch (NoSuchAlgorithmException e) {throw Err_.new_missing_key(key);}
|
||||
}
|
||||
|
||||
public static String
|
||||
Key__md5 = "md5", Key__sha1 = "sha1", Key__sha2_256 = "sha-256"
|
||||
;
|
||||
public static final Jre_hash_factory Instance = new Jre_hash_factory(); Jre_hash_factory() {}
|
||||
}
|
@ -37,7 +37,9 @@ public interface String_bldr {
|
||||
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_mid(String str, int bgn, int end);
|
||||
String_bldr Add_mid_len(char[] ary, int bgn, int count);
|
||||
String_bldr Add_mid_len(String str, int bgn, int count);
|
||||
String_bldr Add_at(int idx, String s);
|
||||
String_bldr Del(int bgn, int len);
|
||||
}
|
||||
@ -82,7 +84,9 @@ abstract class String_bldr_base implements String_bldr {
|
||||
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_mid(String str, int bgn, int end);
|
||||
public abstract String_bldr Add_mid_len(char[] ary, int bgn, int count);
|
||||
public abstract String_bldr Add_mid_len(String str, int bgn, int count);
|
||||
public abstract String_bldr Add_obj(Object o);
|
||||
public abstract String_bldr Del(int bgn, int len);
|
||||
}
|
||||
@ -95,7 +99,9 @@ class String_bldr_thread_single extends String_bldr_base {
|
||||
@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_mid(String str, int bgn, int end) {sb.append(str, bgn, end); return this;}
|
||||
@Override public String_bldr Add_mid_len(char[] ary, int bgn, int count) {sb.append(ary, bgn, count); return this;}
|
||||
@Override public String_bldr Add_mid_len(String str, int bgn, int count) {sb.append(str, 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;}
|
||||
}
|
||||
@ -108,7 +114,9 @@ class String_bldr_thread_multiple extends String_bldr_base {
|
||||
@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_mid(String str, int bgn, int end) {sb.append(str, bgn, end); return this;}
|
||||
@Override public String_bldr Add_mid_len(char[] ary, int bgn, int count) {sb.append(ary, bgn, count); return this;}
|
||||
@Override public String_bldr Add_mid_len(String str, int bgn, int count) {sb.append(str, 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;}
|
||||
}
|
||||
|
17
100_core/src/gplx/core/tests/GfoTestMethod.java
Normal file
17
100_core/src/gplx/core/tests/GfoTestMethod.java
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests;
|
||||
public @interface GfoTestMethod {}
|
54
100_core/src/gplx/core/tests/Gfo_test_err_mgr.java
Normal file
54
100_core/src/gplx/core/tests/Gfo_test_err_mgr.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
public class Gfo_test_err_mgr {
|
||||
private final List_adp expd = List_adp_.New();
|
||||
public void Init() {
|
||||
Gfo_usr_dlg_.Test__list__init();
|
||||
expd.Clear();
|
||||
}
|
||||
public void Term() {
|
||||
Gfo_usr_dlg_.Instance = Gfo_usr_dlg_.Noop;
|
||||
}
|
||||
public void Add_expd(boolean contains, String msg) {
|
||||
Object[] itm = new Object[] {contains, msg};
|
||||
expd.Add(itm);
|
||||
}
|
||||
public void Test() {
|
||||
List_adp actl = ((Gfo_usr_dlg__gui_mock)Gfo_usr_dlg_.Instance.Gui_wkr()).Warns();
|
||||
int expd_len = expd.Len();
|
||||
int actl_len = actl.Len();
|
||||
if (expd_len == 0 && actl_len == 0) {}
|
||||
else if (actl_len == 0) {
|
||||
Gftest.Fail("expected some errors; got zero; expd={0}", expd.To_str());
|
||||
}
|
||||
else if (expd_len == 0) {
|
||||
Gftest.Fail("expected zero errors; got some; actl={0}", actl.To_str());
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < actl_len; i++) {
|
||||
String actl_err = (String)actl.Get_at(i);
|
||||
Object[] expd_err_ary = (Object[])expd.Get_at(i);
|
||||
if (Bool_.Cast(expd_err_ary[0])) {
|
||||
Gftest.Eq__bool(true, String_.Has(actl_err, (String)expd_err_ary[1]));
|
||||
}
|
||||
else {
|
||||
Gftest.Eq__str((String)expd_err_ary[1], (String)actl_err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
104
100_core/src/gplx/core/tests/Gfo_test_itm.java
Normal file
104
100_core/src/gplx/core/tests/Gfo_test_itm.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.strings.*;
|
||||
public class Gfo_test_itm {
|
||||
private final boolean is_expd;
|
||||
private final Ordered_hash hash = Ordered_hash_.New();
|
||||
Gfo_test_itm(boolean is_expd) {
|
||||
this.is_expd = is_expd;
|
||||
}
|
||||
public int Len() {return hash.Len();}
|
||||
public Gfo_test_itm Add(String key, Object val) {hash.Add(key, Keyval_.new_(key, val)); return this;}
|
||||
private Object Get_by_val(String key) {return ((Keyval)hash.Get_by_or_fail(key)).Val();}
|
||||
public String Get_str(String key) {
|
||||
Object val_obj = Get_by_val(key);
|
||||
if (Type_.Eq_by_obj(val_obj, byte[].class)) {
|
||||
return String_.new_u8((byte[])val_obj);
|
||||
}
|
||||
else
|
||||
return (String)val_obj;
|
||||
}
|
||||
public void Test_bool(String key, boolean val) {
|
||||
boolean cur = Bool_.Cast(Get_by_val(key));
|
||||
boolean expd = is_expd ? cur : val;
|
||||
boolean actl = is_expd ? val : cur;
|
||||
Gftest.Eq__bool(expd, actl);
|
||||
}
|
||||
public void Test_bry(String key, byte[] val) {
|
||||
byte[] cur = (byte[])Get_by_val(key);
|
||||
byte[] expd = is_expd ? cur : val;
|
||||
byte[] actl = is_expd ? val : cur;
|
||||
Gftest.Eq__bry(expd, actl);
|
||||
}
|
||||
public void Test_long(String key, long val) {
|
||||
long cur = Long_.cast(Get_by_val(key));
|
||||
long expd = is_expd ? cur : val;
|
||||
long actl = is_expd ? val : cur;
|
||||
Gftest.Eq__long(expd, actl);
|
||||
}
|
||||
public void Test_int(String key, int val) {
|
||||
int cur = Int_.Cast(Get_by_val(key));
|
||||
int expd = is_expd ? cur : val;
|
||||
int actl = is_expd ? val : cur;
|
||||
Gftest.Eq__int(expd, actl);
|
||||
}
|
||||
public void Test_byte(String key, byte val) {
|
||||
byte cur = Byte_.Cast(Get_by_val(key));
|
||||
byte expd = is_expd ? cur : val;
|
||||
byte actl = is_expd ? val : cur;
|
||||
Gftest.Eq__byte(expd, actl);
|
||||
}
|
||||
public void Test_str(String key, String val) {
|
||||
String cur = String_.cast(Get_by_val(key));
|
||||
String expd = is_expd ? cur : val;
|
||||
String actl = is_expd ? val : cur;
|
||||
Gftest.Eq__str(expd, actl);
|
||||
}
|
||||
public void Test_actl(Gfo_test_itm actl) {
|
||||
int expd_len = hash.Len();
|
||||
String[] expd_ary = new String[expd_len];
|
||||
String[] actl_ary = new String[expd_len];
|
||||
for (int i = 0; i < expd_len; i++) {
|
||||
Keyval expd_kv = (Keyval)hash.Get_at(i);
|
||||
String key = expd_kv.Key();
|
||||
expd_ary[i] = Object_.Xto_str_strict_or_null(expd_kv.Val());
|
||||
|
||||
Keyval actl_kv = (Keyval)actl.hash.Get_by(key);
|
||||
actl_ary[i] = actl_kv == null ? "MISSING" : Object_.Xto_str_strict_or_null(actl_kv.Val());
|
||||
}
|
||||
Gftest.Eq__ary(expd_ary, actl_ary);
|
||||
}
|
||||
public String To_str(boolean single_line) {
|
||||
String_bldr bldr = String_bldr_.new_();
|
||||
int len = hash.Len();
|
||||
String itm_dlm = single_line ? ";" : "\n";
|
||||
for (int i = 0; i < len; i++) {
|
||||
Object itm = hash.Get_at(i);
|
||||
int itm_tid = Type_ids_.To_id_by_obj(itm);
|
||||
if (itm_tid == Type_ids_.Id__bry)
|
||||
itm = String_.new_u8((byte[])itm);
|
||||
bldr.Add_obj(itm);
|
||||
bldr.Add(itm_dlm);
|
||||
}
|
||||
return bldr.To_str();
|
||||
}
|
||||
@Override public String toString() {
|
||||
return this.To_str(true);
|
||||
}
|
||||
public static Gfo_test_itm New__actl() {return new Gfo_test_itm(false);}
|
||||
public static Gfo_test_itm New__expd() {return new Gfo_test_itm(true);}
|
||||
}
|
41
100_core/src/gplx/core/tests/Gfo_test_list_base.java
Normal file
41
100_core/src/gplx/core/tests/Gfo_test_list_base.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.strings.*;
|
||||
public class Gfo_test_list_base {
|
||||
private final List_adp expd = List_adp_.New();
|
||||
public void Clear() {expd.Clear();}
|
||||
public void Add(Object itm) {expd.Add(itm);}
|
||||
public void Test(Object actl_obj) {
|
||||
int len = expd.Len();
|
||||
if (len == 0) { // nothing expd; return "pass"
|
||||
return;
|
||||
}
|
||||
|
||||
String actl = Type_.Is_assignable_from_by_obj(actl_obj, List_adp.class) ? To_str((List_adp)actl_obj) : actl_obj.toString();
|
||||
Gftest.Eq__ary__lines(To_str(expd), actl );
|
||||
}
|
||||
private static String To_str(List_adp list) {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int len = list.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Object obj = list.Get_at(i);
|
||||
String str = Object_.Xto_str_strict_or_null_mark(obj);
|
||||
sb.Add(str).Add_char_nl();
|
||||
}
|
||||
return sb.To_str_and_clear();
|
||||
}
|
||||
}
|
69
100_core/src/gplx/core/tests/Gfo_test_lnr_base.java
Normal file
69
100_core/src/gplx/core/tests/Gfo_test_lnr_base.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.strings.*;
|
||||
public class Gfo_test_lnr_base {
|
||||
private String[] keys;
|
||||
public List_adp Expd() {return expd_list;} private final List_adp expd_list = List_adp_.New();
|
||||
public List_adp Actl() {return actl_list;} private final List_adp actl_list = List_adp_.New();
|
||||
public void Clear() {
|
||||
expd_list.Clear();
|
||||
actl_list.Clear();
|
||||
}
|
||||
public void Add_actl_args(Object... vals) {
|
||||
int len = vals.length;
|
||||
Gfo_test_itm itm = Gfo_test_itm.New__actl();
|
||||
for (int i = 0; i < len; i++) {
|
||||
itm.Add(keys[i], vals[i]);
|
||||
}
|
||||
actl_list.Add(itm);
|
||||
}
|
||||
public void Test() {Test(null);}
|
||||
public void Test(Gfo_test_lnr_itm_cbk cbk) {
|
||||
int expd_len = expd_list.Len();
|
||||
int actl_len = actl_list.Len();
|
||||
if (expd_len == 0 && actl_len == 0) {}
|
||||
else if (actl_len == 0) {
|
||||
Gftest.Fail("expected some itms; got zero; expd={0}", expd_list.To_str());
|
||||
}
|
||||
else if (expd_len == 0) {
|
||||
Gftest.Fail("expected zero itms; got some; actl={0}", actl_list.To_str());
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < actl_len; i++) {
|
||||
Gfo_test_itm expd_itm = (Gfo_test_itm)expd_list.Get_at(i);
|
||||
Gfo_test_itm actl_itm = (Gfo_test_itm)actl_list.Get_at(i);
|
||||
expd_itm.Test_actl(actl_itm);
|
||||
if (cbk != null)
|
||||
cbk.Test_itm(i, expd_len, expd_itm, actl_itm);
|
||||
}
|
||||
}
|
||||
}
|
||||
public String To_str() {
|
||||
String_bldr sb = String_bldr_.new_();
|
||||
int len = actl_list.Len();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Gfo_test_itm itm = (Gfo_test_itm)actl_list.Get_at(i);
|
||||
sb.Add(itm.To_str(true)).Add_char_nl();
|
||||
}
|
||||
return sb.To_str_and_clear();
|
||||
}
|
||||
public static Gfo_test_lnr_base New__keys(String... keys) {
|
||||
Gfo_test_lnr_base rv = new Gfo_test_lnr_base();
|
||||
rv.keys = keys;
|
||||
return rv;
|
||||
}
|
||||
}
|
19
100_core/src/gplx/core/tests/Gfo_test_lnr_itm_cbk.java
Normal file
19
100_core/src/gplx/core/tests/Gfo_test_lnr_itm_cbk.java
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
public interface Gfo_test_lnr_itm_cbk {
|
||||
void Test_itm(int i, int len, Gfo_test_itm expd_itm, Gfo_test_itm actl_itm);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -17,6 +17,9 @@ package gplx.core.tests; import gplx.*; import gplx.core.*;
|
||||
import gplx.core.brys.*;
|
||||
public class Gftest {
|
||||
private static final Bry_bfr bfr = Bry_bfr_.New();
|
||||
public static void Fail(String msg_fmt, Object... msg_args) {
|
||||
throw Err_.new_wo_type(String_.Format(msg_fmt, msg_args));
|
||||
}
|
||||
public static void Eq__ary(Object[] expd, Object[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__obj, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(boolean[] expd, boolean[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bool, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(int[] expd, int[] actl) {Eq__array(Type_ids_.Id__int, expd, actl, "");}
|
||||
@ -61,6 +64,7 @@ public class Gftest {
|
||||
if (actl == null) actl = Str__null;
|
||||
Eq__str(Object_.Xto_str_or(expd, Str__null), Object_.Xto_str_or(actl, null), Str__null);
|
||||
}
|
||||
public static void Eq__bry(byte[] expd, String actl) {Eq__str(String_.new_u8(expd), actl, "no_msg");}
|
||||
public static void Eq__str(String expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__str(expd, String_.new_u8(actl), msg_fmt, msg_args);}
|
||||
public static void Eq__str(String expd, byte[] actl) {Eq__str(expd, String_.new_u8(actl), null);}
|
||||
public static void Eq__str(String expd, String actl) {Eq__str(expd, actl, null);}
|
||||
@ -108,6 +112,7 @@ public class Gftest {
|
||||
bfr.Add(Bry__line_end);
|
||||
throw Err_.new_wo_type(bfr.To_str_and_clear());
|
||||
}
|
||||
public static void Eq__bool_n(boolean actl) {Eq__bool(Bool_.N, actl, null);}
|
||||
public static void Eq__bool_y(boolean actl) {Eq__bool(Bool_.Y, actl, null);}
|
||||
public static void Eq__bool_y(boolean actl, String msg_fmt, Object... msg_args) {Eq__bool(Bool_.Y, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__bool(boolean expd, boolean actl) {Eq__bool(expd, actl, null);}
|
||||
|
@ -22,6 +22,11 @@ public class Base64Converter {
|
||||
for(int i=0; i< ALPHABET.length; i++){
|
||||
toInt[ALPHABET[i]]= i;
|
||||
}
|
||||
}
|
||||
public static char GetIndexChar(int i) {return ALPHABET[i];}
|
||||
public static int GetIndexInt(char c) {
|
||||
if (toInt == null) Init();
|
||||
return toInt[c];
|
||||
}
|
||||
public static String EncodeString(String orig) {return Encode(Bry_.new_u8(orig));}
|
||||
public static String Encode(byte[] buf){
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,8 +13,17 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.threads; import gplx.*; import gplx.core.*;
|
||||
import java.lang.*;
|
||||
package gplx.core.threads;
|
||||
|
||||
import gplx.Cancelable;
|
||||
import gplx.Cancelable_;
|
||||
import gplx.Err_;
|
||||
import gplx.GfoMsg;
|
||||
import gplx.GfoMsg_;
|
||||
import gplx.Gfo_invk;
|
||||
import gplx.Gfo_invk_;
|
||||
import gplx.Gfo_log_;
|
||||
|
||||
public class Thread_adp implements Runnable {
|
||||
private final String thread_name; private final Cancelable cxl; private final boolean cxlable;
|
||||
private final Gfo_invk invk_itm; private final String invk_cmd; private final GfoMsg invk_msg;
|
||||
@ -28,6 +37,7 @@ public class Thread_adp implements Runnable {
|
||||
public boolean Thread__cancelable() {return cxlable;}
|
||||
public boolean Thread__is_alive() {return thread == null ? false : thread.isAlive();}
|
||||
public void Thread__interrupt() {thread.interrupt();}
|
||||
public void Thread__stop() {thread.stop();}
|
||||
public void run() {
|
||||
try {
|
||||
Gfo_invk_.Invk_by_msg(invk_itm, invk_cmd, invk_msg);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2020 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,7 +13,15 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.core.threads; import gplx.*; import gplx.core.*;
|
||||
package gplx.core.threads;
|
||||
|
||||
import gplx.Cancelable;
|
||||
import gplx.Cancelable_;
|
||||
import gplx.Err_;
|
||||
import gplx.GfoMsg;
|
||||
import gplx.GfoMsg_;
|
||||
import gplx.Gfo_invk;
|
||||
|
||||
public class Thread_adp_ {
|
||||
public static void Sleep(int milliseconds) {
|
||||
try {
|
||||
|
78
100_core/src/gplx/core/tooling/asserts/TestAssert.java
Normal file
78
100_core/src/gplx/core/tooling/asserts/TestAssert.java
Normal file
@ -0,0 +1,78 @@
|
||||
package gplx.core.tooling.asserts;
|
||||
|
||||
import gplx.core.tests.Gftest;
|
||||
import gplx.core.tooling.dataCollectors.GfoDataCollectorGrp;
|
||||
import gplx.core.tooling.dataCollectors.GfoDataCollectorMgr;
|
||||
import gplx.langs.java.util.List_;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TestAssert {
|
||||
void Test(GfoDataCollectorGrp actlItm);
|
||||
void NotePrepend(String s);
|
||||
static void Test(String note, GfoDataCollectorMgr mgr, TestAssert.Grp[] itms) {
|
||||
for (TestAssert.Grp itm : itms) {
|
||||
itm.NotePrepend(note);
|
||||
itm.Test(mgr.GetGrp(itm.Key()));
|
||||
}
|
||||
}
|
||||
class Grp implements TestAssert {
|
||||
private String key;
|
||||
private TestAssert[] rules;
|
||||
public Grp(String key, TestAssert... rules) {
|
||||
this.key = key;
|
||||
this.rules = rules;
|
||||
}
|
||||
public String Key() {return key;}
|
||||
public void NotePrepend(String s) {
|
||||
note = s;
|
||||
for (TestAssert rule : rules) {
|
||||
rule.NotePrepend(s);
|
||||
}
|
||||
} private String note;
|
||||
public void Test(GfoDataCollectorGrp grp) {
|
||||
for (TestAssert rule : rules) {
|
||||
rule.Test(grp);
|
||||
}
|
||||
}
|
||||
}
|
||||
class StringEq implements TestAssert {
|
||||
private String key;
|
||||
private String expdVal;
|
||||
public StringEq(String key, String expd) {
|
||||
this.key = key;
|
||||
this.expdVal = expd;
|
||||
}
|
||||
public void NotePrepend(String s) {note = s + "." + key;} private String note;
|
||||
public void Test(GfoDataCollectorGrp grp) {
|
||||
String actlVal = (String)grp.Get(key);
|
||||
Gftest.Eq__str(expdVal, actlVal, note);
|
||||
}
|
||||
}
|
||||
class StringHas implements TestAssert {
|
||||
private String key;
|
||||
private String expdVal;
|
||||
public StringHas(String key, String expd) {
|
||||
this.key = key;
|
||||
this.expdVal = expd;
|
||||
}
|
||||
public void NotePrepend(String s) {note = s + "." + key;} private String note;
|
||||
public void Test(GfoDataCollectorGrp grp) {
|
||||
String actlVal = (String)grp.Get(key);
|
||||
Gftest.Eq__bool_y(actlVal.contains(expdVal), note);
|
||||
}
|
||||
}
|
||||
class ListEq implements TestAssert {
|
||||
private String key;
|
||||
private List<?> expdList;
|
||||
public ListEq(String key, Object... expd) {
|
||||
this.key = key;
|
||||
this.expdList = List_.NewByAry(expd);
|
||||
}
|
||||
public void NotePrepend(String s) {note = s + "." + key;} private String note;
|
||||
public void Test(GfoDataCollectorGrp grp) {
|
||||
List<?> actlList = (List<?>)grp.Get(key);
|
||||
Gftest.Eq__ary(expdList.toArray(), actlList.toArray(), note);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package gplx.core.tooling.dataCollectors;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class GfoDataCollectorGrp {
|
||||
private final String key;
|
||||
private final LinkedHashMap<String, Object> hash = new LinkedHashMap<>();
|
||||
public GfoDataCollectorGrp(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
public String Key() {return key;}
|
||||
public GfoDataCollectorGrp Add(String dataKey, String dataVal) {
|
||||
hash.put(dataKey, dataVal);
|
||||
return this;
|
||||
}
|
||||
public GfoDataCollectorGrp Add(String dataKey, List<?> dataVal) {
|
||||
hash.put(dataKey, dataVal);
|
||||
return this;
|
||||
}
|
||||
public Object Get(String dataKey) {
|
||||
return hash.get(dataKey);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package gplx.core.tooling.dataCollectors;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class GfoDataCollectorMgr {
|
||||
private final LinkedHashMap<String, GfoDataCollectorGrp> hash = new LinkedHashMap<>();
|
||||
public GfoDataCollectorGrp GetGrp(String grpKey) {return hash.get(grpKey);}
|
||||
public GfoDataCollectorGrp AddGrp(String grpKey) {
|
||||
GfoDataCollectorGrp grp = new GfoDataCollectorGrp(grpKey);
|
||||
hash.put(grpKey, grp);
|
||||
return grp;
|
||||
}
|
||||
}
|
13
100_core/src/gplx/langs/java/util/List_.java
Normal file
13
100_core/src/gplx/langs/java/util/List_.java
Normal file
@ -0,0 +1,13 @@
|
||||
package gplx.langs.java.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class List_ {
|
||||
public static List<Object> NewByAry(Object[] ary) {
|
||||
List<Object> rv = new ArrayList<>();
|
||||
for (Object o : ary)
|
||||
rv.add(o);
|
||||
return rv;
|
||||
}
|
||||
}
|
@ -17,7 +17,10 @@ package gplx.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
public class Regx_adp {
|
||||
@gplx.Internal protected Regx_adp(String regx) {Pattern_(regx);}
|
||||
public Regx_adp(String regx, int flags) {
|
||||
this.flags = flags;
|
||||
Pattern_(regx);
|
||||
}
|
||||
public String Pattern() {return pattern;} public Regx_adp Pattern_(String val) {pattern = val; Under_sync(); return this;} private String pattern;
|
||||
public boolean Pattern_is_invalid() {return pattern_is_invalid;} private boolean pattern_is_invalid = false;
|
||||
public Exception Pattern_is_invalid_exception() {return pattern_is_invalid_exception;} private Exception pattern_is_invalid_exception = null;
|
||||
@ -38,14 +41,15 @@ public class Regx_adp {
|
||||
}
|
||||
return (Regx_match[])rv.To_ary(Regx_match.class);
|
||||
}
|
||||
private int flags = FLAG__DOTALL | FLAG__UNICODE_CHARACTER_CLASS;// JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
|
||||
private Pattern under;
|
||||
public Pattern Under() {return under;}
|
||||
private void Under_sync() {
|
||||
try {under = Pattern.compile(pattern, Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);} // JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
|
||||
try {under = Pattern.compile(pattern, flags);}
|
||||
catch (Exception e) { // NOTE: if invalid, then default to empty pattern (which should return nothing); EX:d:〆る generates [^]; DATE:2013-10-20
|
||||
pattern_is_invalid = true;
|
||||
pattern_is_invalid_exception = e;
|
||||
under = Pattern.compile("", Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);
|
||||
under = Pattern.compile("", flags);
|
||||
}
|
||||
}
|
||||
public Regx_match Match(String input, int bgn) {
|
||||
@ -56,11 +60,29 @@ public class Regx_adp {
|
||||
Regx_group[] ary = Regx_group.Ary_empty;
|
||||
int groups_len = match.groupCount();
|
||||
if (success && groups_len > 0) {
|
||||
// NOTE: by convention, there are n groups, but groups.count is n - 1 and groups[0] is entire match (not 1st group); see TEST: DATE:2019-12-28
|
||||
groups_len++;
|
||||
ary = new Regx_group[groups_len];
|
||||
for (int i = 0; i < groups_len; i++)
|
||||
ary[i] = new Regx_group(true, match.start(i + 1), match.end(i + 1), match.group(i + 1));
|
||||
for (int i = 0; i < groups_len; i++) {
|
||||
int match_start = match.start(i);
|
||||
ary[i] = new Regx_group(match_start != -1, match_start, match.end(i), match.group(i));
|
||||
}
|
||||
}
|
||||
return new Regx_match(success, match_bgn, match_end, ary);
|
||||
}
|
||||
public String ReplaceAll(String input, String replace) {return under.matcher(input).replaceAll(replace);}
|
||||
// https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
|
||||
public static final int
|
||||
FLAG__NONE = 0
|
||||
, FLAG__UNIX_LINES = Pattern.UNIX_LINES
|
||||
, FLAG__CASE_INSENSITIVE = Pattern.CASE_INSENSITIVE
|
||||
, FLAG__COMMENTS = Pattern.COMMENTS
|
||||
, FLAG__MULTILINE = Pattern.MULTILINE
|
||||
, FLAG__LITERAL = Pattern.LITERAL
|
||||
, FLAG__DOTALL = Pattern.DOTALL
|
||||
, FLAG__UNICODE_CASE = Pattern.UNICODE_CASE
|
||||
, FLAG__CANON_EQ = Pattern.CANON_EQ
|
||||
, FLAG__UNICODE_CHARACTER_CLASS = Pattern.UNICODE_CHARACTER_CLASS
|
||||
;
|
||||
public static final int FLAG__DEFAULT = FLAG__DOTALL | FLAG__UNICODE_CHARACTER_CLASS;// JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
|
||||
}
|
||||
|
@ -15,18 +15,17 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.langs.regxs; import gplx.*; import gplx.langs.*;
|
||||
public class Regx_adp_ {
|
||||
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern);}
|
||||
public static List_adp Find_all(String input, String find) {
|
||||
Regx_adp regx = Regx_adp_.new_(find);
|
||||
int idx = 0;
|
||||
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern, Regx_adp.FLAG__DEFAULT);}
|
||||
public static List_adp Find_all(String src, String pat) {
|
||||
int src_len = String_.Len(src);
|
||||
Regx_adp regx = Regx_adp_.new_(pat);
|
||||
int pos = 0;
|
||||
List_adp rv = List_adp_.New();
|
||||
while (true) {
|
||||
Regx_match match = regx.Match(input, idx);
|
||||
while (pos < src_len) {
|
||||
Regx_match match = regx.Match(src, pos);
|
||||
if (match.Rslt_none()) break;
|
||||
rv.Add(match);
|
||||
int findBgn = match.Find_bgn();
|
||||
idx = findBgn + match.Find_len();
|
||||
if (idx > String_.Len(input)) break;
|
||||
pos = match.Find_bgn() + match.Find_len();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -35,7 +34,7 @@ public class Regx_adp_ {
|
||||
return regx.ReplaceAll(raw, replace);
|
||||
}
|
||||
public static boolean Match(String input, String pattern) {
|
||||
Regx_adp rv = new Regx_adp(pattern);
|
||||
Regx_adp rv = new Regx_adp(pattern, Regx_adp.FLAG__DEFAULT);
|
||||
return rv.Match(input, 0).Rslt();
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,9 @@ public class Regx_adp__tst implements TfdsEqListItmStr {
|
||||
tst_Matches("b", "a b c b a b b", matches_(2, 6, 10, 12)); // BUGFIX: multiple entries did not work b/c of += instead of +
|
||||
}
|
||||
@Test public void Groups() {
|
||||
tst_Groups("abc def ghi dz", "(d\\p{L}+)", "def", "dz");
|
||||
tst_Groups("abc def ghi dz", "(d\\p{L}+)", "def", "def", "dz", "dz");
|
||||
tst_Groups("abc def", "(de)(g?)", "de", "de", ""); // NOTE: (g?) doesn't capture anything, but still add a group for it; DATE:2019-12-28
|
||||
tst_Groups("-123.456", "^-?(([0-9]+)(?:\\.([0-9]+))?)", "-123.456", "123.456", "123", "456"); // NOTE: -123.456 captured even though it's not part of a group; DATE:2019-12-28
|
||||
}
|
||||
Regx_match[] matches_(int... bgnAry) {
|
||||
int aryLen = Array_.Len(bgnAry);
|
||||
|
@ -26,6 +26,7 @@ public class Regx_match {
|
||||
public int Find_bgn() {return find_bgn;} private final int find_bgn;
|
||||
public int Find_end() {return find_end;} private final int find_end;
|
||||
public int Find_len() {return find_end - find_bgn;}
|
||||
public String Find_str(String s) {return String_.Mid(s, find_bgn, find_end);}
|
||||
public Regx_group[] Groups() {return groups;} private final Regx_group[] groups;
|
||||
|
||||
public static final Regx_match[] Ary_empty = new Regx_match[0];
|
||||
|
@ -22,6 +22,11 @@ public class XmlAtrList {
|
||||
Node xatr = list.getNamedItem(key);
|
||||
return (xatr == null) ? or : xatr.getNodeValue();
|
||||
}
|
||||
public XmlAtr Get_by(String key) {
|
||||
Node xatr = list.getNamedItem(key);
|
||||
if (xatr == null) throw Err_.new_missing_key(key);
|
||||
return new XmlAtr(xatr);
|
||||
}
|
||||
public XmlAtr Fetch(String key) {
|
||||
Node xatr = list.getNamedItem(key); if (xatr == null) throw Err_.new_missing_key(key);
|
||||
return new XmlAtr(xatr);
|
||||
|
@ -29,15 +29,45 @@ import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
public class XmlDoc_ {
|
||||
public static XmlNdeList Select_tags(XmlNde cur, String tag) {
|
||||
XmlNdeList_cls_list rv = new XmlNdeList_cls_list(4); // NOTE: pass in an initial amount; do not pass 0
|
||||
Select_tags(rv, cur, tag);
|
||||
return rv;
|
||||
}
|
||||
private static void Select_tags(XmlNdeList_cls_list rv, XmlNde cur, String tag) {
|
||||
if (String_.Eq(cur.Name(), tag)) {
|
||||
rv.Add(cur);
|
||||
}
|
||||
XmlNdeList sub_ndes = cur.SubNdes();
|
||||
int sub_ndes_len = sub_ndes.Count();
|
||||
for (int i = 0; i < sub_ndes_len; i++) {
|
||||
XmlNde sub_nde = sub_ndes.Get_at(i);
|
||||
Select_tags(rv, sub_nde, tag);
|
||||
}
|
||||
}
|
||||
public static XmlDoc parse(String raw) {return new XmlDoc(doc_(raw));}
|
||||
static Document doc_(String raw) {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder bldr = null;
|
||||
try {bldr = factory.newDocumentBuilder();}
|
||||
catch (ParserConfigurationException e) {throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");}
|
||||
try {
|
||||
// NOTE: disable DTD validation else errors for "ldmlSupplemental.dtd" in plurals.xml; DATE:2020-01-01
|
||||
// REF:https://stackoverflow.com/questions/24744175/non-validating-documentbuilder-trying-to-read-dtd-file
|
||||
// REF:https://stackoverflow.com/questions/6204827/xml-parsing-too-slow
|
||||
factory.setNamespaceAware(false);
|
||||
factory.setValidating(false);
|
||||
factory.setFeature("http://xml.org/sax/features/namespaces", false);
|
||||
factory.setFeature("http://xml.org/sax/features/validation", false);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
bldr = factory.newDocumentBuilder();
|
||||
}
|
||||
catch (ParserConfigurationException e) {
|
||||
throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");
|
||||
}
|
||||
StringReader reader = new StringReader(raw);
|
||||
InputSource source = new InputSource(reader);
|
||||
Document doc = null;
|
||||
@ -48,4 +78,3 @@ public class XmlDoc_ {
|
||||
}
|
||||
public static final String Err_XmlException = "gplx.xmls.XmlException";
|
||||
}
|
||||
//#}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user