1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2025-06-13 12:54:14 +00:00

Compare commits

..

352 Commits

Author SHA1 Message Date
gnosygnu
2a4abd8f75 Gui: Fix NullPointerException when pressing backspace on empty search box [#841] 2021-03-03 03:37:22 -05:00
gnosygnu
17a3b4e7b3 Parser: Only print value without ± if lo and hi are null [#839] 2021-02-14 08:13:31 -05:00
gnosygnu
659bca3660 Parser: Prepend 0 to all strings starting with ., even just . [#838] 2021-02-13 20:19:16 -05:00
gnosygnu
8684783139 Lang: Rename Pft_fmt_itm_hijri [#837] 2021-02-08 08:03:06 -05:00
gnosygnu
7e53c8462d Lang: Fix misspelling of hijri [#837] 2021-02-07 10:41:56 -05:00
gnosygnu
559503786b Release: Update app version [#833] 2021-01-26 08:03:13 -05:00
gnosygnu
e117823e60 Gui: Manually fire javascript event and exit [#836] 2021-01-25 08:07:23 -05:00
gnosygnu
ff0f92b950 Gui: Encode and decode image sources [#829] 2021-01-11 08:03:10 -05:00
gnosygnu
4187dc4a76 Gui: Strip about: from links during Copy [#823] 2021-01-05 02:06:20 -05:00
gnosygnu
1a6a203cfd Parser: Match for < + onlyinclude to fix false match [#825] 2020-12-17 07:48:28 -05:00
gnosygnu
814e85ea70 Release: Release v4.6.14.2012 to fix about:/wiki/ when doing "Open in new tab" [#823] 2020-12-16 09:02:02 -05:00
gnosygnu
0ef5058cfd Gui: Strip about:/wiki/ from links [#823] 2020-12-16 09:00:45 -05:00
gnosygnu
aeef520228 Dev: Fix failing tests after project rebuild [#826] 2020-12-14 08:53:28 -05:00
gnosygnu
4a7bd19056 Wikibase: Fix failing tests [#792] 2020-12-14 08:50:31 -05:00
gnosygnu
7d357540c7 ParserFunctions: Fail if e0 or pi0 [#819] 2020-11-25 06:34:13 -05:00
gnosygnu
b1c52aa2b2 ParserFunctions: Handle spaces in {{int}} keys [#817] 2020-11-03 07:59:21 -05:00
gnosygnu
845253af79 Mass_parse: Do not reuse json_parser else threading issues with itwiki [#818] 2020-11-03 06:51:31 -05:00
gnosygnu
541f5f6524 Css: Do not preprend selector for body [#815] 2020-11-01 10:45:38 -05:00
gnosygnu
067e62dd03 Release: Release v4.6.13.2010 [#797] 2020-10-19 09:42:18 -04:00
gnosygnu
19a315b8cd Skin: Change to mustache-backed Skin.Vector [#797] 2020-10-18 10:53:38 -04:00
gnosygnu
5c3d6a173b Wikibase: Calc precision by using longitude when precision is null [#792] 2020-09-25 08:42:52 -04:00
gnosygnu
c801e3a20b Scribunto: Allow int for find parameter [#802] 2020-09-23 08:44:58 -04:00
gnosygnu
59d8a42b22 Release: Update to 4.6.12.2009 [#801] 2020-09-23 08:44:14 -04:00
desb42
567e03dc1d Gui: Strip blank: from links [#799] 2020-09-21 19:29:29 -04:00
gnosygnu
7550894dda Release: Update for 4.6.11.2009 [#801] 2020-09-19 12:49:47 -04:00
gnosygnu
caad4145d5 Gui: Strip about: from links [#799] 2020-09-19 12:47:56 -04:00
gnosygnu
de841f8ff2 Wikibase: Reproduce geocoordinate logic of en.w:Module:Wd [#792] 2020-09-07 17:28:20 -04:00
gnosygnu
5f2e9c7514 Parser: Require coefficient for scientific notation [#795] 2020-09-07 08:32:47 -04:00
gnosygnu
d3896bf547 Parser: Remove Tmpl_result_cache, Bld_key, and corresponding code in Xot_invk_tkn [#793] 2020-09-04 08:20:18 -04:00
gnosygnu
316c6c6a58 Map: Compare precision against 4 not 0 [#792] 2020-09-03 08:32:16 -04:00
gnosygnu
72051f4ce9 Wikibase: Default 'null' to 0, not 1 [#792] 2020-09-03 08:23:57 -04:00
gnosygnu
f19228c886 Mass_parse: Add error_filter to ignore logging certain errors [#793] 2020-09-01 09:02:47 -04:00
gnosygnu
1b6324938c Release: Upgrade version to 4.6.10.2008 for Mac OS X fix [#687] 2020-09-01 08:45:14 -04:00
gnosygnu
9b4ea48753 Install: Upgrade to SWT 4.16 [#687] 2020-08-31 09:06:19 -04:00
gnosygnu
6ed7659b4d Core: Parse decimal 'e' as 'E' [#565] 2020-08-27 06:04:17 -04:00
gnosygnu
1eea3682ca SyntaxHighlight: Treat syntaxHighlight inline as enclose=none [#794] 2020-08-27 05:25:59 -04:00
gnosygnu
4f87d1a195 Image: Mark tif orig files as not images [#788] 2020-08-26 09:01:43 -04:00
gnosygnu
ea9b592cfd Html: Do not remove role= attributes from html tags [#785] 2020-08-18 06:14:25 -04:00
gnosygnu
3c9fd50ddc Pagebanner: Show pageBanner for Wikivoyage namespace [#748] 2020-08-17 07:46:44 -04:00
gnosygnu
619d2f9844 Dev: Include baselib in core classpath [#697] 2020-08-14 09:09:17 -04:00
gnosygnu
bdae819908 Scribunto: Trim zeroes when stringifying Doubles [#697] 2020-08-12 08:48:30 -04:00
gnosygnu
f122a8d8a3 Wikibase: Prepend claim_type with "wikibase-" for lexeme, form, sense [#771] 2020-08-09 13:18:19 -04:00
gnosygnu
174e93cbfa Parser: Add namespace to Template title [#784] 2020-08-09 13:03:41 -04:00
gnosygnu
0aced904a5 Edit: Save compiled HTML when editing pages [#699] 2020-08-06 07:09:34 -04:00
gnosygnu
dc374fa7fc Html: Add 'contentSub2' to xowa.gfs [#783] 2020-08-04 08:28:02 -04:00
gnosygnu
95e833d70c Wikibase: Fix NullPointerException on a few fr.w pages [#773] 2020-08-04 07:24:52 -04:00
gnosygnu
afed865c84 Scribunto: Implement'lang argument for mw.ext.data.get [#779] 2020-08-03 08:37:51 -04:00
gnosygnu
7b6b3ed09a Wikibase: Implement lexeme, form, and sense [#771] 2020-07-31 07:44:00 -04:00
gnosygnu
a0c0b5b2fd HTTP Server: Fix broken links in left nav [#768] 2020-07-23 08:19:24 -04:00
gnosygnu
062d308128 Scribunto: Do not return early in Gsub if source is String.empty [#731] 2020-07-20 08:28:08 -04:00
gnosygnu
ad607d952c Release: Bump version to 4.6.9.2007 [#761] 2020-07-17 09:08:55 -04:00
gnosygnu
6592eaf8de Gui: Fix page loading in wrong wiki after switching tab positions [#761] 2020-07-17 09:07:18 -04:00
gnosygnu
45adc036a2 Luaj: Check for error in LoadString [#759] 2020-07-15 08:06:21 -04:00
gnosygnu
6b2e120fc1 Css: Fix top tabs showing vertically instead of horizontally [#754] 2020-07-02 09:08:26 -04:00
gnosygnu
7c0a8c5064 Luaj: Sync LuaString with latest Luaj source [#735] 2020-07-02 08:00:10 -04:00
gnosygnu
35475d631c Http_server: Fix images not downloading on some Portal pages [#686] 2020-06-27 19:28:42 -04:00
gnosygnu
efe415d3a3 Scribunto: Add help text for xowa.app.settings.publish [#737] 2020-06-20 17:55:01 -04:00
gnosygnu
97b1055b4e Scribunto: Add configurable timeout for en.wikipedia.org and 'Authority_control' [#737] 2020-06-20 17:47:42 -04:00
gnosygnu
b51d224f09 Html: Add 'mw-footer' class to 'footer' div [#745] 2020-06-16 09:05:16 -04:00
gnosygnu
b87e4d07cb Scribunto: Hack fix for stopping long-running threads [#737] 2020-06-15 10:18:34 -04:00
gnosygnu
b4516f5060 Luaj: Change table.sort from MergeSort to QuickSort variant with stable sorting [#743] 2020-06-13 09:37:43 -04:00
gnosygnu
49e18a2255 Css: Prepend '.mw-parser-output' to all nested classes [#741] 2020-06-09 08:38:26 -04:00
gnosygnu
026288f809 Css: Change java.lang.String.charAt to JsString_.charAt (with JsString_.charAt) [#741] 2020-06-08 09:00:39 -04:00
gnosygnu
1103674d88 Css: Change java.lang.String.charAt to JsString_.charAt [#741] 2020-06-08 08:58:32 -04:00
gnosygnu
27756f8056 Scribunto: Hack timeout to limit Scribunto execution to 5 seconds [#737] 2020-06-07 21:41:46 -04:00
gnosygnu
398a1c854a Luaj: Use substring.m_bytes, not substring.getBytes() [#735] 2020-06-03 09:21:25 -04:00
gnosygnu
35f2027b20 Scribunto: Create match string using char-indexes, not codepointIndexes (to handle UTF-8 strings) [#726] 2020-05-31 01:19:24 -04:00
gnosygnu
be072de8d9 Luaj: Reinstate next variable for frontier matches [#732] 2020-05-29 09:15:00 -04:00
gnosygnu
f760fd9cd0 Luaj: Do not match end-of-string for frontier patterns [#732] 2020-05-29 07:23:38 -04:00
gnosygnu
3d5ec47aa8 Html: Do not call Xtn property for non-Xtn XML nodes [#730] 2020-05-27 09:18:53 -04:00
gnosygnu
53762288d7 Release: Release embeddable app version (v4.6.7) [#733] 2020-05-27 08:19:26 -04:00
gnosygnu
7a0247417d Embeddable: Do not call hxtn code during embeddable [#733] 2020-05-27 07:29:39 -04:00
gnosygnu
0cdfa0992c Hdump: Serialize / deserialize top-icon [#721] 2020-05-26 08:38:50 -04:00
gnosygnu
dc66b926d3 Release: Change default download server from dumps.wikimedia.your.org to dumps.wikimedia.org [#727] 2020-05-20 20:16:00 -04:00
gnosygnu
8c7c9f88ff Hdump: Show category at bottom of Category pages [#722] 2020-05-17 17:04:25 -04:00
gnosygnu
94b757682a Luaj: Make anypos captures base-1, not base-0 (with fixed test) [#724] 2020-05-17 11:38:06 -04:00
gnosygnu
1ebc9d3488 Luaj: Make anypos captures base-1, not base-0 [#726] 2020-05-17 11:27:38 -04:00
gnosygnu
654810d56c Html: Add 'lang' to <h1> [#724] 2020-05-15 09:34:09 -04:00
gnosygnu
b551c1875b Html: Show Read, Edit, ViewHtml in correct right-to-left order for RTL languages [#723] 2020-05-15 09:02:45 -04:00
gnosygnu
ba1d4e0b7c XOMW: Add Globals and refine XomwMediaWikiServices [#632] 2020-05-14 08:58:45 -04:00
gnosygnu
a2fe75f402 RandomRootPage: Do not fail to find page for some random selections; also, do not show 'Redirected from redirected_title' [#719] 2020-05-13 09:20:46 -04:00
gnosygnu
a6331f5c89 XOMW: Finish XomwServiceContainer [#632] 2020-05-12 08:13:31 -04:00
gnosygnu
43866163b9 XOMW: Add Assert [#632] 2020-05-11 08:38:35 -04:00
gnosygnu
49f8d4b000 Lst: Handle keys with whitespace [#720] 2020-05-10 09:37:04 -04:00
gnosygnu
994d405a26 Release: Increase version number [#694] 2020-05-10 08:33:43 -04:00
gnosygnu
04c499ce3e XOMW: Add PHP array-diff and array-diff-key [#632] 2020-05-10 07:43:30 -04:00
gnosygnu
ebe82bea6a LuaJ: Always format in Locale.US, not current locale [#694] 2020-05-09 16:24:59 -04:00
gnosygnu
a9367eaca8 XOMW: Consolidate XophpArray_ into XophpArray [#632] 2020-05-09 07:21:14 -04:00
gnosygnu
ee68162a4a XOMW: Add more implementation for XomwServiceContainer [#632] 2020-05-08 09:18:46 -04:00
gnosygnu
6663b769d5 Dev: Fix broken 'xowa_get_and_make.sh' due to JDK 8 and new *Test files [#718] 2020-05-07 09:30:48 -04:00
gnosygnu
2dab6a90be XOMW: Start XomwServiceContainer [#632] 2020-05-07 08:58:15 -04:00
gnosygnu
b0e02979ac XOMW: Start XomwRequestContext [#632] 2020-05-05 08:14:21 -04:00
gnosygnu
f9cf49c160 XOMW: Start XomwMessage [#632] 2020-05-04 08:29:37 -04:00
gnosygnu
0d917bccc7 XOMW: Finish XomwHooks - part 2 [#632] 2020-05-03 09:19:47 -04:00
gnosygnu
d1345bf724 XOMW: Finish XomwHooks [#632] 2020-05-03 09:19:19 -04:00
gnosygnu
3d74406a3e XOMW: Add array_filter [#632] 2020-05-02 08:30:47 -04:00
gnosygnu
a6b128422e XOMW: More XomwHooks implementation [#632] 2020-05-01 09:01:40 -04:00
gnosygnu
0c3cb1ba3d HTTP Server: Do not show new logic for SWT/GUI tabs ('wikiName - message' if mainPage, else 'pageName - wikiName') [#715] 2020-05-01 08:55:03 -04:00
gnosygnu
105446f5ca HTTP Server: Show correct tab / html.head name for pages ('wikiName - message' if mainPage, else 'pageName - wikiName') [#715] 2020-05-01 08:45:01 -04:00
gnosygnu
db73b4302d Xomw: Add some implementation for XomwHooks [#632] 2020-04-29 07:32:10 -04:00
gnosygnu
bd71db3ed6 Xomw: Add more implementation near statelessFetchTemplate [#632] 2020-04-27 08:39:30 -04:00
gnosygnu
a4b5f5de5d TemplateStyles: Apply wrapper to each class, not to top only [#712] 2020-04-26 15:51:56 -04:00
gnosygnu
ecbcf1e707 GFLucene: Add lucene binaries [#707] 2020-04-26 08:09:27 -04:00
gnosygnu
7b00918941 XOMW: Rename XomwTitle to XomwTitleOld [#632] 2020-04-26 08:08:39 -04:00
gnosygnu
8807dcfbeb TemplateStyles: Support wrapper argument [#712] 2020-04-23 08:18:03 -04:00
gnosygnu
a6ac592212 TemplateStyles: Add mw-parser-output in XoCssMin, not in TemplateStyles [#704] 2020-04-22 08:17:54 -04:00
gnosygnu
b05e3cd188 File: Add '.stl' and '.webp' as image extensions [#710] 2020-04-21 08:31:40 -04:00
gnosygnu
9c8650a4d9 Dev: Modify .gitignore files for IntelliJ .iml files [#709] 2020-04-20 07:31:23 -04:00
gnosygnu
73a56ffab3 TemplateStyles: Add XoCssMin from @desb42 [#704] 2020-04-19 08:54:54 -04:00
gnosygnu
e9e5724a2a Make: Add baselib to xowa classpath [#706] 2020-04-13 07:23:39 -04:00
gnosygnu
c3c9d4ad1e Html: Do not add '\n' to media anchor links [#703] 2020-04-10 07:53:45 -04:00
gnosygnu
5a35f3b05b TemplateStyles: Scope TemplateStyles css to main content div by adding 'mw-parser-output' [#426] 2020-04-10 07:07:28 -04:00
gnosygnu
7ad1291768 XomwTemplateParser: Port XomwPreprocessor classes as direct translation of MW code [#632] 2020-04-09 08:10:22 -04:00
gnosygnu
17d7a7ebed XomwTemplateParser: Port other XomwPPTemplateFrame classes [#632] 2020-04-03 06:39:35 -04:00
gnosygnu
9809dfd6c7 XomwTemplateParser: Port XomwPPTemplateFrame_Hash [#632] 2020-03-31 07:46:17 -04:00
gnosygnu
b56673c56e HTTP Server: Url-encode urls in portal div [#572] 2020-03-28 10:33:04 -04:00
gnosygnu
8629292960 Wikibase: Parse e as exponent in wikidata json [#565] 2020-03-25 06:09:57 -04:00
gnosygnu
bc30fd8526 ParserFunctions: Round numbers to default precision of 14 [#683] 2020-03-24 06:46:24 -04:00
gnosygnu
c47820b1a9 Category: (partial) Deactivate mw-category logic [#677] 2020-03-16 07:32:06 -04:00
gnosygnu
292726bd13 Category: (partial) Update messages for category [#677] 2020-03-16 07:29:05 -04:00
gnosygnu
23eefef91a Log: Fix garbled messages still during HTML build [#646] 2020-03-16 06:31:31 -04:00
gnosygnu
89d0ba1271 Dev: Refactor Xoa_ttl to use one url_encoder [#627] 2020-03-10 08:18:04 -04:00
gnosygnu
b2a6f7bbf1 Xtn.Is_in: Escape double-quotes as &quot; [#627] 2020-03-10 07:49:38 -04:00
gnosygnu
ed010f76a8 Table_of_contents: Skip whitespace after slash; Add <mark> as valid HTML tag [#542] 2020-03-09 07:56:21 -04:00
gnosygnu
bc65e9fa61 Hxtn: Edit comment message [#634] 2020-03-08 16:36:42 -04:00
gnosygnu
db01707032 Hxtn: Ignore unknown wkr_ids to allow hxtns developed by others [#634] 2020-03-08 16:32:00 -04:00
gnosygnu
7b3d6e5271 Html: Update HTML Santizer whitelist [#636] 2020-03-08 12:04:46 -04:00
gnosygnu
c3d524c493 Wikibase: Reset pageEntityId on each new page [#638] 2020-03-07 23:46:21 -05:00
gnosygnu
f33f9c4ae9 References: Do not make linkLabelMgr a global reference [#495] 2020-03-07 08:49:09 -05:00
gnosygnu
02f9b9dae3 Category: Show either Category or Categories depending on number of categories [#674] 2020-03-04 08:24:14 -05:00
gnosygnu
891cf53228 Dev: Rename 'Pxd_itm_tz_abbr .java' to 'Pxd_itm_tz_abbr.java' (remove trailing space) [#676] 2020-03-04 08:00:51 -05:00
gnosygnu
f73164d55e Wikibase: Add extra-case to RenderSnaks for key=pid,val=snaks [#666] 2020-03-01 18:48:08 -05:00
gnosygnu
3355d03c44 Wikibase: Use 2nd argument to GetSiteLinkPageName for wiki name [#665] 2020-02-19 08:39:43 -05:00
gnosygnu
bae9ba9e7a Parser: Return length of 0 for empty arrays [#668] 2020-02-17 08:47:34 -05:00
gnosygnu
a5cbc4ede9 ParserFunctions: Add constructor for future use [#661] 2020-02-17 08:42:25 -05:00
gnosygnu
da87b17902 ParserFunctions: Comment out unused variables [#661] 2020-02-17 08:34:29 -05:00
gnosygnu
bfce37f0ba ParserFunctions: Add PHP implementation of strtotime [#661] 2020-02-08 21:58:12 -05:00
gnosygnu
3e9bc6d93a Category: Parse year as yyyy not YYYY [#664] 2020-02-05 08:15:19 -05:00
gnosygnu
775bff3bac Wikibase: Do not fail for FormatStatements and getPropertyOrder [#658] 2020-02-02 21:02:11 -05:00
gnosygnu
bc2beba148 Pages: Do not escape <pages> if invalid attributes [#656] 2020-01-19 14:28:22 -05:00
gnosygnu
af337493af Pages: Forward unknown args to header template [#635] 2020-01-19 13:49:24 -05:00
gnosygnu
ca8afe657e Pages: Treat empty-string as non-null for from / to [#657] 2020-01-19 10:44:38 -05:00
gnosygnu
57ad8e459a ParserFunctions: Fix some comments for meridian [#648] 2020-01-18 16:47:13 -05:00
gnosygnu
763c7b52b7 ParserFunctions: Support timezone / meridian formats [#648] 2020-01-18 16:39:16 -05:00
gnosygnu
9cb60f2540 Redirect: Add span for 'mw-redirected' [#642] 2020-01-14 06:31:23 -05:00
gnosygnu
c6bca54d90 Hdump: Try to eliminate dupes by updating Html_uid for lnki [#643] 2020-01-12 11:00:11 -05:00
gnosygnu
374de22699 ParserFunctions: Set day to last day of month if only Year-Feb passed [#644] 2020-01-12 09:50:01 -05:00
gnosygnu
2dee585fc1 Pages: Treat empty-string as null for fromsection and tosection [#650] 2020-01-11 21:41:37 -05:00
gnosygnu
898701131d Css: Skip comments when importing CSS [#652] 2020-01-11 09:40:34 -05:00
gnosygnu
c1b8911a7d Log: Fix out-of-order log messages during HTML build [#646] 2020-01-09 07:09:47 -05:00
gnosygnu
f384d40e56 Doc: Add HTTP_Server Advanced doc [#621] 2020-01-08 22:56:16 -05:00
gnosygnu
278d55cd62 Gallery: Apply Math.Ceil to packed gallery [#640] 2020-01-08 22:53:37 -05:00
gnosygnu
11447820f2 Doc: Add instructions for disabling Special pages and edit mode [#621] 2020-01-05 12:36:46 -05:00
gnosygnu
5e2ce08abb Xomw: Standardize static classes [#633] 2020-01-05 08:52:37 -05:00
gnosygnu
5aec368f8d Lang: Support explicit plural indexes and rules in other languages [#633] 2020-01-04 04:14:36 -05:00
gnosygnu
5f1d9c6f15 Category: Group category members under same upper-cased letter [#637] 2019-12-14 19:35:13 -05:00
gnosygnu
e0de779e1d Gallery: Enable packed-hover for galleries [#631] 2019-12-08 08:50:07 -05:00
gnosygnu
bc5947507f XomwTemplateParser: Start porting over newChild [#632] 2019-12-08 08:30:28 -05:00
gnosygnu
7e2f832c33 Refactor: Rename Xoa_ttl.Full_txt_w_ttl_case to Full_txt [#626] 2019-12-08 08:24:47 -05:00
gnosygnu
357c725798 Add missing segments to subtitle_caption; also, do not url-encode caption [#626] 2019-12-07 17:18:48 -05:00
gnosygnu
694c3bb133 XomwTemplateParser: Initial port of PPFrame_Hash [#632] 2019-12-07 08:13:52 -05:00
gnosygnu
3285a3c87d Xtn.Pages: Do not show missing pages in subpages bread-crumb trail (also, proper-case titles) [#626] 2019-12-01 11:43:33 -05:00
gnosygnu
520a73537f Xtn.Pages: Do not escape XML in header previous / current / next links [#624] 2019-11-30 17:15:23 -05:00
gnosygnu
9d8ab5d206 Xtn.Pages: Treat header=0 as false [#622] 2019-11-28 09:16:16 -05:00
gnosygnu
d49eda32a8 DB: Add misc commit for fieldList [#619] 2019-11-28 09:15:54 -05:00
gnosygnu
eca943d7a6
Merge pull request #620 from gnosygnu/dependabot/maven/res/dev/make/maven/org.apache.commons-commons-compress-1.19
Bump commons-compress from 1.18 to 1.19 in /res/dev/make/maven
2019-11-26 07:05:40 -05:00
gnosygnu
a7114ecb5a Dev: Update Apache Compress to 1.19 in pom.xml [#619] 2019-11-25 20:58:02 -05:00
dependabot[bot]
ad5613265d
Bump commons-compress from 1.18 to 1.19 in /res/dev/make/maven
Bumps commons-compress from 1.18 to 1.19.

Signed-off-by: dependabot[bot] <support@github.com>
2019-11-26 01:35:44 +00:00
gnosygnu
734206fbd6 Dev: Update Apache Compress to 1.18 in pom.xml [#619] 2019-11-25 20:35:21 -05:00
gnosygnu
605038d8c6 Release: v4.6.5.1911 [#619] 2019-11-25 20:24:12 -05:00
gnosygnu
ae484a8234 Pagebanner: Add extra space after hasPosition or some pageBanners will omit wpb-banner-image [#618] 2019-11-25 16:43:11 -05:00
gnosygnu
cb3b78895c Html_dump: Add no-op related commits [#547] 2019-11-25 16:31:45 -05:00
gnosygnu
38f670649b Html_dump: Show images with plus symbol [#547] 2019-11-25 16:31:02 -05:00
gnosygnu
9e97a7ea9f Html_dump: Show images for files with url-encoded characters (space, symbols, non-ascii) [#547] 2019-11-25 05:26:39 -05:00
gnosygnu
966b0eed59 Luaj: Do not treat superscript 1 as a DIGIT character [#617] 2019-11-24 16:20:58 -05:00
gnosygnu
59985227fb Wikibase: Change siteGlobalID to wiki-specific abbreviation, not wikidatawiki [#614] 2019-11-23 17:32:18 -05:00
gnosygnu
c307946bd2 Scribunto: Synchronize latest of mw.wikibase.entity.lua [#614] 2019-11-23 05:30:44 -05:00
gnosygnu
b2864f8c6a Scribunto: Cache results of title.exists [#597] 2019-11-18 06:25:57 -05:00
gnosygnu
41a521850b TemplateStyles: Add unit test for single-word paragraph bug [#616] 2019-11-18 05:25:22 -05:00
gnosygnu
20c1e32ff2 PageBanner: Fix NullPointer Exception [#610] 2019-11-17 21:02:41 -05:00
gnosygnu
90363fb9fa Template_styles: Close block opened by template-styles [#616] 2019-11-17 20:59:18 -05:00
gnosygnu
46aab7944d Pagebanner: Fix TOC not working from header; also, hide TOC always, not just on 2nd+ load [#610] 2019-11-17 20:14:44 -05:00
gnosygnu
5ddf50d5b5 Search: Wait for page to load before displaying search results [#606] 2019-11-17 15:57:35 -05:00
gnosygnu
e2aa551feb Search: Fix no search results for en.d [#606] 2019-11-17 14:30:49 -05:00
gnosygnu
11810c4fff HTTP_Server: Fix broken test by adding manual override for wiki.Installed [#613] 2019-11-17 14:28:37 -05:00
gnosygnu
e9024e057f HTTP Server: Show error page when navigating to wikis which are not installed [#613] 2019-11-13 08:43:34 -05:00
gnosygnu
9483b56121 Pagebanner: Disable toc if pagebanner html exists; also, sync PageBanner css [#610] 2019-11-11 06:27:49 -05:00
gnosygnu
8653e665cc HTTP_Server: Add 2 line breaks to redirect response for proxy servers [#600] 2019-11-05 06:04:19 -05:00
gnosygnu
dbdc558ed5 Gui: Remove unused serialization code for history items [#608] 2019-11-03 19:49:54 -05:00
gnosygnu
bdb1945d4f Scribunto: Synchronize latest of ustring.lua [#609] 2019-11-03 19:34:59 -05:00
gnosygnu
af9d6c3a92 Gui: Fix NPE when reloading a MISSING_PAGE at start-up [#608] 2019-11-03 17:45:30 -05:00
gnosygnu
de1b9a3991 Pagebanner: Update css classes for 'wpb-banner-image-panorama' [#610] 2019-11-03 17:40:50 -05:00
gnosygnu
d908d4f8b5 HTTP Server: Redirect xwiki urls to different wikis [#600] 2019-11-03 11:43:09 -05:00
gnosygnu
79bdab7946 HTTP Server: Redirect xwiki urls to different wikis [#600] 2019-11-03 11:42:28 -05:00
gnosygnu
0f8dd4a1f8 Luaj: Return NIL not NONE for table.remove and empty table [#604] 2019-10-30 09:40:08 -04:00
gnosygnu
cb3f915cb2 Wikibase: Redirect formatValue and formatValues to renderSnak and renderSnakValues [#593] 2019-10-20 13:25:19 -04:00
gnosygnu
a453ebd4cb Wikibase: Reorganize Wikibase classes; add some basic support for formatters [#593] 2019-10-20 09:28:28 -04:00
gnosygnu
7971f71dc3 Category: Add basic enums for 'numeric' and 'identity' [#601] 2019-10-15 05:15:50 -04:00
gnosygnu
f8bbdb1727 Wikibase: Combine same references from Wikidata [#596] 2019-10-15 04:30:14 -04:00
gnosygnu
bc976ac300 ParserFunctions: Add ParserFunction for PageLanguage [#595] 2019-10-13 16:52:32 -04:00
gnosygnu
c67970b5b9 Parser: Do not assume that Name_ui_w_colon matches Name [#594] 2019-10-13 11:30:40 -04:00
gnosygnu
eac055214c Scribunto: Update Diagnostics for Scribunto Hash:Diagnostics/Scribunto/HashLibrary [#589] 2019-10-12 15:19:45 -04:00
gnosygnu
866debd51d Scribunto: Add HashLibrary [#589] 2019-10-12 15:07:21 -04:00
gnosygnu
9f0cfc27bb Parser: Auto-inline dangling references tag [#583] 2019-10-06 08:40:26 -04:00
gnosygnu
a10c2cd1dc Parser: Auto-close dangling references tag [#583] 2019-10-05 12:41:48 -04:00
gnosygnu
4955748f6d Wikibase: Serialize 'references' [#587] 2019-10-03 06:34:11 -04:00
gnosygnu
73eb42c0ba Score: Clean-up test [#577] 2019-10-03 06:30:22 -04:00
gnosygnu
fca507568f Score: Check for missing src for score generated images [#577] 2019-10-02 05:51:21 -04:00
gnosygnu
1bffdadbaf Scribunto: Make table accessible from datawrapper in mw.lua [#586] 2019-09-29 23:21:08 -04:00
gnosygnu
bb86b026fe Html_dump: Include namespace+title in redlink ttl, not just title [#568] 2019-09-29 08:35:50 -04:00
gnosygnu
88e0398696 Html: Add 'lang=page_lang' to html and div tag [#576] 2019-09-28 16:39:59 -04:00
gnosygnu
e82641f341 Luaj: Do not treat '_' as a SPACE character [#582] 2019-09-28 08:37:00 -04:00
gnosygnu
597c138b56 Parser: Do not reset attributes when tag has more than 16 attributes (comment) [#579] 2019-09-27 21:09:55 -04:00
gnosygnu
fdd05c99a9 Parser: Do not reset attributes when tag has more than 16 attributes [#579] 2019-09-27 20:39:09 -04:00
gnosygnu
742e61b718 Hdump: Add missing Xoh_hdump_wkr [#584] 2019-09-27 20:24:32 -04:00
gnosygnu
1caeea5705 Xtn.Graph: Do not dump build-path for graph [#553] 2019-09-25 23:38:02 -04:00
gnosygnu
24ea3793a2 Xtn.Imap: Do not dump build-path for imap [#553] 2019-09-25 23:37:59 -04:00
gnosygnu
ec9b3ee442 Xtn.Hiero: Do not dump build-path for hiero [#553] 2019-09-25 23:37:55 -04:00
gnosygnu
ea28172885 Parser: Add hdump wkrs [#553] 2019-09-25 23:37:52 -04:00
gnosygnu
d362597d8f Parser: Do not dump build-path for imgs [#553] 2019-09-25 23:37:49 -04:00
gnosygnu
924b5fd17b Parser: Add parser-related test methods [#553] 2019-09-25 23:37:45 -04:00
gnosygnu
b980351989 Parser: Add Bfr to hdoc_wkr [#553] 2019-09-25 23:37:42 -04:00
gnosygnu
518605ece1 Parser: Rename Hzip types to Hdb_htxt and Hdb_hzip [#553] 2019-09-25 23:37:39 -04:00
gnosygnu
115ae8139e Parser:Add extra method overload to Log_file [#553] 2019-09-25 23:37:35 -04:00
gnosygnu
b17cb05edf Parser: Move alt attribute earlier in tag [#553] 2019-09-25 23:37:32 -04:00
gnosygnu
a082e3cf5d Parser: Add Init_once for wiki [#553] 2019-09-25 23:37:29 -04:00
gnosygnu
5b2db5badf Parser: Add To_str for Html_init [#553] 2019-09-25 23:37:24 -04:00
gnosygnu
32cb332b18 Wikidata: Remove unnecessary novalue / somevalue [#553] 2019-09-25 23:37:21 -04:00
gnosygnu
23cbefdeb8 Xtn.Dpl: Move Dpl_page_sorter to separate file [#553] 2019-09-25 23:37:18 -04:00
gnosygnu
620f196d4e Core: Add additional test classes [#553] 2019-09-25 23:37:04 -04:00
gnosygnu
75105c8397 Performance: Disable dirty flag after formatter is compiled [#575] 2019-09-16 22:15:47 -04:00
gnosygnu
b67e528088 Luaj: Handle % at end of replacement string [#571] 2019-09-08 23:05:25 -04:00
gnosygnu
9e302b19b5 Parser: Trim url-encoded space from the end of a title [#567] 2019-09-07 08:23:46 -04:00
gnosygnu
ce5fd232d8 Html_dump: Count 0 byte entries as 1 byte [#561] 2019-09-04 20:33:27 -04:00
gnosygnu
cda21d987f Parser: Do not reuse byte array when trimming bfr [#562] 2019-09-02 22:30:08 -04:00
gnosygnu
8f029f479b Wikibase: Show 'unknown value' / 'no value' instead of 'somevalue' / 'no value' [#529] 2019-09-02 15:33:48 -04:00
gnosygnu
d61fd33a87 References: Ignore follow items when writing primary reference [#555] 2019-09-01 10:29:55 -04:00
gnosygnu
1873c7c5f8 Wikibase: Fix typo on 'addSiteLinksUsage' and disable fineGrainedLuaTracking [#551] 2019-08-31 15:57:40 -04:00
gnosygnu
88dfc857bd Wikibase: Return label and language, not just label [#407] 2019-08-31 08:57:25 -04:00
gnosygnu
9bc0c2c75d Wikibase: Add namespacing to Scribunto libraries [#551] 2019-08-28 22:56:11 -04:00
gnosygnu
2598dee844 Xtn.Dpl: Change dynamicPageList to always get categories from cache [#556] 2019-08-25 21:39:21 -04:00
gnosygnu
42842f0bcc Category: Replace spaces with underscores in category name [#557] 2019-08-22 07:07:15 -04:00
gnosygnu
a7029f8cf1 Search: Do not fail with error when searching in wikidata / commons [#539] 2019-08-21 21:43:44 -04:00
gnosygnu
8c55d2406a Wikibase: Fix 'Module:Infobox/Cycliste:218 attempt to call nil' on many fr.w pages [#551] 2019-08-19 22:21:22 -04:00
gnosygnu
0295d816fd HTTP Server: Handle both 'file:///cur_root' and 'file:///bad_root/' [#524] 2019-08-16 02:30:10 -04:00
gnosygnu
80f4a0fbf5 Category: Fix 'A table in the database is locked' when importing en.d [#543] 2019-08-14 22:58:46 -04:00
gnosygnu
227f7943ff Html_dump: Add missing file for showing configuration to show WIKITEXT / HTML indicators in top-right [#525] 2019-08-14 22:14:00 -04:00
gnosygnu
7f3ab5f381 HTTP_Server: Ignore other request headers (Chrome incognito related) [#524] 2019-08-14 21:52:25 -04:00
gnosygnu
5ac949e8c0 HTTP Server: Generalize file:///root logic even more [#524] 2019-08-14 21:51:50 -04:00
gnosygnu
1e254caa79 Html_dump: Synchronize Xol_name_mgr [#549] 2019-08-14 08:03:20 -04:00
gnosygnu
41e9fc1287 Release: v4.6.4.1908 2019-08-14 08:01:00 -04:00
gnosygnu
be5c65c24c User.Cfg: Ignore duplicate keys in user cache [#534] 2019-08-11 14:28:51 -04:00
gnosygnu
87163c5104 Luaj: Add deprecated foreach / foreachi [#531] 2019-08-11 11:53:14 -04:00
gnosygnu
e213d123f8 Search.Suggest: Move highlighting code out of cache pathway to js_wtr [#538] 2019-08-11 08:33:17 -04:00
gnosygnu
dee491a684 HTTP Server: Remove trailing new line else POST log messages will show up with extra blank line [#537] 2019-08-11 08:02:10 -04:00
gnosygnu
2ef6211e87 HTTP Server: Fix NullPointerException when restarting HTTP_Server and going directly to search suggest [#537] 2019-08-11 08:00:49 -04:00
gnosygnu
6449368800 HTTP_Server: Move call to fsys_hack for mild performance improvement [#524] 2019-08-10 17:35:45 -04:00
gnosygnu
06afe7a7b1 Html_dump: Add configuration to show WIKITEXT / HTML indicators in top-right [#525] 2019-08-10 17:17:50 -04:00
gnosygnu
6559a2b858 Cfg: Fix 'Show search' and 'Show toolbar' not working [#532] 2019-08-10 08:39:53 -04:00
gnosygnu
a421703fb1 HTTP_Server: Generalize file:///.*/file/.* logic [#524] 2019-08-10 08:17:39 -04:00
gnosygnu
a94279c922 Sqlite: Fix faster wiki loading for read-only devices not working for Read-only files [#534] 2019-08-08 20:36:36 -04:00
gnosygnu
19c50b94be Release: v4.6.3.1908 2019-08-04 23:35:48 -04:00
gnosygnu
55a4891064 HTTP Server: Fix search-suggest not working for vector ul [#489] 2019-08-04 23:18:24 -04:00
gnosygnu
b350d95206 HTTP Server: Add search-suggest [#489] 2019-08-04 21:25:04 -04:00
gnosygnu
f5abfa11da HTTP Server: Append url_args to page [#489] 2019-08-03 17:33:04 -04:00
gnosygnu
66039fc9b3 HTTP_Server: Temporary fix to handle broken links and images in 2019-05 enwiki [#524] 2019-08-03 10:04:11 -04:00
gnosygnu
a1da02a99f HTTP_Server: Add initial implementation for post-processing HTML to change to /fsys/ etc [#524] 2019-08-03 10:00:40 -04:00
gnosygnu
a51906bf4b Make: Update wiki domains for 2019-06 Wikidata [#528] 2019-07-31 23:31:20 -04:00
gnosygnu
f38930b63a Xomw.Preprocessor: Remove deleted classes [#508] 2019-07-29 21:41:58 -04:00
gnosygnu
0854cf9ba1 Xomw.Preprocessor: Integrate rest of Preprocessor_Hash tests [#508] 2019-07-28 10:42:02 -04:00
gnosygnu
0280254e8a Scribunto: Use m_offset when doing string.substring [#520] 2019-07-25 23:34:34 -04:00
gnosygnu
9dcc571fc5 Release: 4.6.2.1907 2019-07-25 21:51:41 -04:00
gnosygnu
dea0556df5 Xomw.Preprocessor: Add XomwPPDStackElement [#508] 2019-07-24 22:17:21 -04:00
gnosygnu
436f219477 Mass_parse: Add thread-locking to LRU cache [#518] 2019-07-23 22:47:22 -04:00
gnosygnu
5c8b70fd76 Mass_parse: Use page_cache hashCode, not wiki hashCode [#514] 2019-07-22 22:38:17 -04:00
gnosygnu
4547fa541f Dev: Move XomwEnv.NewTest to XomwEnv_fxt.NewTest [#512] 2019-07-22 21:57:47 -04:00
gnosygnu
9bc2bd400c Dev: Rename test files to use '_tst' and '_fxt' convention [#512] 2019-07-22 21:51:24 -04:00
gnosygnu
877b305136 Luaj: Fix invalid url-encoding for non-ASCII characters like 'æ' [#504] 2019-07-22 21:01:30 -04:00
gnosygnu
0181a42d3d Xomw.Preprocessor: Add initial unit tests for DOM [#508] 2019-07-21 22:09:21 -04:00
gnosygnu
3b5a1f8ffc Xtn.Popups: Disable popups by default for en.wiktionary.org [#511] 2019-07-20 15:43:17 -04:00
gnosygnu
34dcfdde7d User.Logs: Delete log folders if logs are disabled [#510] 2019-07-20 09:40:26 -04:00
gnosygnu
989ccde83a Sqlite: Add option for read-only detection [#509] 2019-07-19 07:14:24 -04:00
gnosygnu
7f76d8128d Xomw.Preprocessor: Start integrating Preprocessor_Hash [#508] 2019-07-11 23:17:06 -04:00
gnosygnu
b65fda764f Luaj: Support PCRE character definitions for Luaj Regex [#502] 2019-07-01 14:09:31 -04:00
gnosygnu
5055f82d21 Scribunto: Print dbg arguments to console [#506] 2019-06-30 14:36:40 -04:00
gnosygnu
e3dce04680 Scribunto: Adjust index position correctly for ucs-2 strings [#506] 2019-06-30 14:28:46 -04:00
gnosygnu
0bfacb2ea5 Scribunto: Add frame_ttl to all Xot_invk_tkn [#503] 2019-06-29 22:29:15 -04:00
gnosygnu
9b51a7c660 Scribunto: Synchronize mw.uri.lua file with changes for uri.encode(s, 'WIKI') [#504] 2019-06-29 17:55:32 -04:00
gnosygnu
9da8b4dde8 Add gplx.xowa.mediawiki source to gplx.xowa [#508] 2019-06-29 10:18:43 -04:00
gnosygnu
5d886501e8 Language: Escape left-to-right / right-to-left marks in names.json ('\xE2\x80\x8E' to '\u200E') [#501] 2019-06-23 21:35:21 -04:00
gnosygnu
d4a28d3ffe Wikibase: Add qualifiers-order to GetEntityStatements [#374] 2019-06-22 21:53:07 -04:00
gnosygnu
2526b677fa Scribunto: Format date correctly for years with less than 4 digits (EX: +0065 -> 65 x> 2065) [#500] 2019-06-22 17:19:58 -04:00
gnosygnu
334bb0a6d0 Xtn.SyntaxHighlight: Add 'class=pretty-print lang-{lang_name}' if 'lang' is passed [#498] 2019-06-22 08:43:13 -04:00
gnosygnu
cbae5d55bb Xtn.SyntaxHighlight: Highlight lines if 'highlight' is passed but 'line' is not [#498] 2019-06-22 08:17:11 -04:00
gnosygnu
a01e7409eb Mass_parse: Change page_cache to LRU cache [#483] 2019-06-21 23:02:49 -04:00
gnosygnu
0cfb0b19ad Parser: Do not parse '&amp;#x;' as byte 0 [#494] 2019-06-16 15:38:56 -04:00
gnosygnu
d812b21dec Add comment for /LocalNames/ support [#388] 2019-06-11 07:10:29 -04:00
gnosygnu
70d845f438 Xtn.Cldr: Check CldrNames for IsKnownLanguageTag [#388] 2019-06-11 06:49:06 -04:00
gnosygnu
8ab9bc5444 Category: Replace UNION with sequential loading from each catlink db [#268] 2019-06-09 06:58:16 -04:00
gnosygnu
c459454da3 Allow hxtn command to be run multiple times during xomp_resume [#482] 2019-06-07 21:50:18 -04:00
gnosygnu
3b6efe4274 Scribunto: Fix 'Module:Exception:2 attempt to index ? (a nil value)' on some en.u pages [#475] 2019-06-02 21:44:47 -04:00
gnosygnu
c7f54287af Html: Change self-link pages from <b> to <a class='mw-selflink selflink'> [#478] 2019-06-02 21:11:51 -04:00
gnosygnu
3852d4762b HttpServer: Navigate to an error page for invalid titles like Earth] [#480] 2019-06-02 18:10:48 -04:00
gnosygnu
43cc4b15e8 Json: Parse surrogate-pairs correctly in unicode-escaped strings [#487] 2019-06-02 16:43:39 -04:00
gnosygnu
641a17621f Json: Skip forward by 5 characters, not 4 for unicode sequences [#486] 2019-06-02 14:31:04 -04:00
gnosygnu
a6ce48fffa Remove trailing whitespace [#482] 2019-06-02 13:05:13 -04:00
gnosygnu
491d1905c9 Scribunto: Ignore snak if novalue [#481] 2019-06-02 13:04:49 -04:00
gnosygnu
3d9491e2de Xtns.TemplateStyles: Cache TemplateStyles for HTML databases [#482] 2019-06-02 12:50:56 -04:00
gnosygnu
fbe158537e Fix build failing due to mis-named _fxt class [#476] 2019-06-02 11:32:57 -04:00
gnosygnu
17da6dc17f Fix build failing due to mis-named _fxt class [#476] 2019-06-02 10:07:40 -04:00
gnosygnu
b48b6def4e Xtn.Translate: Add #translation function with no implementation [#445] 2019-05-26 09:18:11 -04:00
gnosygnu
ee03d79536 Scribunto: Set frame title for pages when invoking Scribunto code [#476] 2019-05-25 17:19:47 -04:00
gnosygnu
cca043dff6 Do not wipe table upon initialization, else will lose data after xomp_resume [#456] 2019-05-24 19:31:11 -04:00
gnosygnu
05e8c11338 Scribunto: Apply namespace argument only if in main namespace [#473] 2019-05-22 22:36:15 -04:00
gnosygnu
b74ca77786 ParserFunctions: Increase precedence of E over ln and other operations [#397] 2019-05-19 11:08:08 -04:00
gnosygnu
42dbaff1d2 Scribunto: Encode key / val in GetUrl [#465] 2019-05-18 17:22:42 -04:00
gnosygnu
648cd4944a Remove unused invk branch; Update tests [#460] 2019-05-12 23:42:42 -04:00
gnosygnu
c07e6e25b5 Parser: Change encoding of html id to encode fewer characters [#462] 2019-05-12 23:31:48 -04:00
gnosygnu
ba35901865 Parser: Parse html in internal link captions [#460] 2019-05-12 20:09:51 -04:00
gnosygnu
4d9072830c HTTP Server: Parse links with trailing slash [#459] 2019-05-11 23:45:51 -04:00
gnosygnu
c94090cd09 Parser: Add test for djvu [#440] 2019-05-11 11:00:08 -04:00
gnosygnu
31c6576b50 Parser: Handle UTF-8 characters in attribute keys / values [#457] 2019-05-11 10:55:37 -04:00
gnosygnu
3a748eea32 Add comment to clarify that NULL content should return NULL [#450] 2019-05-08 06:40:52 -04:00
gnosygnu
cf94f252e9 Make: Add xomp_stats to track time per page (and other attributes) [#456] 2019-05-08 06:35:10 -04:00
gnosygnu
5db81504fb Upgrade Apache Commons Compress from 1.5 to 1.18 2019-04-28 18:36:24 -04:00
gnosygnu
4e920af183 Fix broken gmatch test; Fix broken maven build 2019-04-28 18:29:57 -04:00
gnosygnu
0f75a625db Update build files for new baselib [#413] 2019-04-28 18:06:57 -04:00
gnosygnu
f860edf064 Scribunto: Use Luaj for pattern-matching (instead of Java Regex) [#413] 2019-04-28 17:31:33 -04:00
gnosygnu
4a1b2e25c0 Parser: Comment|Terminate comment if new-line found [#437] 2019-04-27 09:00:30 -04:00
gnosygnu
f895259be6 Wikibase: Add entity-type for lexeme so that 2019-04 wikidata jsons don't fail 2019-04-26 22:27:36 -04:00
gnosygnu
42953aaa0f MassParse: Fix multi-threaded issues b/c wbase caches aren't locked 2019-04-26 22:26:54 -04:00
gnosygnu
74b63d5f08 Test: Add utility core.Page_url for easier logging; also do not run cfg during tests 2019-04-26 22:26:00 -04:00
gnosygnu
1cde843264 Project: Rename test classes for xowa_maven script 2019-04-26 22:24:44 -04:00
gnosygnu
5204d33af7 Dev: Fix more echo mistakes; rename boot.sh [#427] 2019-04-07 23:08:03 -04:00
gnosygnu
bc9e017906 Dev: Fix bootstrapping issues and bad echoes [#427] 2019-04-07 22:57:36 -04:00
gnosygnu
a5644dea07 Dev: Add Maven build files [#427] 2019-04-07 22:35:38 -04:00
gnosygnu
bbbc14eb34 Refactor: Move database-server tests into tst folder [#427] 2019-04-07 22:12:07 -04:00
gnosygnu
022d551760 Refactor: Add _tst suffix to test classes.gfs [#427] 2019-04-07 21:35:27 -04:00
gnosygnu
73cb63c493 Refactor: Remove stray f from beginning of xowa.gfs [#427] 2019-04-07 21:27:42 -04:00
gnosygnu
4909799a67 Refactor: Rename *_test.java files to *_mock.java files [#427] 2019-04-07 21:26:54 -04:00
gnosygnu
367a3a94b9 Refactor: Remove unused experimental files [#427] 2019-04-07 21:15:11 -04:00
gnosygnu
f22a0cca43 Refactor: Remove unnecessary junit import [#427] 2019-04-07 21:14:13 -04:00
gnosygnu
42b158c165 Css: Add 'mw-parser-output' to main div [#274] 2019-04-07 14:22:53 -04:00
gnosygnu
09d9f93d20 Parser.Wikibase: Retrieve by label if pid is not present; also, return pid, not label [#354] 2019-04-07 12:27:50 -04:00
gnosygnu
623c7a129e Fix broken Luaj jar [#419] 2019-04-03 00:19:01 -04:00
gnosygnu
cc8b9810a7 Parser.Tidy: Add vnu as additional tidy engine [#417] 2019-04-01 23:50:26 -04:00
gnosygnu
31c7604f03 Scribunto: Add initial support for LuaJ StringLib as replacement for Regex [#413] 2019-04-01 22:34:45 -04:00
gnosygnu
2fc03f6211 Parser.TemplateStyles: Check if title is null [#416] 2019-04-01 00:13:30 -04:00
gnosygnu
581aa5123c Parser.Wikibase: Return null instead of empty string if invalid title passed to getEntityId [#415] 2019-04-01 00:00:05 -04:00
gnosygnu
8c1f30039b Css: Change css jump-to class from 'mw-navigation' to 'mw-head' [#394] 2019-03-30 10:08:20 -04:00
gnosygnu
61cc5e89a7 Release: v4.6.1.1903 [#404] 2019-03-26 22:52:55 -04:00
gnosygnu
7bcbdabbfc Htxt: Extract img.src data [#404] 2019-03-26 22:26:26 -04:00
1217 changed files with 182146 additions and 60103 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.iml
**/.idea/**

View File

@ -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>

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,14 +14,15 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.lang.*;
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.ios.*;
import gplx.langs.htmls.entitys.*;
import gplx.core.primitives.Int_obj_ref;
import gplx.langs.htmls.entitys.Gfh_entity_;
public class Bry_ {
public static final String Cls_val_name = "byte[]";
public static final byte[] Empty = new byte[0];
public static final byte[][] Ary_empty = new byte[0][];
public static final Class<?> Cls_ref_type = byte[].class;
public static final byte[] Empty = new byte[0];
public static final byte[][] Ary_empty = new byte[0][];
public static final Class<?> Cls_ref_type = byte[].class;
public static byte[] cast(Object val) {return (byte[])val;}
public static byte[] New_by_byte(byte b) {return new byte[] {b};}
public static byte[] New_by_ints(int... ary) {
@ -154,7 +155,7 @@ public class Bry_ {
public static byte[] Resize(byte[] src, int src_bgn, int trg_len) {
byte[] trg = new byte[trg_len];
int src_len = src.length; if (src_len > trg_len) src_len = trg_len; // trg_len can be less than src_len
Copy_by_len(src, src_bgn, src_len, trg, 0);
Copy_to(src, src_bgn, src_len, trg, 0);
return trg;
}
public static byte[] Repeat_space(int len) {return Repeat(Byte_ascii.Space, len);}
@ -178,14 +179,14 @@ public class Bry_ {
public static byte[] Add(byte[] src, byte b) {
int src_len = src.length;
byte[] rv = new byte[src_len + 1];
Copy_by_pos(src, 0, src_len, rv, 0);
Copy_to(src, 0, src_len, rv, 0);
rv[src_len] = b;
return rv;
}
public static byte[] Add(byte b, byte[] src) {
int src_len = src.length;
byte[] rv = new byte[src_len + 1];
Copy_by_pos(src, 0, src_len, rv, 1);
Copy_to(src, 0, src_len, rv, 1);
rv[0] = b;
return rv;
}
@ -297,29 +298,30 @@ public class Bry_ {
for (int i = 0; i < repl_len; i++)
src[i + bgn] = repl[i];
}
public static void Copy_by_pos(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
public static void Copy_to(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
int trg_adj = trg_bgn - src_bgn;
for (int i = src_bgn; i < src_end; i++)
trg[i + trg_adj] = src[i];
}
public static void Copy_by_pos_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
public static void Copy_to_reversed(byte[] src, int src_bgn, int src_end, byte[] trg, int trg_bgn) {
// copies src to trg, but in reverse order; EX: trg="1" src="432." -> "1.234"
int len = src_end - src_bgn;
for (int i = 0; i < len; i++)
trg[trg_bgn + i] = src[src_end - i - 1];
}
private static void Copy_by_len(byte[] src, int src_bgn, int src_len, byte[] trg, int trg_bgn) {
for (int i = 0; i < src_len; i++)
trg[i + trg_bgn] = src[i + src_bgn];
}
public static byte[] Replace_one(byte[] src, byte[] find, byte[] repl) {
int src_len = src.length;
int findPos = Bry_find_.Find(src, find, 0, src_len, true); if (findPos == Bry_find_.Not_found) return src;
int findLen = find.length, replLen = repl.length;
int rvLen = src_len + replLen - findLen;
byte[] rv = new byte[rvLen];
Copy_by_len(src , 0 , findPos , rv, 0 );
Copy_by_len(repl, 0 , replLen , rv, findPos );
Copy_by_len(src , findPos + findLen , src_len - findPos - findLen , rv, findPos + replLen);
public static byte[] Replace_one(byte[] orig, byte[] find, byte[] repl) {
// find val
int orig_len = orig.length;
int find_pos = Bry_find_.Find(orig, find, 0, orig_len, true);
if (find_pos == Bry_find_.Not_found) return orig; // nothing found; exit
// do copy
int find_len = find.length, repl_len = repl.length;
int rv_len = orig_len + repl_len - find_len;
byte[] rv = new byte[rv_len];
Copy_to(orig, 0 , find_pos, rv, 0 ); // copy orig before repl
Copy_to(repl, 0 , repl_len, rv, find_pos ); // copy repl
Copy_to(orig, find_pos + find_len, orig_len, rv, find_pos + repl_len); // copy orig after repl
return rv;
}
public static void Replace_all_direct(byte[] src, byte find, byte repl) {Replace_all_direct(src, find, repl, 0, src.length);}
@ -437,9 +439,9 @@ public class Bry_ {
return rv;
}
public static final byte[] Trim_ary_ws = mask_(256, Byte_ascii.Tab, Byte_ascii.Nl, Byte_ascii.Cr, Byte_ascii.Space);
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws);}
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary) {
public static byte[] Trim(byte[] src) {return Trim(src, 0, src.length, true, true, Trim_ary_ws, true);}
public static byte[] Trim(byte[] src, int bgn, int end) {return Trim(src, bgn, end, true, true, Trim_ary_ws, true);}
public static byte[] Trim(byte[] src, int bgn, int end, boolean trim_bgn, boolean trim_end, byte[] trim_ary, boolean reuse_bry_if_noop) {
int txt_bgn = bgn, txt_end = end;
boolean all_ws = true;
if (trim_bgn) {
@ -465,7 +467,8 @@ public class Bry_ {
if (all_ws) return Bry_.Empty;
}
if ( bgn == 0 && end == src.length // Trim is called on entire bry, not subset
if ( reuse_bry_if_noop
&& bgn == 0 && end == src.length // Trim is called on entire bry, not subset
&& bgn == txt_bgn && end == txt_end // Trim hasn't trimmed anything
) {
return src;
@ -473,6 +476,19 @@ public class Bry_ {
else
return Bry_.Mid(src, txt_bgn, txt_end);
}
public static byte[] Trim_bgn(byte[] v, byte trim, int bgn) {
boolean trimmed = false;
int len = v.length;
int pos = bgn;
for (; pos < len; pos++) {
if (v[pos] == trim) {
trimmed = true;
}
else
break;
}
return trimmed ? Bry_.Mid(v, pos, len) : v;
}
public static byte[] Trim_end(byte[] v, byte trim, int end) {
boolean trimmed = false;
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len
@ -977,6 +993,43 @@ public class Bry_ {
}
return bfr.To_bry_and_clear();
}
public static byte[] Replace_many(byte[] src, byte[] find, byte[] repl) {
Bry_bfr bfr = null;
int src_len = src.length;
int find_len = find.length;
int pos = 0;
while (true) {
// find find_bgn
int find_bgn = Bry_find_.Find_fwd(src, find, pos, src_len);
// exit if nothing found
if (find_bgn == Bry_find_.Not_found)
break;
// lazy-instantiation
if (bfr == null)
bfr = Bry_bfr_.New();
// add everything up to find_bgn
bfr.Add_mid(src, pos, find_bgn);
// add repl
bfr.Add(repl);
// move pos forward
pos = find_bgn + find_len;
}
// nothing found; return src
if (bfr == null)
return src;
else {
// add rest
bfr.Add_mid(src, pos, src_len);
return bfr.To_bry_and_clear();
}
}
public static int Trim_end_pos(byte[] src, int end) {
for (int i = end - 1; i > -1; i--) {
switch (src[i]) {

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,51 +14,55 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import org.junit.*; import gplx.core.primitives.*; import gplx.core.brys.*; import gplx.core.tests.*;
import gplx.core.primitives.Int_obj_ref;
import gplx.core.tests.Gftest;
import org.junit.Test;
public class Bry__tst {
private final Bry__fxt fxt = new Bry__fxt();
@Test public void new_ascii_() {
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() {
@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() {
@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() {
@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() {
@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() {
@Test public void Add_w_dlm_bry() {
fxt.Test_add_w_dlm("<>", String_.Ary("a","b","c"), "a<>b<>c");
}
@Test public void MidByPos() {
@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() {
@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() {
@Test public void XtoStrBytesByInt() {
tst_XtoStrBytesByInt(0, 0);
tst_XtoStrBytesByInt(9, 9);
tst_XtoStrBytesByInt(10, 1, 0);
@ -74,7 +78,7 @@ public class Bry__tst {
}
Tfds.Eq_ary(expd, Bry_.To_a7_bry(val, Int_.DigitCount(val)));
}
@Test public void Has_at_end() {
@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
@ -85,13 +89,13 @@ public class Bry__tst {
}
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() {
@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() {
@Test public void Match() {
tst_Match("abc", 0, "abc", true);
tst_Match("abc", 2, "c", true);
tst_Match("abc", 0, "cde", false);
@ -102,7 +106,7 @@ public class Bry__tst {
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() {
@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");
@ -119,13 +123,13 @@ public class Bry__tst {
tst_ReadCsvStr_err("'a|");
tst_ReadCsvStr_err("'a'");
}
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
@Test public void XtoIntBy4Bytes() { // test len=1, 2, 3, 4
tst_XtoIntBy4Bytes(32, (byte)32); // space
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // &exist;
tst_XtoIntBy4Bytes(6382179, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c);
tst_XtoIntBy4Bytes(1633837924, Byte_ascii.Ltr_a, Byte_ascii.Ltr_b, Byte_ascii.Ltr_c, Byte_ascii.Ltr_d);
}
@Test public void XtoInt() {
@Test public void XtoInt() {
tst_XtoInt("1", 1);
tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
@ -157,18 +161,18 @@ public class Bry__tst {
catch (Exception e) {Err_.Noop(e); return;}
Tfds.Fail_expdError();
}
@Test public void ReadCsvDte() {
@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() {
@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() {
@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() {
@Test public void Xto_int_lax() {
tst_Xto_int_lax("12a", 12);
tst_Xto_int_lax("1", 1);
tst_Xto_int_lax("123", 123);
@ -176,14 +180,14 @@ public class Bry__tst {
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() {
@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() {
@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);
@ -191,7 +195,7 @@ public class Bry__tst {
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() {
@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));
@ -203,12 +207,12 @@ public class Bry__tst {
return rv;
}
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));}
@Test public void Replace_between() {
@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() {
@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
@ -221,7 +225,7 @@ public class Bry__tst {
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() {
@Test public void Split_bry() {
Split_bry_tst("a|b|c|" , "|" , String_.Ary("a", "b", "c"));
Split_bry_tst("a|" , "|" , String_.Ary("a"));
}
@ -229,7 +233,7 @@ public class Bry__tst {
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() {
@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
@ -245,7 +249,7 @@ public class Bry__tst {
rv[i] = String_.new_u8(lines[i]);
return rv;
}
@Test public void Match_bwd_any() {
@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);
@ -256,38 +260,48 @@ public class Bry__tst {
void Tst_match_bwd_any(String src, int src_end, int src_bgn, String find, boolean expd) {
Tfds.Eq(expd, Bry_.Match_bwd_any(Bry_.new_a7(src), src_end, src_bgn, Bry_.new_a7(find)));
}
@Test public void Trim_end() {
@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() {
@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() {
@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() {
@Test public void Repeat_bry() {
fxt.Test__repeat_bry("abc" , 3, "abcabcabc");
}
@Test public void Xcase__build__all() {
@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();
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)));}

View File

@ -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;
}

View File

@ -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);

View File

@ -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 | {|}~
*/

View File

@ -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);}

View File

@ -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;
}

View File

@ -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";

View File

@ -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());
}
}

View File

@ -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();}

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2021 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,10 +14,15 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.text.DecimalFormat;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class Decimal_adp_ {
public static final String Cls_val_name = "decimal";
public static final Class<?> Cls_ref_type = Decimal_adp.class;
@ -53,17 +58,34 @@ public class Decimal_adp_ {
return Decimal_adp_.float_(Float_.Div(dividend, divisor) * 100).To_str(fmt) + "%";
}
public static Decimal_adp divide_safe_(long lhs, long rhs) {return rhs == 0 ? Zero : divide_(lhs, rhs);}
public static Decimal_adp divide_(long lhs, long rhs) { return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context)); } public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));} public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));} public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp divide_(long lhs, long rhs) {
return new Decimal_adp(new BigDecimal(lhs).divide(new BigDecimal(rhs), Gplx_rounding_context));
}
public static Decimal_adp int_(int v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp long_(long v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp float_(float v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp double_(double v) {return new Decimal_adp(new BigDecimal(v));}
public static Decimal_adp double_thru_str_(double v) {return new Decimal_adp(BigDecimal.valueOf(v));}
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);} public static Decimal_adp parse(String raw) {
public static Decimal_adp db_(Object v) {return new Decimal_adp((BigDecimal)v);}
public static Decimal_adp parse(String raw) {
try {
DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(Locale.US); // always parse as US format; EX:".9" should not be ",9" in german; DATE:2016-01-31
nf.setParseBigDecimal(true);
// 2020-08-27|ISSUE#:565|Parse 'e' as 'E'; PAGE:en.w:Huntington_Plaza
if (raw.contains("e")) {
raw = raw.replace("e", "E");
}
// 2021-02-13|ISSUE#:838|Parse '.' as '0.'; PAGE:en.w:2019_FIVB_Volleyball_Women%27s_Challenger_Cup#Pool_A
if (raw.startsWith(".")) {
raw = "0" + raw;
}
BigDecimal bd = (BigDecimal)nf.parse(raw);
return new Decimal_adp(bd);
} catch (ParseException e) {
throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw);
}
} public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN); public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31 }
}
public static Decimal_adp pow_10_(int v) {return new Decimal_adp(new BigDecimal(1).scaleByPowerOfTen(v));}
public static final MathContext RoundDownContext = new MathContext(0, RoundingMode.DOWN);
public static final MathContext Gplx_rounding_context = new MathContext(14, RoundingMode.HALF_UP); // changed from 28 to 14; DATE:2015-07-31
}

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2021 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,52 +14,59 @@ 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_() {
@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_() {
@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_() {
@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() {
@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 Truncate_decimal() {
@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() {
@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() {
@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() {
@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() {
@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");

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,6 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Double_ {
public static final String Cls_val_name = "double";
public static final Class<?> Cls_ref_type = Double.class;
@ -42,7 +43,9 @@ public class Double_ {
int v_as_int = (int)v;
return v == v_as_int
? Int_.To_str(v_as_int) // convert to int, and call print String to eliminate any trailing decimal places
: Float_.To_str((float)v); // calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d; DATE:2014-07-29
// DATE:2014-07-29; calling ((float)v).toString is better at removing trailing 0s than String.format("%g", v). note that .net .toString() handles it better; EX:2449.600000000000d
// DATE:2020-08-12; calling ToStrByPrintF b/c better at removing trailing 0s; ISSUE#:697;
: gplx.objects.primitives.Double_.ToStrByPrintF(v);
}
public static int Compare(double lhs, double rhs) {
if (lhs == rhs) return CompareAble_.Same;

View File

@ -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);}

View File

@ -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) {

View File

@ -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() {

View File

@ -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;}
}

View 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);

View File

@ -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);

View File

@ -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());

View File

@ -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);

View File

@ -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;}

View File

@ -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;
}
}

View File

@ -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)));}

View File

@ -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;

View File

@ -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) {

View File

@ -24,7 +24,9 @@ public class Io_url__tst {
class Io_url__fxt {
public void Clear() {Io_mgr.Instance.InitEngine_mem();}
public void Test__New__http_or_null(boolean os_is_wnt, String raw, String expd) {
int curTid = Op_sys.Cur().Tid();
Op_sys.Cur_(os_is_wnt ? Op_sys.Tid_wnt : Op_sys.Tid_lnx);
Gftest.Eq__obj_or_null(expd, Io_url_.New__http_or_null(raw));
Op_sys.Cur_(curTid);
}
}

View File

@ -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;

View File

@ -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);}

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -14,6 +14,7 @@ GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx;
public class Type_ {//RF:2017-10-08
public static Class<?> Type_by_obj(Object o) {return o.getClass();}
public static Class<?> Type_by_primitive(Object o) {
@ -45,6 +46,11 @@ public class Type_ {//RF:2017-10-08
return type.getName();
}
public static String SimpleName_by_obj(Object obj) {return obj == null ? String_.Null_mark : SimpleName(Type_by_obj(obj));}
public static String SimpleName(Class<?> type) {
return type.getSimpleName();
}
public static boolean Is_array(Class<?> t) {
return t.isArray();
}

View File

@ -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);

View File

@ -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);}
}

View File

@ -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;
}
}

View 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();
}
}

View 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();
}

View 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);
}
}

View File

@ -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;

View 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;
}
}

View File

@ -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
;
}

View File

@ -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() {}
}

View 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() {}
}

View File

@ -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);

View File

@ -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_();

View File

@ -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;

View File

@ -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;

View 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);
}
}

View 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);
}
}
}

View 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;
}
//#}

View File

@ -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);
}
}

View 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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View 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);}
}

View File

@ -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);}
}

View 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);
}
}
}

View 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
}

View 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;
}

View 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));
}
}

View File

@ -13,8 +13,7 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.mediawiki.includes.exception; import gplx.*; import gplx.xowa.*; import gplx.xowa.mediawiki.*; import gplx.xowa.mediawiki.includes.*;
public class XomwMWException extends Err {
public XomwMWException(String msg) {super(true, "", "", msg);
}
package gplx.core.security.algos; import gplx.*; import gplx.core.*; import gplx.core.security.*;
public interface Hash_algo_factory {
Hash_algo New_hash_algo(String key);
}

View File

@ -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;
}
}

View 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;
}
}

View 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);
}

View File

@ -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];

View File

@ -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());

View File

@ -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() {

View File

@ -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;
}

View 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.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);
}
}

View 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.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() {}
}

View 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);
}
}

View File

@ -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)));
}
}

View File

@ -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");}

View File

@ -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");}

View 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;
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() {}
}

View File

@ -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;}
}

View 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 {}

View 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);
}
}
}
}
}

View 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);}
}

View 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();
}
}

View 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;
}
}

View 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);
}

View File

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -17,6 +17,9 @@ package gplx.core.tests; import gplx.*; import gplx.core.*;
import gplx.core.brys.*;
public class Gftest {
private static final Bry_bfr bfr = Bry_bfr_.New();
public static void Fail(String msg_fmt, Object... msg_args) {
throw Err_.new_wo_type(String_.Format(msg_fmt, msg_args));
}
public static void Eq__ary(Object[] expd, Object[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__obj, expd, actl, msg_fmt, msg_args);}
public static void Eq__ary(boolean[] expd, boolean[] actl, String msg_fmt, Object... msg_args) {Eq__array(Type_ids_.Id__bool, expd, actl, msg_fmt, msg_args);}
public static void Eq__ary(int[] expd, int[] actl) {Eq__array(Type_ids_.Id__int, expd, actl, "");}
@ -61,6 +64,7 @@ public class Gftest {
if (actl == null) actl = Str__null;
Eq__str(Object_.Xto_str_or(expd, Str__null), Object_.Xto_str_or(actl, null), Str__null);
}
public static void Eq__bry(byte[] expd, String actl) {Eq__str(String_.new_u8(expd), actl, "no_msg");}
public static void Eq__str(String expd, byte[] actl, String msg_fmt, Object... msg_args) {Eq__str(expd, String_.new_u8(actl), msg_fmt, msg_args);}
public static void Eq__str(String expd, byte[] actl) {Eq__str(expd, String_.new_u8(actl), null);}
public static void Eq__str(String expd, String actl) {Eq__str(expd, actl, null);}
@ -108,6 +112,7 @@ public class Gftest {
bfr.Add(Bry__line_end);
throw Err_.new_wo_type(bfr.To_str_and_clear());
}
public static void Eq__bool_n(boolean actl) {Eq__bool(Bool_.N, actl, null);}
public static void Eq__bool_y(boolean actl) {Eq__bool(Bool_.Y, actl, null);}
public static void Eq__bool_y(boolean actl, String msg_fmt, Object... msg_args) {Eq__bool(Bool_.Y, actl, msg_fmt, msg_args);}
public static void Eq__bool(boolean expd, boolean actl) {Eq__bool(expd, actl, null);}

View File

@ -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){

View File

@ -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,11 +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.core.threads; import gplx.*; import gplx.core.*;
import java.lang.*;
package gplx.core.threads;
import gplx.Cancelable;
import gplx.Cancelable_;
import gplx.Err_;
import gplx.GfoMsg;
import gplx.GfoMsg_;
import gplx.Gfo_invk;
import gplx.Gfo_invk_;
import gplx.Gfo_log_;
public class Thread_adp implements Runnable {
private final String thread_name; private final Cancelable cxl; private final boolean cxlable;
private final Gfo_invk invk_itm; private final String invk_cmd; private final GfoMsg invk_msg;
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);
}

View File

@ -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,16 +13,24 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.core.threads; import gplx.*; import gplx.core.*;
package gplx.core.threads;
import gplx.Cancelable;
import gplx.Cancelable_;
import gplx.Err_;
import gplx.GfoMsg;
import gplx.GfoMsg_;
import gplx.Gfo_invk;
public class Thread_adp_ {
public static void Sleep(int milliseconds) {
try {
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));}

View 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);
}
}
}

View File

@ -0,0 +1,24 @@
package gplx.core.tooling.dataCollectors;
import java.util.LinkedHashMap;
import java.util.List;
public class GfoDataCollectorGrp {
private final String key;
private final LinkedHashMap<String, Object> hash = new LinkedHashMap<>();
public GfoDataCollectorGrp(String key) {
this.key = key;
}
public String Key() {return key;}
public GfoDataCollectorGrp Add(String dataKey, String dataVal) {
hash.put(dataKey, dataVal);
return this;
}
public GfoDataCollectorGrp Add(String dataKey, List<?> dataVal) {
hash.put(dataKey, dataVal);
return this;
}
public Object Get(String dataKey) {
return hash.get(dataKey);
}
}

View File

@ -0,0 +1,13 @@
package gplx.core.tooling.dataCollectors;
import java.util.LinkedHashMap;
public class GfoDataCollectorMgr {
private final LinkedHashMap<String, GfoDataCollectorGrp> hash = new LinkedHashMap<>();
public GfoDataCollectorGrp GetGrp(String grpKey) {return hash.get(grpKey);}
public GfoDataCollectorGrp AddGrp(String grpKey) {
GfoDataCollectorGrp grp = new GfoDataCollectorGrp(grpKey);
hash.put(grpKey, grp);
return grp;
}
}

View File

@ -0,0 +1,13 @@
package gplx.langs.java.util;
import java.util.ArrayList;
import java.util.List;
public class List_ {
public static List<Object> NewByAry(Object[] ary) {
List<Object> rv = new ArrayList<>();
for (Object o : ary)
rv.add(o);
return rv;
}
}

View File

@ -17,7 +17,10 @@ package gplx.langs.regxs; import gplx.*; import gplx.langs.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regx_adp {
@gplx.Internal protected Regx_adp(String regx) {Pattern_(regx);}
public Regx_adp(String regx, int flags) {
this.flags = flags;
Pattern_(regx);
}
public String Pattern() {return pattern;} public Regx_adp Pattern_(String val) {pattern = val; Under_sync(); return this;} private String pattern;
public boolean Pattern_is_invalid() {return pattern_is_invalid;} private boolean pattern_is_invalid = false;
public Exception Pattern_is_invalid_exception() {return pattern_is_invalid_exception;} private Exception pattern_is_invalid_exception = null;
@ -38,14 +41,15 @@ public class Regx_adp {
}
return (Regx_match[])rv.To_ary(Regx_match.class);
}
private Pattern under;
private int flags = FLAG__DOTALL | FLAG__UNICODE_CHARACTER_CLASS;// JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
private Pattern under;
public Pattern Under() {return under;}
private void Under_sync() {
try {under = Pattern.compile(pattern, Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);} // JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
try {under = Pattern.compile(pattern, flags);}
catch (Exception e) { // NOTE: if invalid, then default to empty pattern (which should return nothing); EX:d:〆る generates [^]; DATE:2013-10-20
pattern_is_invalid = true;
pattern_is_invalid_exception = e;
under = Pattern.compile("", Pattern.DOTALL | Pattern.UNICODE_CHARACTER_CLASS);
under = Pattern.compile("", flags);
}
}
public Regx_match Match(String input, int bgn) {
@ -56,11 +60,29 @@ public class Regx_adp {
Regx_group[] ary = Regx_group.Ary_empty;
int groups_len = match.groupCount();
if (success && groups_len > 0) {
// NOTE: by convention, there are n groups, but groups.count is n - 1 and groups[0] is entire match (not 1st group); see TEST: DATE:2019-12-28
groups_len++;
ary = new Regx_group[groups_len];
for (int i = 0; i < groups_len; i++)
ary[i] = new Regx_group(true, match.start(i + 1), match.end(i + 1), match.group(i + 1));
for (int i = 0; i < groups_len; i++) {
int match_start = match.start(i);
ary[i] = new Regx_group(match_start != -1, match_start, match.end(i), match.group(i));
}
}
return new Regx_match(success, match_bgn, match_end, ary);
}
public String ReplaceAll(String input, String replace) {return under.matcher(input).replaceAll(replace);}
// https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
public static final int
FLAG__NONE = 0
, FLAG__UNIX_LINES = Pattern.UNIX_LINES
, FLAG__CASE_INSENSITIVE = Pattern.CASE_INSENSITIVE
, FLAG__COMMENTS = Pattern.COMMENTS
, FLAG__MULTILINE = Pattern.MULTILINE
, FLAG__LITERAL = Pattern.LITERAL
, FLAG__DOTALL = Pattern.DOTALL
, FLAG__UNICODE_CASE = Pattern.UNICODE_CASE
, FLAG__CANON_EQ = Pattern.CANON_EQ
, FLAG__UNICODE_CHARACTER_CLASS = Pattern.UNICODE_CHARACTER_CLASS
;
public static final int FLAG__DEFAULT = FLAG__DOTALL | FLAG__UNICODE_CHARACTER_CLASS;// JRE.7:UNICODE_CHARACTER_CLASS; added during %w fix for en.w:A#; DATE:2015-06-10
}

View File

@ -15,18 +15,17 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.langs.regxs; import gplx.*; import gplx.langs.*;
public class Regx_adp_ {
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern);}
public static List_adp Find_all(String input, String find) {
Regx_adp regx = Regx_adp_.new_(find);
int idx = 0;
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern, Regx_adp.FLAG__DEFAULT);}
public static List_adp Find_all(String src, String pat) {
int src_len = String_.Len(src);
Regx_adp regx = Regx_adp_.new_(pat);
int pos = 0;
List_adp rv = List_adp_.New();
while (true) {
Regx_match match = regx.Match(input, idx);
while (pos < src_len) {
Regx_match match = regx.Match(src, pos);
if (match.Rslt_none()) break;
rv.Add(match);
int findBgn = match.Find_bgn();
idx = findBgn + match.Find_len();
if (idx > String_.Len(input)) break;
pos = match.Find_bgn() + match.Find_len();
}
return rv;
}
@ -35,7 +34,7 @@ public class Regx_adp_ {
return regx.ReplaceAll(raw, replace);
}
public static boolean Match(String input, String pattern) {
Regx_adp rv = new Regx_adp(pattern);
Regx_adp rv = new Regx_adp(pattern, Regx_adp.FLAG__DEFAULT);
return rv.Match(input, 0).Rslt();
}
}

View File

@ -49,7 +49,9 @@ public class Regx_adp__tst implements TfdsEqListItmStr {
tst_Matches("b", "a b c b a b b", matches_(2, 6, 10, 12)); // BUGFIX: multiple entries did not work b/c of += instead of +
}
@Test public void Groups() {
tst_Groups("abc def ghi dz", "(d\\p{L}+)", "def", "dz");
tst_Groups("abc def ghi dz", "(d\\p{L}+)", "def", "def", "dz", "dz");
tst_Groups("abc def", "(de)(g?)", "de", "de", ""); // NOTE: (g?) doesn't capture anything, but still add a group for it; DATE:2019-12-28
tst_Groups("-123.456", "^-?(([0-9]+)(?:\\.([0-9]+))?)", "-123.456", "123.456", "123", "456"); // NOTE: -123.456 captured even though it's not part of a group; DATE:2019-12-28
}
Regx_match[] matches_(int... bgnAry) {
int aryLen = Array_.Len(bgnAry);

View File

@ -26,6 +26,7 @@ public class Regx_match {
public int Find_bgn() {return find_bgn;} private final int find_bgn;
public int Find_end() {return find_end;} private final int find_end;
public int Find_len() {return find_end - find_bgn;}
public String Find_str(String s) {return String_.Mid(s, find_bgn, find_end);}
public Regx_group[] Groups() {return groups;} private final Regx_group[] groups;
public static final Regx_match[] Ary_empty = new Regx_match[0];

View File

@ -22,6 +22,11 @@ public class XmlAtrList {
Node xatr = list.getNamedItem(key);
return (xatr == null) ? or : xatr.getNodeValue();
}
public XmlAtr Get_by(String key) {
Node xatr = list.getNamedItem(key);
if (xatr == null) throw Err_.new_missing_key(key);
return new XmlAtr(xatr);
}
public XmlAtr Fetch(String key) {
Node xatr = list.getNamedItem(key); if (xatr == null) throw Err_.new_missing_key(key);
return new XmlAtr(xatr);

View File

@ -29,15 +29,45 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class XmlDoc_ {
public static XmlDoc parse(String raw) {return new XmlDoc(doc_(raw));}
public static XmlNdeList Select_tags(XmlNde cur, String tag) {
XmlNdeList_cls_list rv = new XmlNdeList_cls_list(4); // NOTE: pass in an initial amount; do not pass 0
Select_tags(rv, cur, tag);
return rv;
}
private static void Select_tags(XmlNdeList_cls_list rv, XmlNde cur, String tag) {
if (String_.Eq(cur.Name(), tag)) {
rv.Add(cur);
}
XmlNdeList sub_ndes = cur.SubNdes();
int sub_ndes_len = sub_ndes.Count();
for (int i = 0; i < sub_ndes_len; i++) {
XmlNde sub_nde = sub_ndes.Get_at(i);
Select_tags(rv, sub_nde, tag);
}
}
public static XmlDoc parse(String raw) {return new XmlDoc(doc_(raw));}
static Document doc_(String raw) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder bldr = null;
try {bldr = factory.newDocumentBuilder();}
catch (ParserConfigurationException e) {throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");}
try {
// NOTE: disable DTD validation else errors for "ldmlSupplemental.dtd" in plurals.xml; DATE:2020-01-01
// REF:https://stackoverflow.com/questions/24744175/non-validating-documentbuilder-trying-to-read-dtd-file
// REF:https://stackoverflow.com/questions/6204827/xml-parsing-too-slow
factory.setNamespaceAware(false);
factory.setValidating(false);
factory.setFeature("http://xml.org/sax/features/namespaces", false);
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
bldr = factory.newDocumentBuilder();
}
catch (ParserConfigurationException e) {
throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");
}
StringReader reader = new StringReader(raw);
InputSource source = new InputSource(reader);
Document doc = null;
@ -47,5 +77,4 @@ public class XmlDoc_ {
return doc;
}
public static final String Err_XmlException = "gplx.xmls.XmlException";
}
//#}
}

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