mirror of
https://github.com/gnosygnu/xowa.git
synced 2025-06-13 12:54:14 +00:00
Compare commits
460 Commits
v4.5.21.18
...
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 | ||
|
04c7326b1d | ||
|
2dfa751958 | ||
|
ef0300dfeb | ||
|
14d978e2af | ||
|
9b5d585750 | ||
|
71232e4402 | ||
|
ab4cbbd3c1 | ||
|
ca8c4ce5a4 | ||
|
82bee2e877 | ||
|
4f22548121 | ||
|
ad317bd90e | ||
|
a94a9f0c7f | ||
|
41deb3c0c1 | ||
|
8ef5854eb7 | ||
|
4cd23b9827 | ||
|
92927687a5 | ||
|
7d747b6d28 | ||
|
bafa4e31dd | ||
|
91a100f154 | ||
|
dd750c6c4e | ||
|
0eabd9efc2 | ||
|
992cde7e71 | ||
|
f40f227454 | ||
|
790e82ac9e | ||
|
beab14117e | ||
|
a70131254f | ||
|
5c724dc93d | ||
|
3488084eca | ||
|
3fd759b020 | ||
|
91cbb34fa5 | ||
|
c383f2a231 | ||
|
e744c5123a | ||
|
81ea765714 | ||
|
b822997638 | ||
|
be4d2fdfb4 | ||
|
a5f8b6e482 | ||
|
21309d66be | ||
|
298c83a806 | ||
|
2fa5d9bc03 | ||
|
78e8db95b9 | ||
|
e80dfc6adc | ||
|
571f0a2388 | ||
|
ba40cf6c69 | ||
|
cde0163ae7 | ||
|
ebfd7a8352 | ||
|
cd56234e28 | ||
|
4c47bb8793 | ||
|
739d302850 | ||
|
5daf74516a | ||
|
6b5c014e75 | ||
|
c32a4ae253 | ||
|
8b13930d30 | ||
|
46ec06986e | ||
|
29d82a5b88 | ||
|
560e3c9685 | ||
|
5fa8c20561 | ||
|
4626203f16 | ||
|
f44a1874a8 | ||
|
0ecb31575f | ||
|
aaa402119b | ||
|
5d8a139903 | ||
|
b3120bab39 | ||
|
a08f7f362d | ||
|
1517fcd585 | ||
|
bc60e09823 | ||
|
c4682aad9c | ||
|
f1c8fb3404 | ||
|
8412119902 | ||
|
2f3f84fba3 | ||
|
8cd39534a6 | ||
|
85478ad7e7 | ||
|
42d15b726c | ||
|
2b4320b302 | ||
|
9e5a13f54f | ||
|
e250331e97 | ||
|
cc502c872f | ||
|
e65d9268d6 | ||
|
b86228d6f2 | ||
|
87cb6b5a01 | ||
|
1f2b73699b | ||
|
1d54b8a756 | ||
|
54ad1d697d | ||
|
43ec6a8163 | ||
|
64cd27e9fe | ||
|
166963d767 | ||
|
089661a0bc | ||
|
af19381e3c | ||
|
3935d10b45 | ||
|
f151d7babf | ||
|
225959160c | ||
|
51e42d65ad | ||
|
333c507720 | ||
|
68fe39f5e1 | ||
|
8abb2cd0ee | ||
|
38bdc95acf | ||
|
2e5994788f | ||
|
50d1fbfed1 | ||
|
41773e586b | ||
|
dca2357067 | ||
|
6e361414f5 | ||
|
5137eda4fb | ||
|
9a81e1b593 | ||
|
5721913241 | ||
|
a672fd8340 | ||
|
0f89d3aa3a | ||
|
4cadd6b89b | ||
|
62f41ebbd3 | ||
|
a8f6fd0fb0 |
@ -1,4 +0,0 @@
|
||||
[Dolphin]
|
||||
Timestamp=2015,7,12,21,9,46
|
||||
Version=3
|
||||
ViewMode=1
|
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>
|
||||
|
@ -54,6 +54,15 @@ public class Array_ {
|
||||
Copy_to(src, 0, trg, 0, copy_len);
|
||||
return trg;
|
||||
}
|
||||
public static Object Extract_by_pos(Object src, int src_bgn) {
|
||||
return Extract_by_pos(src, src_bgn, Array.getLength(src));
|
||||
}
|
||||
public static Object Extract_by_pos(Object src, int src_bgn, int src_end) {
|
||||
int trg_len = src_end - src_bgn;
|
||||
Object trg = Create(Component_type(src), trg_len);
|
||||
Copy_to(src, src_bgn, trg, 0, src_end - src_bgn);
|
||||
return trg;
|
||||
}
|
||||
public static List_adp To_list(Object ary) {
|
||||
int aryLen = Array_.Len(ary);
|
||||
List_adp rv = List_adp_.New();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,295 +13,309 @@ 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;
|
||||
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.tests.*;
|
||||
public class Bry__tst {
|
||||
private final Bry__fxt fxt = new Bry__fxt();
|
||||
@Test public void new_ascii_() {
|
||||
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_a7("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_a7("" , Bry_.Empty); // none
|
||||
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ?
|
||||
}
|
||||
@Test public void new_u8() {
|
||||
fxt.Test_new_u8("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_u8("¢" , Bry_.New_by_ints(194, 162)); // bry_len=2; cent
|
||||
fxt.Test_new_u8("€" , Bry_.New_by_ints(226, 130, 172)); // bry_len=3; euro
|
||||
fxt.Test_new_u8("𤭢" , Bry_.New_by_ints(240, 164, 173, 162)); // bry_len=4; example from en.w:UTF-8
|
||||
}
|
||||
@Test public void Add__bry_plus_byte() {
|
||||
fxt.Test_add("a" , Byte_ascii.Pipe , "a|"); // basic
|
||||
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String
|
||||
}
|
||||
@Test public void Add__byte_plus_bry() {
|
||||
fxt.Test_add(Byte_ascii.Pipe , "a" , "|a"); // basic
|
||||
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String
|
||||
}
|
||||
@Test public void Add_w_dlm() {
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
|
||||
}
|
||||
@Test public void Add_w_dlm_bry() {
|
||||
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
|
||||
}
|
||||
@Test public void MidByPos() {
|
||||
tst_MidByPos("abcba", 0, 1, "a");
|
||||
tst_MidByPos("abcba", 0, 2, "ab");
|
||||
tst_MidByPos("abcba", 1, 4, "bcb");
|
||||
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Mid(Bry_.new_u8(src), bgn, end)));}
|
||||
@Test public void Replace_one() {
|
||||
tst_ReplaceOne("a" , "b" , "c" , "a");
|
||||
tst_ReplaceOne("b" , "b" , "c" , "c");
|
||||
tst_ReplaceOne("bb" , "b" , "c" , "cb");
|
||||
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
|
||||
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
|
||||
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Replace_one(Bry_.new_u8(src), Bry_.new_u8(find), Bry_.new_u8(repl))));}
|
||||
@Test public void XtoStrBytesByInt() {
|
||||
tst_XtoStrBytesByInt(0, 0);
|
||||
tst_XtoStrBytesByInt(9, 9);
|
||||
tst_XtoStrBytesByInt(10, 1, 0);
|
||||
tst_XtoStrBytesByInt(321, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(Int_.Max_value, 2,1,4,7,4,8,3,6,4,7);
|
||||
}
|
||||
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
|
||||
byte[] expd = new byte[expdAryAsInt.length];
|
||||
for (int i = 0; i < expd.length; i++) {
|
||||
int expdInt = expdAryAsInt[i];
|
||||
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Byte_ascii.To_a7_str(expdAryAsInt[i]);
|
||||
}
|
||||
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
|
||||
}
|
||||
@Test public void Has_at_end() {
|
||||
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
|
||||
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
|
||||
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
|
||||
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
|
||||
tst_HasAtEnd("abc", "bc", true); // y
|
||||
tst_HasAtEnd("abc", "bd", false); // n
|
||||
tst_HasAtEnd("a", "ab", false); // exceeds_len
|
||||
}
|
||||
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end));}
|
||||
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find)));}
|
||||
@Test public void Has_at_bgn() {
|
||||
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
|
||||
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
|
||||
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
|
||||
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
|
||||
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_bgn(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end), tst);}
|
||||
@Test public void Match() {
|
||||
tst_Match("abc", 0, "abc", true);
|
||||
tst_Match("abc", 2, "c", true);
|
||||
tst_Match("abc", 0, "cde", false);
|
||||
tst_Match("abc", 2, "abc", false); // bounds check
|
||||
tst_Match("abc", 0, "abcd", false);
|
||||
tst_Match("a" , 0, "", false);
|
||||
tst_Match("" , 0, "a", false);
|
||||
tst_Match("" , 0, "", true);
|
||||
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
|
||||
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_u8(src), srcPos, Bry_.new_u8(find)));}
|
||||
@Test public void ReadCsvStr() {
|
||||
tst_ReadCsvStr("a|" , "a");
|
||||
tst_ReadCsvStr("|a|", 1 , "a");
|
||||
Int_obj_ref bgn = Int_obj_ref.New_zero(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
|
||||
tst_ReadCsvStr("|", "");
|
||||
tst_ReadCsvStr_err("a");
|
||||
|
||||
tst_ReadCsvStr("'a'|" , "a");
|
||||
tst_ReadCsvStr("'a''b'|" , "a'b");
|
||||
tst_ReadCsvStr("'a|b'|" , "a|b");
|
||||
tst_ReadCsvStr("''|", "");
|
||||
tst_ReadCsvStr_err("''");
|
||||
tst_ReadCsvStr_err("'a'b'");
|
||||
tst_ReadCsvStr_err("'a");
|
||||
tst_ReadCsvStr_err("'a|");
|
||||
tst_ReadCsvStr_err("'a'");
|
||||
}
|
||||
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
|
||||
tst_XtoIntBy4Bytes(32, (byte)32); // space
|
||||
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // ∃
|
||||
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
|
||||
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
|
||||
}
|
||||
@Test public void XtoInt() {
|
||||
tst_XtoInt("1", 1);
|
||||
tst_XtoInt("123", 123);
|
||||
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("-1", Int_.Min_value, -1);
|
||||
tst_XtoInt("-123", Int_.Min_value, -123);
|
||||
tst_XtoInt("123-1", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("+123", Int_.Min_value, 123);
|
||||
tst_XtoInt("", -1);
|
||||
}
|
||||
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
|
||||
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.To_int_or(Bry_.new_u8(val), or));}
|
||||
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.To_int_by_a7(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.new_by_int(expd), "XbyInt");}
|
||||
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New_zero() , expd);}
|
||||
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New(bgn), expd);}
|
||||
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
|
||||
int bgn = bgnRef.Val();
|
||||
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
|
||||
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
|
||||
Tfds.Eq(expd, actl, "rv");
|
||||
if (rawHasQuotes) {
|
||||
int quoteAdj = String_.Count(actl, "'");
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
|
||||
}
|
||||
else
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
|
||||
}
|
||||
void tst_ReadCsvStr_err(String raw) {
|
||||
try {Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), Int_obj_ref.New_zero(), (byte)'|');}
|
||||
catch (Exception e) {Err_.Noop(e); return;}
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
@Test public void ReadCsvDte() {
|
||||
tst_ReadCsvDte("20110801 221435.987");
|
||||
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void ReadCsvInt() {
|
||||
tst_ReadCsvInt("1234567890");
|
||||
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.Parse(raw), Bry_.ReadCsvInt(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void Trim() {
|
||||
Trim_tst("a b c", 1, 4, "b");
|
||||
Trim_tst("a c", 1, 3, "");
|
||||
Trim_tst(" ", 0, 2, "");
|
||||
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Trim(Bry_.new_u8(raw), bgn, end)));}
|
||||
@Test public void Xto_int_lax() {
|
||||
tst_Xto_int_lax("12a", 12);
|
||||
tst_Xto_int_lax("1", 1);
|
||||
tst_Xto_int_lax("123", 123);
|
||||
tst_Xto_int_lax("a", 0);
|
||||
tst_Xto_int_lax("-1", -1);
|
||||
}
|
||||
private void tst_Xto_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__lax(Bry_.new_u8(val), 0, String_.Len(val), 0));}
|
||||
@Test public void To_int_or__trim_ws() {
|
||||
tst_Xto_int_trim("123 " , 123);
|
||||
tst_Xto_int_trim(" 123" , 123);
|
||||
tst_Xto_int_trim(" 123 " , 123);
|
||||
tst_Xto_int_trim(" 1 3 " , -1);
|
||||
}
|
||||
private void tst_Xto_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__trim_ws(Bry_.new_u8(val), 0, String_.Len(val), -1));}
|
||||
@Test public void Compare() {
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
|
||||
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_u8(lhs), lhs_bgn, lhs_end, Bry_.new_u8(rhs), rhs_bgn, rhs_end));}
|
||||
@Test public void Increment_last() {
|
||||
tst_IncrementLast(ary_(0), ary_(1));
|
||||
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
|
||||
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
|
||||
}
|
||||
byte[] ary_(int... ary) {
|
||||
byte[] rv = new byte[ary.length];
|
||||
for (int i = 0; i < ary.length; i++)
|
||||
rv[i] = Byte_.By_int(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
|
||||
@Test public void Replace_between() {
|
||||
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
|
||||
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
|
||||
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
|
||||
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_a7(Bry_.Replace_between(Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(end), Bry_.new_a7(repl))));}
|
||||
@Test public void Replace() {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
|
||||
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
|
||||
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
|
||||
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
|
||||
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
|
||||
}
|
||||
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
|
||||
Tfds.Eq(expd, String_.new_a7(Bry_.Replace(tmp_bfr, Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(repl))));
|
||||
}
|
||||
@Test public void Split_bry() {
|
||||
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
|
||||
Split_bry_tst("a|" , "|" , String_.Ary("a"));
|
||||
}
|
||||
void Split_bry_tst(String src, String dlm, String[] expd) {
|
||||
String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
}
|
||||
@Test public void Split_lines() {
|
||||
Tst_split_lines("a\nb" , "a", "b"); // basic
|
||||
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
|
||||
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
|
||||
Tst_split_lines("a\rb" , "a", "b"); // cr only
|
||||
}
|
||||
void Tst_split_lines(String src, String... expd) {
|
||||
Tfds.Eq_ary(expd, New_ary(Bry_split_.Split_lines(Bry_.new_a7(src))));
|
||||
}
|
||||
String[] New_ary(byte[][] lines) {
|
||||
int len = lines.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = String_.new_u8(lines[i]);
|
||||
return rv;
|
||||
}
|
||||
@Test public void Match_bwd_any() {
|
||||
Tst_match_bwd_any("abc", 2, 0, "c", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "b", false);
|
||||
Tst_match_bwd_any("abc", 2, 0, "bc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "abc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
|
||||
Tst_match_bwd_any("abc", 1, 0, "ab", true);
|
||||
}
|
||||
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
|
||||
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
|
||||
}
|
||||
@Test public void Trim_end() {
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.one
|
||||
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many
|
||||
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@Test public void Mid_w_trim() {
|
||||
fxt.Test_Mid_w_trim("abc", "abc"); // no ws
|
||||
fxt.Test_Mid_w_trim(" a b c ", "a b c"); // ws at bgn and end
|
||||
fxt.Test_Mid_w_trim("\r\n\t a\r\n\t b \r\n\t ", "a\r\n\t b"); // space at bgn and end
|
||||
fxt.Test_Mid_w_trim("", ""); // handle 0 bytes
|
||||
fxt.Test_Mid_w_trim(" ", ""); // handle all ws
|
||||
}
|
||||
@Test public void New_u8_nl_apos() {
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a"), "a");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b'c", "d"), "a\nb\"c\nd");
|
||||
}
|
||||
@Test public void Repeat_bry() {
|
||||
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
|
||||
}
|
||||
@Test public void Xcase__build__all() {
|
||||
fxt.Test__xcase__build__all(Bool_.N, "abc", "abc");
|
||||
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
|
||||
}
|
||||
}
|
||||
class Bry__fxt {
|
||||
private final Bry_bfr tmp = Bry_bfr_.New();
|
||||
public void Test_trim_end(String raw, byte trim, String expd) {
|
||||
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_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)));}
|
||||
public void Test_add(byte b, String s, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(b, Bry_.new_u8(s))));}
|
||||
public void Test_add_w_dlm(String dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(Bry_.new_u8(dlm), Bry_.Ary(itms))));}
|
||||
public void Test_add_w_dlm(byte dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(dlm, Bry_.Ary(itms))));}
|
||||
public void Test_Mid_w_trim(String src, String expd) {byte[] bry = Bry_.new_u8(src); Tfds.Eq(expd, String_.new_u8(Bry_.Mid_w_trim(bry, 0, bry.length)));}
|
||||
public void Test__new_u8_nl_apos(String[] ary, String expd) {
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(Bry_.New_u8_nl_apos(ary)));
|
||||
}
|
||||
public void Test__repeat_bry(String s, int count, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Repeat_bry(Bry_.new_u8(s), count));
|
||||
}
|
||||
public void Test__xcase__build__all(boolean upper, String src, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Xcase__build__all(tmp, upper, Bry_.new_u8(src)));
|
||||
}
|
||||
}
|
||||
package gplx;
|
||||
|
||||
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_() {
|
||||
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_a7("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_a7("" , Bry_.Empty); // none
|
||||
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ?
|
||||
}
|
||||
@Test public void new_u8() {
|
||||
fxt.Test_new_u8("a" , Bry_.New_by_ints(97)); // one
|
||||
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many
|
||||
fxt.Test_new_u8("¢" , Bry_.New_by_ints(194, 162)); // bry_len=2; cent
|
||||
fxt.Test_new_u8("€" , Bry_.New_by_ints(226, 130, 172)); // bry_len=3; euro
|
||||
fxt.Test_new_u8("𤭢" , Bry_.New_by_ints(240, 164, 173, 162)); // bry_len=4; example from en.w:UTF-8
|
||||
}
|
||||
@Test public void Add__bry_plus_byte() {
|
||||
fxt.Test_add("a" , Byte_ascii.Pipe , "a|"); // basic
|
||||
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String
|
||||
}
|
||||
@Test public void Add__byte_plus_bry() {
|
||||
fxt.Test_add(Byte_ascii.Pipe , "a" , "|a"); // basic
|
||||
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String
|
||||
}
|
||||
@Test public void Add_w_dlm() {
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", "b", "c") , "a|b|c"); // basic
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a") , "a"); // one item
|
||||
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null
|
||||
}
|
||||
@Test public void Add_w_dlm_bry() {
|
||||
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
|
||||
}
|
||||
@Test public void MidByPos() {
|
||||
tst_MidByPos("abcba", 0, 1, "a");
|
||||
tst_MidByPos("abcba", 0, 2, "ab");
|
||||
tst_MidByPos("abcba", 1, 4, "bcb");
|
||||
} void tst_MidByPos(String src, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Mid(Bry_.new_u8(src), bgn, end)));}
|
||||
@Test public void Replace_one() {
|
||||
tst_ReplaceOne("a" , "b" , "c" , "a");
|
||||
tst_ReplaceOne("b" , "b" , "c" , "c");
|
||||
tst_ReplaceOne("bb" , "b" , "c" , "cb");
|
||||
tst_ReplaceOne("abcd" , "bc" , "" , "ad");
|
||||
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd");
|
||||
} void tst_ReplaceOne(String src, String find, String repl, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Replace_one(Bry_.new_u8(src), Bry_.new_u8(find), Bry_.new_u8(repl))));}
|
||||
@Test public void XtoStrBytesByInt() {
|
||||
tst_XtoStrBytesByInt(0, 0);
|
||||
tst_XtoStrBytesByInt(9, 9);
|
||||
tst_XtoStrBytesByInt(10, 1, 0);
|
||||
tst_XtoStrBytesByInt(321, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(-321, Bry_.Byte_NegSign, 3, 2, 1);
|
||||
tst_XtoStrBytesByInt(Int_.Max_value, 2,1,4,7,4,8,3,6,4,7);
|
||||
}
|
||||
void tst_XtoStrBytesByInt(int val, int... expdAryAsInt) {
|
||||
byte[] expd = new byte[expdAryAsInt.length];
|
||||
for (int i = 0; i < expd.length; i++) {
|
||||
int expdInt = expdAryAsInt[i];
|
||||
expd[i] = expdInt == Bry_.Byte_NegSign ? Bry_.Byte_NegSign : Byte_ascii.To_a7_str(expdAryAsInt[i]);
|
||||
}
|
||||
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
|
||||
}
|
||||
@Test public void Has_at_end() {
|
||||
tst_HasAtEnd("a|bcd|e", "d" , 2, 5, true); // y_basic
|
||||
tst_HasAtEnd("a|bcd|e", "bcd" , 2, 5, true); // y_many
|
||||
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long
|
||||
tst_HasAtEnd("a|bcd|e", "|bc" , 2, 5, false); // n_pos
|
||||
tst_HasAtEnd("abc", "bc", true); // y
|
||||
tst_HasAtEnd("abc", "bd", false); // n
|
||||
tst_HasAtEnd("a", "ab", false); // exceeds_len
|
||||
}
|
||||
void tst_HasAtEnd(String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end));}
|
||||
void tst_HasAtEnd(String src, String find, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_end(Bry_.new_u8(src), Bry_.new_u8(find)));}
|
||||
@Test public void Has_at_bgn() {
|
||||
tst_HasAtBgn("y_basic" , "a|bcd|e", "b" , 2, 5, true);
|
||||
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 2, 5, true);
|
||||
tst_HasAtBgn("n_long" , "a|bcd|e", "bcde" , 2, 5, false);
|
||||
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 2, 5, false);
|
||||
} void tst_HasAtBgn(String tst, String src, String find, int bgn, int end, boolean expd) {Tfds.Eq(expd, Bry_.Has_at_bgn(Bry_.new_u8(src), Bry_.new_u8(find), bgn, end), tst);}
|
||||
@Test public void Match() {
|
||||
tst_Match("abc", 0, "abc", true);
|
||||
tst_Match("abc", 2, "c", true);
|
||||
tst_Match("abc", 0, "cde", false);
|
||||
tst_Match("abc", 2, "abc", false); // bounds check
|
||||
tst_Match("abc", 0, "abcd", false);
|
||||
tst_Match("a" , 0, "", false);
|
||||
tst_Match("" , 0, "a", false);
|
||||
tst_Match("" , 0, "", true);
|
||||
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different
|
||||
} void tst_Match(String src, int srcPos, String find, boolean expd) {Tfds.Eq(expd, Bry_.Match(Bry_.new_u8(src), srcPos, Bry_.new_u8(find)));}
|
||||
@Test public void ReadCsvStr() {
|
||||
tst_ReadCsvStr("a|" , "a");
|
||||
tst_ReadCsvStr("|a|", 1 , "a");
|
||||
Int_obj_ref bgn = Int_obj_ref.New_zero(); tst_ReadCsvStr("a|b|c|", bgn, "a"); tst_ReadCsvStr("a|b|c|", bgn, "b"); tst_ReadCsvStr("a|b|c|", bgn, "c");
|
||||
tst_ReadCsvStr("|", "");
|
||||
tst_ReadCsvStr_err("a");
|
||||
|
||||
tst_ReadCsvStr("'a'|" , "a");
|
||||
tst_ReadCsvStr("'a''b'|" , "a'b");
|
||||
tst_ReadCsvStr("'a|b'|" , "a|b");
|
||||
tst_ReadCsvStr("''|", "");
|
||||
tst_ReadCsvStr_err("''");
|
||||
tst_ReadCsvStr_err("'a'b'");
|
||||
tst_ReadCsvStr_err("'a");
|
||||
tst_ReadCsvStr_err("'a|");
|
||||
tst_ReadCsvStr_err("'a'");
|
||||
}
|
||||
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
|
||||
tst_XtoIntBy4Bytes(32, (byte)32); // space
|
||||
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // ∃
|
||||
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
|
||||
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
|
||||
}
|
||||
@Test public void XtoInt() {
|
||||
tst_XtoInt("1", 1);
|
||||
tst_XtoInt("123", 123);
|
||||
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("-1", Int_.Min_value, -1);
|
||||
tst_XtoInt("-123", Int_.Min_value, -123);
|
||||
tst_XtoInt("123-1", Int_.Min_value, Int_.Min_value);
|
||||
tst_XtoInt("+123", Int_.Min_value, 123);
|
||||
tst_XtoInt("", -1);
|
||||
}
|
||||
void tst_XtoInt(String val, int expd) {tst_XtoInt(val, -1, expd);}
|
||||
void tst_XtoInt(String val, int or, int expd) {Tfds.Eq(expd, Bry_.To_int_or(Bry_.new_u8(val), or));}
|
||||
void tst_XtoIntBy4Bytes(int expd, byte... ary) {Tfds.Eq(expd, Bry_.To_int_by_a7(ary), "XtoInt"); Tfds.Eq_ary(ary, Bry_.new_by_int(expd), "XbyInt");}
|
||||
void tst_ReadCsvStr(String raw, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New_zero() , expd);}
|
||||
void tst_ReadCsvStr(String raw, int bgn, String expd) {tst_ReadCsvStr(raw, Int_obj_ref.New(bgn), expd);}
|
||||
void tst_ReadCsvStr(String raw, Int_obj_ref bgnRef, String expd) {
|
||||
int bgn = bgnRef.Val();
|
||||
boolean rawHasQuotes = String_.CharAt(raw, bgn) == '\'';
|
||||
String actl = String_.Replace(Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), bgnRef, (byte)'|'), "\"", "'");
|
||||
Tfds.Eq(expd, actl, "rv");
|
||||
if (rawHasQuotes) {
|
||||
int quoteAdj = String_.Count(actl, "'");
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl) + 2 + quoteAdj, bgnRef.Val(), "pos_quote"); // +1=lkp.Len; +2=bgn/end quotes
|
||||
}
|
||||
else
|
||||
Tfds.Eq(bgn + 1 + String_.Len(actl), bgnRef.Val(), "pos"); // +1=lkp.Len
|
||||
}
|
||||
void tst_ReadCsvStr_err(String raw) {
|
||||
try {Bry_.ReadCsvStr(Bry_.new_u8(String_.Replace(raw, "'", "\"")), Int_obj_ref.New_zero(), (byte)'|');}
|
||||
catch (Exception e) {Err_.Noop(e); return;}
|
||||
Tfds.Fail_expdError();
|
||||
}
|
||||
@Test public void ReadCsvDte() {
|
||||
tst_ReadCsvDte("20110801 221435.987");
|
||||
} void tst_ReadCsvDte(String raw) {Tfds.Eq_date(DateAdp_.parse_fmt(raw, Bry_.Fmt_csvDte), Bry_.ReadCsvDte(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void ReadCsvInt() {
|
||||
tst_ReadCsvInt("1234567890");
|
||||
} void tst_ReadCsvInt(String raw) {Tfds.Eq(Int_.Parse(raw), Bry_.ReadCsvInt(Bry_.new_u8(raw + "|"), Int_obj_ref.New_zero(), (byte)'|'));}
|
||||
@Test public void Trim() {
|
||||
Trim_tst("a b c", 1, 4, "b");
|
||||
Trim_tst("a c", 1, 3, "");
|
||||
Trim_tst(" ", 0, 2, "");
|
||||
} void Trim_tst(String raw, int bgn, int end, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Trim(Bry_.new_u8(raw), bgn, end)));}
|
||||
@Test public void Xto_int_lax() {
|
||||
tst_Xto_int_lax("12a", 12);
|
||||
tst_Xto_int_lax("1", 1);
|
||||
tst_Xto_int_lax("123", 123);
|
||||
tst_Xto_int_lax("a", 0);
|
||||
tst_Xto_int_lax("-1", -1);
|
||||
}
|
||||
private void tst_Xto_int_lax(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__lax(Bry_.new_u8(val), 0, String_.Len(val), 0));}
|
||||
@Test public void To_int_or__trim_ws() {
|
||||
tst_Xto_int_trim("123 " , 123);
|
||||
tst_Xto_int_trim(" 123" , 123);
|
||||
tst_Xto_int_trim(" 123 " , 123);
|
||||
tst_Xto_int_trim(" 1 3 " , -1);
|
||||
}
|
||||
private void tst_Xto_int_trim(String val, int expd) {Tfds.Eq(expd, Bry_.To_int_or__trim_ws(Bry_.new_u8(val), 0, String_.Len(val), -1));}
|
||||
@Test public void Compare() {
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 1, CompareAble_.Same);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 0, 1, "abcde", 0, 2, CompareAble_.Less);
|
||||
tst_Compare("abcde", 0, 2, "abcde", 0, 1, CompareAble_.More);
|
||||
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less);
|
||||
} void tst_Compare(String lhs, int lhs_bgn, int lhs_end, String rhs, int rhs_bgn, int rhs_end, int expd) {Tfds.Eq(expd, Bry_.Compare(Bry_.new_u8(lhs), lhs_bgn, lhs_end, Bry_.new_u8(rhs), rhs_bgn, rhs_end));}
|
||||
@Test public void Increment_last() {
|
||||
tst_IncrementLast(ary_(0), ary_(1));
|
||||
tst_IncrementLast(ary_(0, 255), ary_(1, 0));
|
||||
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
|
||||
}
|
||||
byte[] ary_(int... ary) {
|
||||
byte[] rv = new byte[ary.length];
|
||||
for (int i = 0; i < ary.length; i++)
|
||||
rv[i] = Byte_.By_int(ary[i]);
|
||||
return rv;
|
||||
}
|
||||
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
|
||||
@Test public void Replace_between() {
|
||||
tst_Replace_between("a[0]b" , "[", "]", "0", "a0b");
|
||||
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
|
||||
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b");
|
||||
} public void tst_Replace_between(String src, String bgn, String end, String repl, String expd) {Tfds.Eq(expd, String_.new_a7(Bry_.Replace_between(Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(end), Bry_.new_a7(repl))));}
|
||||
@Test public void Replace() {
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.New();
|
||||
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2
|
||||
tst_Replace(tmp_bfr, "a00b00c" , "00", "0", "a0b0c"); // 2 -> 1
|
||||
tst_Replace(tmp_bfr, "a0b0" , "0", "00", "a00b00"); // 1 -> 2; EOS
|
||||
tst_Replace(tmp_bfr, "a00b00" , "00", "0", "a0b0"); // 2 -> 1; EOS
|
||||
tst_Replace(tmp_bfr, "a0b0" , "1", "2", "a0b0"); // no match
|
||||
tst_Replace(tmp_bfr, "a0b0" , "b1", "b2", "a0b0"); // false match; EOS
|
||||
}
|
||||
public void tst_Replace(Bry_bfr tmp_bfr, String src, String bgn, String repl, String expd) {
|
||||
Tfds.Eq(expd, String_.new_a7(Bry_.Replace(tmp_bfr, Bry_.new_a7(src), Bry_.new_a7(bgn), Bry_.new_a7(repl))));
|
||||
}
|
||||
@Test public void Split_bry() {
|
||||
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
|
||||
Split_bry_tst("a|" , "|" , String_.Ary("a"));
|
||||
}
|
||||
void Split_bry_tst(String src, String dlm, String[] expd) {
|
||||
String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
|
||||
Tfds.Eq_ary_str(expd, actl);
|
||||
}
|
||||
@Test public void Split_lines() {
|
||||
Tst_split_lines("a\nb" , "a", "b"); // basic
|
||||
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
|
||||
Tst_split_lines("a\r\nb" , "a", "b"); // crlf
|
||||
Tst_split_lines("a\rb" , "a", "b"); // cr only
|
||||
}
|
||||
void Tst_split_lines(String src, String... expd) {
|
||||
Tfds.Eq_ary(expd, New_ary(Bry_split_.Split_lines(Bry_.new_a7(src))));
|
||||
}
|
||||
String[] New_ary(byte[][] lines) {
|
||||
int len = lines.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = String_.new_u8(lines[i]);
|
||||
return rv;
|
||||
}
|
||||
@Test public void Match_bwd_any() {
|
||||
Tst_match_bwd_any("abc", 2, 0, "c", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "b", false);
|
||||
Tst_match_bwd_any("abc", 2, 0, "bc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "abc", true);
|
||||
Tst_match_bwd_any("abc", 2, 0, "zabc", false);
|
||||
Tst_match_bwd_any("abc", 1, 0, "ab", true);
|
||||
}
|
||||
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
|
||||
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_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
|
||||
fxt.Test_trim_end("a" , Byte_ascii.Space, "a"); // trim.none
|
||||
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty
|
||||
}
|
||||
@Test public void Mid_w_trim() {
|
||||
fxt.Test_Mid_w_trim("abc", "abc"); // no ws
|
||||
fxt.Test_Mid_w_trim(" a b c ", "a b c"); // ws at bgn and end
|
||||
fxt.Test_Mid_w_trim("\r\n\t a\r\n\t b \r\n\t ", "a\r\n\t b"); // space at bgn and end
|
||||
fxt.Test_Mid_w_trim("", ""); // handle 0 bytes
|
||||
fxt.Test_Mid_w_trim(" ", ""); // handle all ws
|
||||
}
|
||||
@Test public void New_u8_nl_apos() {
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a"), "a");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb");
|
||||
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b'c", "d"), "a\nb\"c\nd");
|
||||
}
|
||||
@Test public void Repeat_bry() {
|
||||
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
|
||||
}
|
||||
@Test public void Xcase__build__all() {
|
||||
fxt.Test__xcase__build__all(Bool_.N, "abc", "abc");
|
||||
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
|
||||
}
|
||||
}
|
||||
class Bry__fxt {
|
||||
private final Bry_bfr tmp = Bry_bfr_.New();
|
||||
public void Test_trim_end(String raw, byte trim, String expd) {
|
||||
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)));}
|
||||
public void Test_add(byte b, String s, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(b, Bry_.new_u8(s))));}
|
||||
public void Test_add_w_dlm(String dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(Bry_.new_u8(dlm), Bry_.Ary(itms))));}
|
||||
public void Test_add_w_dlm(byte dlm, String[] itms, String expd) {Tfds.Eq(expd, String_.new_u8(Bry_.Add_w_dlm(dlm, Bry_.Ary(itms))));}
|
||||
public void Test_Mid_w_trim(String src, String expd) {byte[] bry = Bry_.new_u8(src); Tfds.Eq(expd, String_.new_u8(Bry_.Mid_w_trim(bry, 0, bry.length)));}
|
||||
public void Test__new_u8_nl_apos(String[] ary, String expd) {
|
||||
Tfds.Eq_str_lines(expd, String_.new_u8(Bry_.New_u8_nl_apos(ary)));
|
||||
}
|
||||
public void Test__repeat_bry(String s, int count, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Repeat_bry(Bry_.new_u8(s), count));
|
||||
}
|
||||
public void Test__xcase__build__all(boolean upper, String src, String expd) {
|
||||
Gftest.Eq__str(expd, Bry_.Xcase__build__all(tmp, upper, Bry_.new_u8(src)));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -134,6 +134,24 @@ public class Bry_split_ {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static byte[][] Split_ws(byte[] src) {// REF.PHP: preg_split('/\s+/', $text)
|
||||
int len = src.length;
|
||||
if (len == 0) return Bry_.Ary_empty;
|
||||
|
||||
List_adp list = List_adp_.New();
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
int bgn = Bry_find_.Find_fwd_while_ws(src, pos, len);
|
||||
if (bgn == len) break; // EOS
|
||||
int end = Bry_find_.Find_fwd_until_ws(src, bgn + 1, len);
|
||||
if (end == -1) end = len;
|
||||
list.Add(Bry_.Mid(src, bgn, end));
|
||||
pos = end + 1;
|
||||
if (pos >= len) break;
|
||||
}
|
||||
return (byte[][])list.To_ary_and_clear(byte[].class);
|
||||
}
|
||||
|
||||
|
||||
public static final int Rv__ok = 0, Rv__extend = 1, Rv__cancel = 2;
|
||||
}
|
||||
|
@ -49,6 +49,11 @@ public class Bry_split__tst {
|
||||
fxt.Test__split_w_max("a" , Byte_ascii.Pipe, 2, "a", null); // max is more
|
||||
fxt.Test__split_w_max("|" , Byte_ascii.Pipe, 2, "", ""); // empty itms
|
||||
}
|
||||
@Test public void Split_ws() {
|
||||
fxt.Test__split_ws("a b", "a", "b");
|
||||
fxt.Test__split_ws(" a ", "a");
|
||||
fxt.Test__split_ws(" abc def ", "abc", "def");
|
||||
}
|
||||
}
|
||||
class Bry_split__fxt {
|
||||
private final Bry_split_wkr__example wkr = new Bry_split_wkr__example();
|
||||
@ -64,6 +69,10 @@ class Bry_split__fxt {
|
||||
public void Test__split_w_max(String src, byte dlm, int max, String... expd) {
|
||||
Gftest.Eq__ary(expd, String_.Ary(Bry_split_.Split_w_max(Bry_.new_u8(src), dlm, max)));
|
||||
}
|
||||
public void Test__split_ws(String raw, String... expd) {
|
||||
byte[][] actl = Bry_split_.Split_ws(Bry_.new_u8(raw));
|
||||
Gftest.Eq__ary(Bry_.Ary(expd), actl, raw);
|
||||
}
|
||||
}
|
||||
class Bry_split_wkr__example implements gplx.core.brys.Bry_split_wkr {
|
||||
private final List_adp list = List_adp_.New();
|
||||
|
@ -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.
|
||||
@ -13,57 +13,79 @@ 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;
|
||||
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;
|
||||
public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
|
||||
public static final Decimal_adp Zero = new Decimal_adp(0);
|
||||
public static final Decimal_adp One = new Decimal_adp(1);
|
||||
public static final Decimal_adp Neg1 = new Decimal_adp(-1);
|
||||
public static final Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
|
||||
public static final Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
|
||||
public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
|
||||
public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
|
||||
public static Decimal_adp parts_(long num, int frc) {
|
||||
// int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
|
||||
// int pow10 = (int)Math_.Pow(10, log10);
|
||||
int pow10 = XtoPow10(frc);
|
||||
return divide_((num * (pow10)) + frc, pow10);
|
||||
}
|
||||
public static Decimal_adp cast(Object obj) {return (Decimal_adp)obj;}
|
||||
static int XtoPow10(int v) {
|
||||
if (v > -1 && v < 10) return 10;
|
||||
else if (v > 9 && v < 100) return 100;
|
||||
else if (v > 99 && v < 1000) return 1000;
|
||||
else if (v > 999 && v < 10000) return 10000;
|
||||
else if (v > 9999 && v < 100000) return 100000;
|
||||
else if (v > 99999 && v < 1000000) return 1000000;
|
||||
else if (v > 999999 && v < 10000000) return 10000000;
|
||||
else if (v > 9999999 && v < 100000000) return 100000000;
|
||||
else if (v > 99999999 && v < 1000000000) return 1000000000;
|
||||
else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
|
||||
}
|
||||
public static String CalcPctStr(long dividend, long divisor, String fmt) {
|
||||
if (divisor == 0) return "%ERR";
|
||||
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 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) {
|
||||
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);
|
||||
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
}
|
||||
package gplx;
|
||||
|
||||
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;
|
||||
public static Decimal_adp as_(Object obj) {return obj instanceof Decimal_adp ? (Decimal_adp)obj : null;}
|
||||
public static final Decimal_adp Zero = new Decimal_adp(0);
|
||||
public static final Decimal_adp One = new Decimal_adp(1);
|
||||
public static final Decimal_adp Neg1 = new Decimal_adp(-1);
|
||||
public static final Decimal_adp Const_e = Decimal_adp_.double_(Math_.E);
|
||||
public static final Decimal_adp Const_pi = Decimal_adp_.double_(Math_.Pi);
|
||||
public static Decimal_adp base1000_(long v) {return divide_(v, 1000);}
|
||||
public static Decimal_adp parts_1000_(long num, int frc) {return divide_((num * (1000)) + frc, 1000);}
|
||||
public static Decimal_adp parts_(long num, int frc) {
|
||||
// int log10 = frc == 0 ? 0 : (Math_.Log10(frc) + 1);
|
||||
// int pow10 = (int)Math_.Pow(10, log10);
|
||||
int pow10 = XtoPow10(frc);
|
||||
return divide_((num * (pow10)) + frc, pow10);
|
||||
}
|
||||
public static Decimal_adp cast(Object obj) {return (Decimal_adp)obj;}
|
||||
static int XtoPow10(int v) {
|
||||
if (v > -1 && v < 10) return 10;
|
||||
else if (v > 9 && v < 100) return 100;
|
||||
else if (v > 99 && v < 1000) return 1000;
|
||||
else if (v > 999 && v < 10000) return 10000;
|
||||
else if (v > 9999 && v < 100000) return 100000;
|
||||
else if (v > 99999 && v < 1000000) return 1000000;
|
||||
else if (v > 999999 && v < 10000000) return 10000000;
|
||||
else if (v > 9999999 && v < 100000000) return 100000000;
|
||||
else if (v > 99999999 && v < 1000000000) return 1000000000;
|
||||
else throw Err_.new_wo_type("value must be between 0 and 1 billion", "v", v);
|
||||
}
|
||||
public static String CalcPctStr(long dividend, long divisor, String fmt) {
|
||||
if (divisor == 0) return "%ERR";
|
||||
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 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) {
|
||||
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
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
Copyright (C) 2012-2021 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
@ -13,74 +13,81 @@ 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;
|
||||
import org.junit.*;
|
||||
public class Decimal_adp__tst {
|
||||
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt();
|
||||
@Test public void divide_() {
|
||||
fxt.Test_divide(1, 1000, "0.001");
|
||||
fxt.Test_divide(1, 3, "0.33333333333333");
|
||||
fxt.Test_divide(1, 7, "0.14285714285714");
|
||||
}
|
||||
@Test public void base1000_() {
|
||||
fxt.Test_base_1000(1000, "1");
|
||||
fxt.Test_base_1000(1234, "1.234");
|
||||
fxt.Test_base_1000(123, "0.123");
|
||||
}
|
||||
@Test public void parts_() {
|
||||
fxt.Test_parts(1, 0, "1");
|
||||
fxt.Test_parts(1, 2, "1.2");
|
||||
fxt.Test_parts(1, 23, "1.23");
|
||||
fxt.Test_parts(123, 4567, "123.4567");
|
||||
}
|
||||
@Test public void parse() {
|
||||
fxt.Test_parse("1", "1");
|
||||
fxt.Test_parse("1.2", "1.2");
|
||||
fxt.Test_parse("0.1", "0.1");
|
||||
}
|
||||
@Test public void Truncate_decimal() {
|
||||
fxt.Test_truncate_decimal("1", "1");
|
||||
fxt.Test_truncate_decimal("1.1", "1");
|
||||
fxt.Test_truncate_decimal("1.9", "1");
|
||||
}
|
||||
@Test public void Fraction1000() {
|
||||
fxt.Test_frac_1000(1, 1000, 1); // 0.001
|
||||
fxt.Test_frac_1000(1, 3, 333); // 0.33333333
|
||||
fxt.Test_frac_1000(1234, 1000, 234); // 1.234
|
||||
fxt.Test_frac_1000(12345, 10000, 234); // 1.2345
|
||||
}
|
||||
@Test public void Lt() {
|
||||
fxt.Test_comp_lt(1,123, 2, true);
|
||||
fxt.Test_comp_lt(1,99999999, 2, true);
|
||||
}
|
||||
@Test public void To_str_fmt() {
|
||||
fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
|
||||
fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
|
||||
fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
|
||||
fxt.Test_to_str_fmt(1, 2, "00.00", "00.50");
|
||||
}
|
||||
@Test public void Round() {
|
||||
fxt.Test_round("123.456", 3, "123.456");
|
||||
fxt.Test_round("123.456", 2, "123.46");
|
||||
fxt.Test_round("123.456", 1, "123.5");
|
||||
fxt.Test_round("123.456", 0, "123");
|
||||
fxt.Test_round("123.456", -1, "120");
|
||||
fxt.Test_round("123.456", -2, "100");
|
||||
fxt.Test_round("123.456", -3, "0");
|
||||
|
||||
fxt.Test_round("6", -1, "10");
|
||||
fxt.Test_round("5", -1, "10");
|
||||
fxt.Test_round("6", -2, "0");
|
||||
}
|
||||
}
|
||||
class Decimal_adp__fxt {
|
||||
public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
|
||||
public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
|
||||
public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
|
||||
public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse(raw).To_str());}
|
||||
public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse(expd).To_str(), Decimal_adp_.parse(raw).Truncate().To_str());}
|
||||
public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
|
||||
public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
|
||||
public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
|
||||
public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse(raw).Round(places).To_str(), "round");}
|
||||
}
|
||||
package gplx;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class Decimal_adp__tst {
|
||||
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt();
|
||||
@Test public void divide_() {
|
||||
fxt.Test_divide(1, 1000, "0.001");
|
||||
fxt.Test_divide(1, 3, "0.33333333333333");
|
||||
fxt.Test_divide(1, 7, "0.14285714285714");
|
||||
}
|
||||
@Test public void base1000_() {
|
||||
fxt.Test_base_1000(1000, "1");
|
||||
fxt.Test_base_1000(1234, "1.234");
|
||||
fxt.Test_base_1000(123, "0.123");
|
||||
}
|
||||
@Test public void parts_() {
|
||||
fxt.Test_parts(1, 0, "1");
|
||||
fxt.Test_parts(1, 2, "1.2");
|
||||
fxt.Test_parts(1, 23, "1.23");
|
||||
fxt.Test_parts(123, 4567, "123.4567");
|
||||
}
|
||||
@Test public void parse() {
|
||||
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");
|
||||
fxt.Test_truncate_decimal("1.1", "1");
|
||||
fxt.Test_truncate_decimal("1.9", "1");
|
||||
}
|
||||
@Test public void Fraction1000() {
|
||||
fxt.Test_frac_1000(1, 1000, 1); // 0.001
|
||||
fxt.Test_frac_1000(1, 3, 333); // 0.33333333
|
||||
fxt.Test_frac_1000(1234, 1000, 234); // 1.234
|
||||
fxt.Test_frac_1000(12345, 10000, 234); // 1.2345
|
||||
}
|
||||
@Test public void Lt() {
|
||||
fxt.Test_comp_lt(1,123, 2, true);
|
||||
fxt.Test_comp_lt(1,99999999, 2, true);
|
||||
}
|
||||
@Test public void To_str_fmt() {
|
||||
fxt.Test_to_str_fmt(1, 2, "0.0", "0.5");
|
||||
fxt.Test_to_str_fmt(1, 3, "0.0", "0.3");
|
||||
fxt.Test_to_str_fmt(10000, 7, "0,000.000", "1,428.571");
|
||||
fxt.Test_to_str_fmt(1, 2, "00.00", "00.50");
|
||||
}
|
||||
@Test public void Round() {
|
||||
fxt.Test_round("123.456", 3, "123.456");
|
||||
fxt.Test_round("123.456", 2, "123.46");
|
||||
fxt.Test_round("123.456", 1, "123.5");
|
||||
fxt.Test_round("123.456", 0, "123");
|
||||
fxt.Test_round("123.456", -1, "120");
|
||||
fxt.Test_round("123.456", -2, "100");
|
||||
fxt.Test_round("123.456", -3, "0");
|
||||
|
||||
fxt.Test_round("6", -1, "10");
|
||||
fxt.Test_round("5", -1, "10");
|
||||
fxt.Test_round("6", -2, "0");
|
||||
}
|
||||
}
|
||||
class Decimal_adp__fxt {
|
||||
public void Test_divide(int lhs, int rhs, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).To_str());}
|
||||
public void Test_base_1000(int val, String expd) {Tfds.Eq(expd, Decimal_adp_.base1000_(val).To_str());}
|
||||
public void Test_parts(int num, int fracs, String expd) {Tfds.Eq(expd, Decimal_adp_.parts_(num, fracs).To_str());}
|
||||
public void Test_parse(String raw, String expd) {Tfds.Eq(expd, Decimal_adp_.parse(raw).To_str());}
|
||||
public void Test_truncate_decimal(String raw, String expd) {Tfds.Eq(Decimal_adp_.parse(expd).To_str(), Decimal_adp_.parse(raw).Truncate().To_str());}
|
||||
public void Test_frac_1000(int lhs, int rhs, int expd) {Tfds.Eq(expd, Decimal_adp_.divide_(lhs, rhs).Frac_1000());}
|
||||
public void Test_comp_lt(int lhsNum, int lhsFrc, int rhs, boolean expd) {Tfds.Eq(expd, Decimal_adp_.parts_(lhsNum, lhsFrc).Comp_lt(rhs));}
|
||||
public void Test_to_str_fmt(int l, int r, String fmt, String expd) {Tfds.Eq(expd, Decimal_adp_.divide_(l, r).To_str(fmt));}
|
||||
public void Test_round(String raw, int places, String expd) {Tfds.Eq_str(expd, Decimal_adp_.parse(raw).Round(places).To_str(), "round");}
|
||||
}
|
||||
|
@ -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,40 +13,43 @@ 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;
|
||||
package gplx;
|
||||
|
||||
public class Double_ {
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
public static final double
|
||||
MinValue = Double.MIN_VALUE
|
||||
, NaN = Double.NaN
|
||||
, Inf_pos = Double.POSITIVE_INFINITY
|
||||
;
|
||||
public static final byte[]
|
||||
NaN_bry = Bry_.new_a7("NaN")
|
||||
, Inf_pos_bry = Bry_.new_a7("INF")
|
||||
;
|
||||
public static boolean IsNaN(double v) {return Double.isNaN(v);}
|
||||
public static double cast(Object o) {try {return (Double)o;} catch(Exception e) {throw Err_.new_type_mismatch_w_exc(e, double.class, o);}}
|
||||
public static double parse(String raw) {try {return Double.parseDouble(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, double.class, raw);}}
|
||||
public static double parse_or(String raw, double v) {try {return Double.parseDouble(raw);} catch(Exception e) {Err_.Noop(e); return v;}}
|
||||
public static double coerce_(Object v) {
|
||||
try {String s = String_.as_(v); return s == null ? Double_.cast(v) : Double_.parse(s);}
|
||||
catch (Exception e) {throw Err_.new_cast(e, double.class, v);}
|
||||
}
|
||||
public static String To_str(double v) {
|
||||
int v_int = (int)v;
|
||||
return v - v_int == 0 ? Int_.To_str(v_int) : Double.toString(v);
|
||||
}
|
||||
public static String To_str_loose(double v) {
|
||||
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
|
||||
}
|
||||
public static int Compare(double lhs, double rhs) {
|
||||
if (lhs == rhs) return CompareAble_.Same;
|
||||
else if (lhs < rhs) return CompareAble_.Less;
|
||||
else return CompareAble_.More;
|
||||
}
|
||||
}
|
||||
public static final String Cls_val_name = "double";
|
||||
public static final Class<?> Cls_ref_type = Double.class;
|
||||
public static final double
|
||||
MinValue = Double.MIN_VALUE
|
||||
, NaN = Double.NaN
|
||||
, Inf_pos = Double.POSITIVE_INFINITY
|
||||
;
|
||||
public static final byte[]
|
||||
NaN_bry = Bry_.new_a7("NaN")
|
||||
, Inf_pos_bry = Bry_.new_a7("INF")
|
||||
;
|
||||
public static boolean IsNaN(double v) {return Double.isNaN(v);}
|
||||
public static double cast(Object o) {try {return (Double)o;} catch(Exception e) {throw Err_.new_type_mismatch_w_exc(e, double.class, o);}}
|
||||
public static double parse(String raw) {try {return Double.parseDouble(raw);} catch(Exception e) {throw Err_.new_parse_exc(e, double.class, raw);}}
|
||||
public static double parse_or(String raw, double v) {try {return Double.parseDouble(raw);} catch(Exception e) {Err_.Noop(e); return v;}}
|
||||
public static double coerce_(Object v) {
|
||||
try {String s = String_.as_(v); return s == null ? Double_.cast(v) : Double_.parse(s);}
|
||||
catch (Exception e) {throw Err_.new_cast(e, double.class, v);}
|
||||
}
|
||||
public static String To_str(double v) {
|
||||
int v_int = (int)v;
|
||||
return v - v_int == 0 ? Int_.To_str(v_int) : Double.toString(v);
|
||||
}
|
||||
public static String To_str_loose(double v) {
|
||||
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
|
||||
// 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;
|
||||
else if (lhs < rhs) return CompareAble_.Less;
|
||||
else return CompareAble_.More;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
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");
|
||||
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
|
||||
Io_mgr.Instance.AppendFilStr(url, txt);
|
||||
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) {
|
||||
|
@ -13,18 +13,20 @@ 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;
|
||||
import org.junit.*; import gplx.core.tests.*; import gplx.core.envs.*;
|
||||
public class Io_url__tst {
|
||||
@Before public void init() {fxt.Clear();} private final Io_url__fxt fxt = new Io_url__fxt();
|
||||
@Test public void Basic__lnx() {fxt.Test__New__http_or_null(Bool_.N, "file:///C:/a.txt", "C:/a.txt");}
|
||||
@Test public void Basic__wnt() {fxt.Test__New__http_or_null(Bool_.Y, "file:///C:/a.txt", "C:\\a.txt");}
|
||||
@Test public void Null() {fxt.Test__New__http_or_null(Bool_.N, "C:/a.txt", null);}
|
||||
}
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
package gplx;
|
||||
import org.junit.*; import gplx.core.tests.*; import gplx.core.envs.*;
|
||||
public class Io_url__tst {
|
||||
@Before public void init() {fxt.Clear();} private final Io_url__fxt fxt = new Io_url__fxt();
|
||||
@Test public void Basic__lnx() {fxt.Test__New__http_or_null(Bool_.N, "file:///C:/a.txt", "C:/a.txt");}
|
||||
@Test public void Basic__wnt() {fxt.Test__New__http_or_null(Bool_.Y, "file:///C:/a.txt", "C:\\a.txt");}
|
||||
@Test public void Null() {fxt.Test__New__http_or_null(Bool_.N, "C:/a.txt", null);}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -67,49 +67,64 @@ public class Keyval_ {
|
||||
}
|
||||
public static String Ary__to_str__nest(Keyval... ary) {
|
||||
Bry_bfr bfr = Bry_bfr_.New();
|
||||
Ary__to_str__nest__obj(bfr, 0, true, ary);
|
||||
Ary__to_str__nest__ary(bfr, 0, true, ary);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
private static void Ary__to_str__nest__obj(Bry_bfr bfr, int indent, boolean is_kv, Object[] ary) {
|
||||
public static Object[] Ary__to_objary__val(Keyval[] ary) {
|
||||
int ary_len = ary.length;
|
||||
Object[] rv = new Object[ary_len];
|
||||
for (int i = 0; i < ary_len; i++) {
|
||||
rv[i] = ary[i].Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static void Ary__to_str__nest__ary(Bry_bfr bfr, int indent, boolean is_kv, Object[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Object val = ary[i];
|
||||
if (indent > 0)
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent * 2); // add indent; EX: " "
|
||||
String key = null;
|
||||
if (is_kv) {
|
||||
Keyval kv = (Keyval)val;
|
||||
key = Object_.Xto_str_strict_or_empty(kv.Key());
|
||||
val = kv.Val();
|
||||
}
|
||||
else {
|
||||
key = Int_.To_str(i + 1);
|
||||
}
|
||||
bfr.Add_str_u8(key).Add_byte_eq(); // add key + eq : "key="
|
||||
if (val == null)
|
||||
bfr.Add_str_a7(String_.Null_mark);
|
||||
else {
|
||||
Class<?> val_type = Type_.Type_by_obj(val);
|
||||
if (Type_.Eq(val_type, Keyval[].class)) { // val is Keyval[]; recurse
|
||||
bfr.Add_byte_nl(); // add nl : "\n"
|
||||
Ary__to_str__nest__obj(bfr, indent + 1, true, (Keyval[])val);
|
||||
continue; // don't add \n below
|
||||
}
|
||||
else if (Type_.Eq(val_type, Object[].class)) { // val is Object[]
|
||||
bfr.Add_byte_nl();
|
||||
Ary__to_str__nest__obj(bfr, indent + 1, false, (Object[])val);
|
||||
continue; // don't add \n below
|
||||
}
|
||||
else if (Type_.Eq(val_type, Bool_.Cls_ref_type)) { // val is boolean
|
||||
boolean val_as_bool = Bool_.Cast(val);
|
||||
bfr.Add(val_as_bool ? Bool_.True_bry : Bool_.False_bry); // add "true" or "false"; don't call toString
|
||||
}
|
||||
else
|
||||
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(val)); // call toString()
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
Ary__to_str__nest__val(bfr, indent, is_kv, i, ary[i]);
|
||||
}
|
||||
}
|
||||
private static void Ary__to_str__nest__val(Bry_bfr bfr, int indent, boolean is_kv, int idx, Object val) {
|
||||
if (indent > 0)
|
||||
bfr.Add_byte_repeat(Byte_ascii.Space, indent * 2); // add indent; EX: " "
|
||||
String key = null;
|
||||
if (is_kv) {
|
||||
Keyval kv = (Keyval)val;
|
||||
key = Object_.Xto_str_strict_or_empty(kv.Key());
|
||||
val = kv.Val();
|
||||
}
|
||||
else {
|
||||
key = Int_.To_str(idx + 1);
|
||||
}
|
||||
bfr.Add_str_u8(key).Add_byte_eq(); // add key + eq : "key="
|
||||
if (val == null)
|
||||
bfr.Add_str_a7(String_.Null_mark);
|
||||
else {
|
||||
Class<?> val_type = Type_.Type_by_obj(val);
|
||||
if (Type_.Eq(val_type, Keyval[].class)) { // val is Keyval[]; recurse
|
||||
bfr.Add_byte_nl(); // add nl: "\n"
|
||||
Ary__to_str__nest__ary(bfr, indent + 1, true, (Keyval[])val);
|
||||
return; // don't add \n below
|
||||
}
|
||||
else if (Type_.Eq(val_type, Keyval.class)) { // val is Keyval; recurse
|
||||
bfr.Add_byte_nl(); // add nl: "\n"
|
||||
Ary__to_str__nest__val(bfr, indent + 1, true, 1, (Keyval)val);
|
||||
return; // don't add \n below
|
||||
}
|
||||
else if (Type_.Eq(val_type, Object[].class)) { // val is Object[]
|
||||
bfr.Add_byte_nl();
|
||||
Ary__to_str__nest__ary(bfr, indent + 1, false, (Object[])val);
|
||||
return; // don't add \n below
|
||||
}
|
||||
else if (Type_.Eq(val_type, Bool_.Cls_ref_type)) { // val is boolean
|
||||
boolean val_as_bool = Bool_.Cast(val);
|
||||
bfr.Add(val_as_bool ? Bool_.True_bry : Bool_.False_bry); // add "true" or "false"; don't call toString
|
||||
}
|
||||
else
|
||||
bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(val)); // call toString()
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
public static Keyval as_(Object obj) {return obj instanceof Keyval ? (Keyval)obj : null;}
|
||||
public static Keyval new_(String key) {return new Keyval(Type_ids_.Id__str, key, key);}
|
||||
public static Keyval new_(String key, Object val) {return new Keyval(Type_ids_.Id__str, key, val);}
|
||||
|
@ -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.
|
||||
@ -13,44 +13,50 @@ 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;
|
||||
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) {
|
||||
Class<?> rv = o.getClass();
|
||||
if (rv == Integer.class) rv = int.class;
|
||||
else if (rv == Long.class) rv = long.class;
|
||||
else if (rv == Byte.class) rv = byte.class;
|
||||
else if (rv == Short.class) rv = short.class;
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static boolean Eq_by_obj(Object lhs_obj, Class<?> rhs_type) {
|
||||
Class<?> lhs_type = lhs_obj == null ? null : lhs_obj.getClass();
|
||||
return Type_.Eq(lhs_type, rhs_type);
|
||||
}
|
||||
public static boolean Eq(Class<?> lhs, Class<?> rhs) {// DUPE_FOR_TRACKING: same as Object_.Eq
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
else return lhs.equals(rhs);
|
||||
}
|
||||
|
||||
public static String Canonical_name_by_obj(Object o) {return Canonical_name(o.getClass());}
|
||||
public static String Canonical_name(Class<?> type) {
|
||||
return type.getCanonicalName();
|
||||
}
|
||||
|
||||
public static String Name_by_obj(Object obj) {return obj == null ? String_.Null_mark : Name(Type_by_obj(obj));}
|
||||
public static String Name(Class<?> type) {
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
public static boolean Is_array(Class<?> t) {
|
||||
return t.isArray();
|
||||
}
|
||||
|
||||
public static boolean Is_assignable_from_by_obj(Object o, Class<?> generic) {return o == null ? false : Is_assignable_from(generic, o.getClass());}
|
||||
public static boolean Is_assignable_from(Class<?> generic, Class<?> specific) {
|
||||
return generic.isAssignableFrom(specific);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
Class<?> rv = o.getClass();
|
||||
if (rv == Integer.class) rv = int.class;
|
||||
else if (rv == Long.class) rv = long.class;
|
||||
else if (rv == Byte.class) rv = byte.class;
|
||||
else if (rv == Short.class) rv = short.class;
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static boolean Eq_by_obj(Object lhs_obj, Class<?> rhs_type) {
|
||||
Class<?> lhs_type = lhs_obj == null ? null : lhs_obj.getClass();
|
||||
return Type_.Eq(lhs_type, rhs_type);
|
||||
}
|
||||
public static boolean Eq(Class<?> lhs, Class<?> rhs) {// DUPE_FOR_TRACKING: same as Object_.Eq
|
||||
if (lhs == null && rhs == null) return true;
|
||||
else if (lhs == null || rhs == null) return false;
|
||||
else return lhs.equals(rhs);
|
||||
}
|
||||
|
||||
public static String Canonical_name_by_obj(Object o) {return Canonical_name(o.getClass());}
|
||||
public static String Canonical_name(Class<?> type) {
|
||||
return type.getCanonicalName();
|
||||
}
|
||||
|
||||
public static String Name_by_obj(Object obj) {return obj == null ? String_.Null_mark : Name(Type_by_obj(obj));}
|
||||
public static String Name(Class<?> type) {
|
||||
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();
|
||||
}
|
||||
|
||||
public static boolean Is_assignable_from_by_obj(Object o, Class<?> generic) {return o == null ? false : Is_assignable_from(generic, o.getClass());}
|
||||
public static boolean Is_assignable_from(Class<?> generic, Class<?> specific) {
|
||||
return generic.isAssignableFrom(specific);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ public class Console_adp__sys implements Console_adp {
|
||||
Clear_tmp();
|
||||
if (String_.Has(s, "\r")) s = String_.Replace(s, "\r", " ");
|
||||
if (String_.Has(s, "\n")) s = String_.Replace(s, "\n", " ");
|
||||
if (String_.Len(s) >= chars_per_line_max) s = String_.Mid(s, 0, chars_per_line_max - String_.Len("...") - 1) + "..."; // NOTE: >= and -1 needed b/c line needs to be 1 less than max; ex: default cmd is 80 width, but writing 80 chars will automatically create lineBreak
|
||||
// if (String_.Len(s) >= chars_per_line_max) s = String_.Mid(s, 0, chars_per_line_max - String_.Len("...") - 1) + "..."; // NOTE: >= and -1 needed b/c line needs to be 1 less than max; ex: default cmd is 80 width, but writing 80 chars will automatically create lineBreak
|
||||
tmp_txt = s;
|
||||
Write_str_lang(s);
|
||||
}
|
||||
|
@ -128,18 +128,22 @@ public class Hex_utl_ {
|
||||
}
|
||||
public static boolean Is_hex_many(byte... ary) {
|
||||
for (byte itm : ary) {
|
||||
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;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
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:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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
|
||||
;
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ import org.junit.*; import gplx.core.primitives.*;
|
||||
public class Utf16__tst {
|
||||
private Utf16__fxt fxt = new Utf16__fxt();
|
||||
@Test public void Encode_decode() {
|
||||
// fxt.Test_encode_decode(162, 194, 162); // cent
|
||||
// fxt.Test_encode_decode(8364, 226, 130, 172); // euro
|
||||
fxt.Test_encode_decode(150370, 240, 164, 173, 162); // example from [[UTF-8]]; should be encoded as two bytes
|
||||
fxt.Test_encode_decode(143489, 240, 163, 130, 129); // EX: 駣𣂁脁 DATE:2017-04-22
|
||||
fxt.Test_encode_decode(162, 194, 162); // cent; ¢
|
||||
fxt.Test_encode_decode(8364, 226, 130, 172); // euro; €
|
||||
fxt.Test_encode_decode(150370, 240, 164, 173, 162); // example from [[UTF-8]]; should be encoded as two bytes; 𤭢
|
||||
fxt.Test_encode_decode(143489, 240, 163, 130, 129); // EX: 駣𣂁脁 DATE:2017-04-22; 𣂁
|
||||
}
|
||||
@Test public void Encode_as_bry_by_hex() {
|
||||
fxt.Test_Encode_hex_to_bry("00", 0);
|
||||
|
@ -52,6 +52,7 @@ public class Utf8_ {
|
||||
default: throw Err_.new_wo_type("invalid initial utf8 byte", "byte", b);
|
||||
}
|
||||
}
|
||||
public static int Len_of_char_by_bytes_len(int v) {return v == 4 ? 2 : 1;} // 1 to 3 UTF bytes will encode up to 65,536 and fit in 1 char
|
||||
public static byte[] Get_char_at_pos_as_bry(byte[] bry, int pos) {
|
||||
int len = Len_of_char_by_1st_byte(bry[pos]);
|
||||
return Bry_.Mid(bry, pos, pos + len);
|
||||
@ -88,7 +89,7 @@ public class Utf8_ {
|
||||
for (int i = pos - 1; i >= stop; i--) { // start at pos - 1, and move bwd; NOTE: pos - 1 to skip pos, b/c pos will never definitively yield any char_len info
|
||||
byte b = bry[i];
|
||||
int char_len = Len_of_char_by_1st_byte(b);
|
||||
switch (char_len) { // if char_len is multi-byte and pos is at correct multi-byte pos (pos - i = # of bytes - 1), then pos0 found; EX: <EFBFBD> = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct pos for 3 byte char -> return
|
||||
switch (char_len) { // if char_len is multi-byte and pos is at correct multi-byte pos (pos - i = # of bytes - 1), then pos0 found; EX: € = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct pos for 3 byte char -> return
|
||||
case 2: if (pos - i == 1) return i; break;
|
||||
case 3: if (pos - i == 2) return i; break;
|
||||
case 4: if (pos - i == 3) return i; break;
|
||||
@ -111,7 +112,7 @@ public class Utf8_ {
|
||||
// loop maximum of 4 times; note that UTF8 char has max of 4 bytes
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int char_len = Len_of_char_by_1st_byte(b);
|
||||
switch (char_len) { // if char_len is multi-byte and cur is at correct multi-byte pos (cur - i = # of bytes - 1), then pos0 found; EX: <EFBFBD> = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct cur for 3 byte char -> return
|
||||
switch (char_len) { // if char_len is multi-byte and cur is at correct multi-byte pos (cur - i = # of bytes - 1), then pos0 found; EX: € = {226,130,172}; 172 is skipped; 130 has len of 1 -> continue; 226 has len of 3 and is found at correct cur for 3 byte char -> return
|
||||
case 2: if (i == 1) return pos; break;
|
||||
case 3: if (i == 2) return pos; break;
|
||||
case 4: if (i == 3) return pos; break;
|
||||
@ -141,3 +142,48 @@ public class Utf8_ {
|
||||
, Codepoint_surrogate_end = 0xDFFF
|
||||
;
|
||||
}
|
||||
/*
|
||||
== Definitions ==
|
||||
=== a7 vs u8 ===
|
||||
* a7 -> ASCII (7 bits)
|
||||
* u8 -> UTF-8 (8 bytes)
|
||||
|
||||
In retrospect, better abbreviations would have been:
|
||||
* ascii -> ASCII
|
||||
* utf08 -> UTF-8
|
||||
* utf16 -> UTF-16
|
||||
|
||||
=== General ===
|
||||
==== Byte ====
|
||||
* Standard definition; 8 bits (2^8 or 256)
|
||||
|
||||
==== Codepoint ====
|
||||
* Represents 1 atomic character but can be composed of multiple bytes
|
||||
** Examples:
|
||||
<pre>
|
||||
1 byte : "a" (letter a)
|
||||
2 bytes: "¢" (cent)
|
||||
3 bytes: "€" (euro)
|
||||
4 bytes: "𤭢" (Chinese character)
|
||||
</pre>
|
||||
* Defined by unicode as a sequence of 4 hexadecimals (2 bytes) or 8 hexadecimals (4 bytes); REF:http://www.unicode.org
|
||||
** 4 hexadecimal is 2 bytes (2^(4 * 4) -> 2^16)
|
||||
|
||||
==== char ====
|
||||
* Java definition of a codepoint which is encoded as 2 bytes (2^16 or 65,536)
|
||||
* For Western langauges: 1 codepoint equals 1 char (2 bytes);
|
||||
** For example, chars like "a", "œ", "é" are 1 Java char
|
||||
* For Eastern langauges: 1 codepoint can equal 2 chars (4 bytes);
|
||||
** For example, chars like "駣" are 2 Java chars though they represent 1 conceptual codepoint (in English terms, "駣" is a single letter just like the letter "a")
|
||||
|
||||
==== Supplementary characters ====
|
||||
* Represents a codepoint which is defined by 3 or 4 bytes
|
||||
* Is defined by 1 surrogate pair
|
||||
** lo-surrogate : 2 bytes
|
||||
** hi-surrogate : 2 bytes
|
||||
|
||||
=== Conventions ===
|
||||
* Codepoints will be rendered as one int (4 bytes), not 4 hexadecimals (1 byte) 8 hexadecimal (4 bytes)
|
||||
* The "char" datatype will rarely be used in code; instead byte arrays or codepoint-ints will be used
|
||||
* The "character" word will not be used in comments; instead the "codepoint" word will be used
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -17,7 +17,8 @@ package gplx.core.ios; import gplx.*; import gplx.core.*;
|
||||
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;
|
||||
@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;
|
||||
}
|
||||
|
@ -31,9 +31,10 @@ public class Js_wtr {
|
||||
bfr.Add_byte(Byte_ascii.Paren_end).Add_byte_semic();
|
||||
return this;
|
||||
}
|
||||
public Js_wtr Prm_bry(byte[] bry) {
|
||||
public Js_wtr Prm_str(String v) {return Prm_bry(Bry_.new_u8(v));}
|
||||
public Js_wtr Prm_bry(byte[] v) {
|
||||
Prm_spr();
|
||||
Write_val(bry);
|
||||
Write_val(v);
|
||||
return this;
|
||||
}
|
||||
public Js_wtr Prm_obj_ary(Object[] ary) {
|
||||
|
@ -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,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.xowa.wikis.pages; import gplx.*; import gplx.xowa.*; import gplx.xowa.wikis.*;
|
||||
public class Xopg_page_ {
|
||||
public static final byte Tid_read = 0, Tid_edit = 1, Tid_html = 2;
|
||||
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,26 +1,32 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
/*
|
||||
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; 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, "");}
|
||||
public static void Eq__ary(int[] expd, int[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__int, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(long[] expd, long[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__long, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary(byte[] expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__byte, expd, actl, msg_fmt, msg_args);}
|
||||
public static void Eq__ary__lines(String expd, String actl) {Eq__ary__lines(expd, actl, "no_msg");}
|
||||
public static void Eq__ary__lines(String expd, byte[] actl) {Eq__ary__lines(expd, String_.new_u8(actl), "no_msg");}
|
||||
public static void Eq__ary__lines(String expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__ary__lines(expd, String_.new_u8(actl), msg_fmt, msg_args);}
|
||||
public static void Eq__ary__lines(String expd, String actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bry, Bry_split_.Split_lines(Bry_.new_u8_safe(expd)), Bry_split_.Split_lines(Bry_.new_u8_safe(actl)), msg_fmt, msg_args);}
|
||||
@ -58,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);}
|
||||
@ -105,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);}
|
||||
@ -150,12 +158,14 @@ public class Gftest {
|
||||
}
|
||||
private static void Write__itm(Bry_bfr bfr, int type_id, Object ary, int len, int idx) {
|
||||
if (idx < len) {
|
||||
Object val = Array_.Get_at(ary, idx);
|
||||
switch (type_id) {
|
||||
case Type_ids_.Id__bool: bfr.Add_yn(Bool_.Cast(Array_.Get_at(ary, idx))); break;
|
||||
case Type_ids_.Id__bry: bfr.Add_safe((byte[])Array_.Get_at(ary, idx)); break;
|
||||
case Type_ids_.Id__long: bfr.Add_long_variable(Long_.cast(Array_.Get_at(ary, idx))); break;
|
||||
case Type_ids_.Id__int: bfr.Add_int_variable(Int_.Cast(Array_.Get_at(ary, idx))); break;
|
||||
case Type_ids_.Id__byte: bfr.Add_int_variable((int)(Byte_.Cast(Array_.Get_at(ary, idx)))); break;
|
||||
case Type_ids_.Id__bool: bfr.Add_yn(Bool_.Cast(val)); break;
|
||||
case Type_ids_.Id__bry: bfr.Add_safe((byte[])val); break;
|
||||
case Type_ids_.Id__long: bfr.Add_long_variable(Long_.cast(val)); break;
|
||||
case Type_ids_.Id__int: bfr.Add_int_variable(Int_.Cast(val)); break;
|
||||
case Type_ids_.Id__byte: bfr.Add_int_variable((int)(Byte_.Cast(val))); break;
|
||||
case Type_ids_.Id__obj: bfr.Add_str_u8(Object_.Xto_str_strict_or_null_mark(val)); break;
|
||||
default: throw Err_.new_unhandled_default(type_id);
|
||||
}
|
||||
}
|
||||
@ -181,6 +191,7 @@ public class Gftest {
|
||||
case Type_ids_.Id__long: eq = Long_.cast(expd_obj) == Long_.cast(actl_obj); break;
|
||||
case Type_ids_.Id__int: eq = Int_.Cast(expd_obj) == Int_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__byte: eq = Byte_.Cast(expd_obj) == Byte_.Cast(actl_obj); break;
|
||||
case Type_ids_.Id__obj: eq = Object_.Eq(expd_obj, actl_obj); break;
|
||||
}
|
||||
}
|
||||
if (!eq) {
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
/*
|
||||
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.texts; import gplx.*; import gplx.core.*;
|
||||
public class Base64Converter {
|
||||
private final static char[] ALPHABET = String_.XtoCharAry("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||
@ -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,23 +1,32 @@
|
||||
/*
|
||||
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.threads; import gplx.*; import gplx.core.*;
|
||||
import java.lang.*;
|
||||
/*
|
||||
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.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;
|
||||
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;
|
||||
private Thread thread;
|
||||
@gplx.Internal protected Thread_adp(String thread_name, Cancelable cxl, Gfo_invk invk_itm, String invk_cmd, GfoMsg invk_msg) {
|
||||
this.thread_name = thread_name; this.cxl = cxl; this.cxlable = cxl != Cancelable_.Never;
|
||||
@ -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);
|
||||
@ -37,8 +47,8 @@ public class Thread_adp implements Runnable {
|
||||
}
|
||||
}
|
||||
public void Thread__start() {
|
||||
this.thread = (thread_name == null) ? new Thread(this) : new Thread(this, thread_name);
|
||||
this.thread = (thread_name == null) ? new Thread(this) : new Thread(this, thread_name);
|
||||
thread.start();
|
||||
}
|
||||
public static final Thread_adp Noop = new Thread_adp(Thread_adp_.Name_null, Cancelable_.Never, Gfo_invk_.Noop, "", GfoMsg_.Null);
|
||||
}
|
||||
public static final Thread_adp Noop = new Thread_adp(Thread_adp_.Name_null, Cancelable_.Never, Gfo_invk_.Noop, "", GfoMsg_.Null);
|
||||
}
|
||||
|
@ -1,28 +1,36 @@
|
||||
/*
|
||||
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.threads; import gplx.*; import gplx.core.*;
|
||||
/*
|
||||
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.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 {
|
||||
Thread.sleep(milliseconds);
|
||||
} catch (InterruptedException e) {
|
||||
throw Err_.new_exc(e, "core", "thread interrupted", "milliseconds", milliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static Thread_adp Start_by_key(String thread_name, Gfo_invk invk_itm, String invk_cmd) {return Start(thread_name, Cancelable_.Never, invk_itm, invk_cmd , GfoMsg_.new_cast_(invk_cmd));}
|
||||
public static Thread_adp Start_by_key(String thread_name, Gfo_invk invk_itm, String invk_cmd) {return Start(thread_name, Cancelable_.Never, invk_itm, invk_cmd , GfoMsg_.new_cast_(invk_cmd));}
|
||||
public static Thread_adp Start_by_val(String thread_name, Gfo_invk invk_itm, String invk_cmd, Object val) {return Start(thread_name, Cancelable_.Never, invk_itm, invk_cmd , GfoMsg_.new_cast_(invk_cmd).Add("v", val));}
|
||||
public static Thread_adp Start_by_msg(String thread_name, Gfo_invk invk_itm, GfoMsg invk_msg) {return Start(thread_name, Cancelable_.Never, invk_itm, invk_msg.Key() , invk_msg);}
|
||||
public static Thread_adp Start_by_key(String thread_name, Cancelable cxl, Gfo_invk invk_itm, String invk_cmd) {return Start(thread_name, cxl, invk_itm, invk_cmd , GfoMsg_.new_cast_(invk_cmd));}
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user