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

Compare commits

..

170 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
607 changed files with 158894 additions and 51216 deletions

2
.gitignore vendored Normal file
View File

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

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; package gplx;
import java.lang.*;
import gplx.core.brys.*; import gplx.core.primitives.*; import gplx.core.ios.*; import gplx.core.primitives.Int_obj_ref;
import gplx.langs.htmls.entitys.*; import gplx.langs.htmls.entitys.Gfh_entity_;
public class Bry_ { public class Bry_ {
public static final String Cls_val_name = "byte[]"; public static final String Cls_val_name = "byte[]";
public static final byte[] Empty = new byte[0]; public static final byte[] Empty = new byte[0];
public static final byte[][] Ary_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 Class<?> Cls_ref_type = byte[].class;
public static byte[] cast(Object val) {return (byte[])val;} 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_byte(byte b) {return new byte[] {b};}
public static byte[] New_by_ints(int... ary) { public static byte[] New_by_ints(int... ary) {
@ -475,6 +476,19 @@ public class Bry_ {
else else
return Bry_.Mid(src, txt_bgn, txt_end); 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) { public static byte[] Trim_end(byte[] v, byte trim, int end) {
boolean trimmed = false; boolean trimmed = false;
int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len int pos = end - 1; // NOTE: -1 b/c callers will always be passing pos + 1; EX: src, src_len

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; 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 { public class Bry__tst {
private final Bry__fxt fxt = new Bry__fxt(); private final Bry__fxt fxt = new Bry__fxt();
@Test public void new_ascii_() { @Test public void new_ascii_() {
fxt.Test_new_a7("a" , Bry_.New_by_ints(97)); // one 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("abc" , Bry_.New_by_ints(97, 98, 99)); // many
fxt.Test_new_a7("" , Bry_.Empty); // none fxt.Test_new_a7("" , Bry_.Empty); // none
fxt.Test_new_a7("¢€𤭢" , Bry_.New_by_ints(63, 63, 63, 63)); // non-ascii -> ? 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("a" , Bry_.New_by_ints(97)); // one
fxt.Test_new_u8("abc" , Bry_.New_by_ints(97, 98, 99)); // many 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(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(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 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("a" , Byte_ascii.Pipe , "a|"); // basic
fxt.Test_add("" , Byte_ascii.Pipe , "|"); // empty String 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 , "a" , "|a"); // basic
fxt.Test_add(Byte_ascii.Pipe , "" , "|"); // empty String 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", "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") , "a"); // one item
fxt.Test_add_w_dlm(Byte_ascii.Pipe, String_.Ary("a", null, "c") , "a||c"); // null 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"); 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, 1, "a");
tst_MidByPos("abcba", 0, 2, "ab"); tst_MidByPos("abcba", 0, 2, "ab");
tst_MidByPos("abcba", 1, 4, "bcb"); 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)));} } 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("a" , "b" , "c" , "a");
tst_ReplaceOne("b" , "b" , "c" , "c"); tst_ReplaceOne("b" , "b" , "c" , "c");
tst_ReplaceOne("bb" , "b" , "c" , "cb"); tst_ReplaceOne("bb" , "b" , "c" , "cb");
tst_ReplaceOne("abcd" , "bc" , "" , "ad"); tst_ReplaceOne("abcd" , "bc" , "" , "ad");
tst_ReplaceOne("abcd" , "b" , "ee" , "aeecd"); 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))));} } 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(0, 0);
tst_XtoStrBytesByInt(9, 9); tst_XtoStrBytesByInt(9, 9);
tst_XtoStrBytesByInt(10, 1, 0); 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))); 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", "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, true); // y_many
tst_HasAtEnd("a|bcd|e", "|bcd" , 2, 5, false); // n_long 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, 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)));} 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_basic" , "a|bcd|e", "b" , 2, 5, true);
tst_HasAtBgn("y_many" , "a|bcd|e", "bcd" , 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_long" , "a|bcd|e", "bcde" , 2, 5, false);
tst_HasAtBgn("n_pos" , "a|bcd|e", "|bc" , 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);} } 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", 0, "abc", true);
tst_Match("abc", 2, "c", true); tst_Match("abc", 2, "c", true);
tst_Match("abc", 0, "cde", false); tst_Match("abc", 0, "cde", false);
@ -102,7 +106,7 @@ public class Bry__tst {
tst_Match("" , 0, "", true); tst_Match("" , 0, "", true);
tst_Match("ab", 0, "a", false); // FIX: "ab" should not match "a" b/c .length is different 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)));} } 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|" , "a");
tst_ReadCsvStr("|a|", 1 , "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"); 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|");
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(32, (byte)32); // space
tst_XtoIntBy4Bytes(8707, (byte)34, (byte)3); // &exist; 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(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); 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("1", 1);
tst_XtoInt("123", 123); tst_XtoInt("123", 123);
tst_XtoInt("a", Int_.Min_value, Int_.Min_value); tst_XtoInt("a", Int_.Min_value, Int_.Min_value);
@ -157,18 +161,18 @@ public class Bry__tst {
catch (Exception e) {Err_.Noop(e); return;} catch (Exception e) {Err_.Noop(e); return;}
Tfds.Fail_expdError(); Tfds.Fail_expdError();
} }
@Test public void ReadCsvDte() { @Test public void ReadCsvDte() {
tst_ReadCsvDte("20110801 221435.987"); 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)'|'));} } 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"); 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)'|'));} } 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 b c", 1, 4, "b");
Trim_tst("a c", 1, 3, ""); Trim_tst("a c", 1, 3, "");
Trim_tst(" ", 0, 2, ""); 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)));} } 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("12a", 12);
tst_Xto_int_lax("1", 1); tst_Xto_int_lax("1", 1);
tst_Xto_int_lax("123", 123); tst_Xto_int_lax("123", 123);
@ -176,14 +180,14 @@ public class Bry__tst {
tst_Xto_int_lax("-1", -1); 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));} 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(" 123" , 123);
tst_Xto_int_trim(" 123 " , 123); tst_Xto_int_trim(" 123 " , 123);
tst_Xto_int_trim(" 1 3 " , -1); 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));} 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", 0, 1, CompareAble_.Same);
tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less); tst_Compare("abcde", 0, 1, "abcde", 1, 2, CompareAble_.Less);
tst_Compare("abcde", 1, 2, "abcde", 0, 1, CompareAble_.More); 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", 0, 2, "abcde", 0, 1, CompareAble_.More);
tst_Compare("abcde", 2, 3, "abçde", 2, 3, CompareAble_.Less); 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));} } 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), ary_(1));
tst_IncrementLast(ary_(0, 255), ary_(1, 0)); tst_IncrementLast(ary_(0, 255), ary_(1, 0));
tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102)); tst_IncrementLast(ary_(104, 111, 112, 101), ary_(104, 111, 112, 102));
@ -203,12 +207,12 @@ public class Bry__tst {
return rv; return rv;
} }
void tst_IncrementLast(byte[] ary, byte[] expd) {Tfds.Eq_ary(expd, Bry_.Increment_last(Bry_.Copy(ary)));} 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" , "[", "]", "0", "a0b");
tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c"); tst_Replace_between("a[0]b[1]c" , "[", "]", "0", "a0b0c");
tst_Replace_between("a[0b" , "[", "]", "0", "a[0b"); 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))));} } 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(); Bry_bfr tmp_bfr = Bry_bfr_.New();
tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1 tst_Replace(tmp_bfr, "a0b" , "0", "00", "a00b"); // 1 -> 1
tst_Replace(tmp_bfr, "a0b0c" , "0", "00", "a00b00c"); // 1 -> 2 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) { 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)))); 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|b|c|" , "|" , String_.Ary("a", "b", "c"));
Split_bry_tst("a|" , "|" , String_.Ary("a")); 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))); String[] actl = String_.Ary(Bry_split_.Split(Bry_.new_a7(src), Bry_.new_a7(dlm)));
Tfds.Eq_ary_str(expd, actl); 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" , "a", "b"); // basic
Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines Tst_split_lines("a\nb\n" , "a", "b"); // do not create empty trailing lines
Tst_split_lines("a\r\nb" , "a", "b"); // crlf Tst_split_lines("a\r\nb" , "a", "b"); // crlf
@ -245,7 +249,7 @@ public class Bry__tst {
rv[i] = String_.new_u8(lines[i]); rv[i] = String_.new_u8(lines[i]);
return rv; 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, "c", true);
Tst_match_bwd_any("abc", 2, 0, "b", false); Tst_match_bwd_any("abc", 2, 0, "b", false);
Tst_match_bwd_any("abc", 2, 0, "bc", true); Tst_match_bwd_any("abc", 2, 0, "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) { 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))); 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.one
fxt.Test_trim_end("a " , Byte_ascii.Space, "a"); // trim.many 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("a" , Byte_ascii.Space, "a"); // trim.none
fxt.Test_trim_end("" , Byte_ascii.Space, ""); // empty 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("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(" 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("\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 0 bytes
fxt.Test_Mid_w_trim(" ", ""); // handle all ws 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"), "a");
fxt.Test__new_u8_nl_apos(String_.Ary("a", "b"), "a\nb"); 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"); 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"); 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");
fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc"); fxt.Test__xcase__build__all(Bool_.N, "aBc", "abc");
} }
} }
class Bry__fxt { 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) { public void Test_trim_end(String raw, byte trim, String expd) {
byte[] raw_bry = Bry_.new_a7(raw); byte[] raw_bry = Bry_.new_a7(raw);
Tfds.Eq(expd, String_.new_u8(Bry_.Trim_end(raw_bry, trim, raw_bry.length))); 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_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_new_a7(String raw, byte[] expd) {Tfds.Eq_ary(expd, Bry_.new_a7(raw));}
public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));} public void Test_add(String s, byte b, String expd) {Tfds.Eq_str(expd, String_.new_u8(Bry_.Add(Bry_.new_u8(s), b)));}

View File

@ -56,13 +56,14 @@ public class Char_ {
if (itm == match) return true; if (itm == match) return true;
return false; return false;
} }
public static int To_int_or(char c, int or) { public static int To_digit_or(char c, int or) {
switch (c) { switch (c) {
case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; 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; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9;
default: return or; 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(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(int b) {return To_str((char)b);}
public static String To_str(char c) {return String.valueOf(c);} 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 : 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() { public DateAdp XtoUtc() {
java.util.Date date = under.getTime(); java.util.Date date = under.getTime();
java.util.TimeZone tz = under.getTimeZone(); java.util.TimeZone tz = under.getTimeZone();
@ -109,6 +112,7 @@ public class DateAdp implements CompareAble, Gfo_invk {
long dst_adj = dst ? 3600000 : 0; long dst_adj = dst ? 3600000 : 0;
return (under.getTimeInMillis() + offsetFromUTC + dst_adj) / 1000; return (under.getTimeInMillis() + offsetFromUTC + dst_adj) / 1000;
} }
public int WeekOfYear() {return under.get(Calendar.WEEK_OF_YEAR);} public int WeekOfYear() {return under.get(Calendar.WEEK_OF_YEAR);}
public int Frac() {return under.get(Calendar.MILLISECOND);} public int Frac() {return under.get(Calendar.MILLISECOND);}
public DateAdp Add_frac(int val) {return CloneAndAdd(Calendar.MILLISECOND, val);} 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); this.under = new GregorianCalendar(year, month - Month_base0adj, day, hour, minute, second);
under.set(Calendar.MILLISECOND, frac); 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; 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 DateAdp dateTime_obj_(Object v) {return new DateAdp((GregorianCalendar)v);}
public static final DateAdp_ Gfs = new DateAdp_(); public static final DateAdp_ Gfs = new DateAdp_();
public static int DaysInMonth(DateAdp date) { public static int DaysInMonth(DateAdp date) {return DaysInMonth(date.Month(), date.Year());}
int rv = DaysInMonth_ary[date.Month() - Int_.Base1]; public static int DaysInMonth(int month, int year) {
if (rv == 28 && IsLeapYear(date.Year())) rv = 29; int rv = DaysInMonth_ary[month - Int_.Base1];
if (rv == 28 && IsLeapYear(year)) rv = 29;
return rv; 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) { public static boolean IsLeapYear(int year) {
if (year % 4 != 0) return false; if (year % 4 != 0) return false;
else if (year % 400 == 0) return true; else if (year % 400 == 0) return true;
@ -114,10 +116,29 @@ public class DateAdp_ implements Gfo_invk {
c.setTimeInMillis(v); c.setTimeInMillis(v);
return new DateAdp(c); 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) { public static String Xto_str_fmt_or(DateAdp v, String fmt, String or) {
return v == null ? or : v.XtoStr_fmt(fmt); 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 public static final String
Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss" Fmt_iso8561_date_time = "yyyy-MM-dd HH:mm:ss"
, Fmt__yyyyMMdd = "yyyyMMdd"; , Fmt__yyyyMMdd = "yyyyMMdd";

View File

@ -60,6 +60,9 @@ public class DateAdp__tst {
@Test public void XtoUtc() { @Test public void XtoUtc() {
fxt.Test__to_utc("2012-01-01 00:00", "2012-01-01 05:00"); //4=Wed 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 { class DateAdp__fxt {
public void Test__parse_gplx(String raw, String expd) { 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) { public void Test__to_utc(String raw, String expd) {
Tfds.Eq(expd, DateAdp_.parse_gplx(raw).XtoUtc().XtoStr_fmt_yyyy_MM_dd_HH_mm()); 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; import java.text.DecimalFormat;
public class Decimal_adp implements CompareAble { public class Decimal_adp implements CompareAble {
public int compareTo(Object obj) {Decimal_adp comp = (Decimal_adp)obj; return under.compareTo(comp.under);} 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(BigDecimal v) {this.under = v;} private final BigDecimal under;
protected Decimal_adp(int v) {this.under = new BigDecimal(v);} protected Decimal_adp(int v) {this.under = new BigDecimal(v);}
public Object Under() {return under;} public Object Under() {return under;}
@ -79,6 +80,9 @@ public class Decimal_adp implements CompareAble {
} }
return new Decimal_adp(new_val); 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(Decimal_adp v) {return under.doubleValue() >= v.under.doubleValue();}
public boolean Comp_gte(int v) {return under.doubleValue() >= v;} public boolean Comp_gte(int v) {return under.doubleValue() >= v;}
public boolean Comp_lte(Decimal_adp v) {return under.doubleValue() <= v.under.doubleValue();} 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 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; 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.NumberFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.Locale; import java.util.Locale;
public class Decimal_adp_ { public class Decimal_adp_ {
public static final String Cls_val_name = "decimal"; public static final String Cls_val_name = "decimal";
public static final Class<?> Cls_ref_type = Decimal_adp.class; 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) + "%"; 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_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 divide_(long lhs, long rhs) {
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));} 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 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 { 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 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); 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); BigDecimal bd = (BigDecimal)nf.parse(raw);
return new Decimal_adp(bd); return new Decimal_adp(bd);
} catch (ParseException e) { } catch (ParseException e) {
throw Err_.new_("Decimal_adp_", "parse to decimal failed", "raw", raw); 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 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; package gplx;
import org.junit.*; import org.junit.*;
public class Decimal_adp__tst { public class Decimal_adp__tst {
private final Decimal_adp__fxt fxt = new Decimal_adp__fxt(); 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, 1000, "0.001");
fxt.Test_divide(1, 3, "0.33333333333333"); fxt.Test_divide(1, 3, "0.33333333333333");
fxt.Test_divide(1, 7, "0.14285714285714"); 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(1000, "1");
fxt.Test_base_1000(1234, "1.234"); fxt.Test_base_1000(1234, "1.234");
fxt.Test_base_1000(123, "0.123"); 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, 0, "1");
fxt.Test_parts(1, 2, "1.2"); fxt.Test_parts(1, 2, "1.2");
fxt.Test_parts(1, 23, "1.23"); fxt.Test_parts(1, 23, "1.23");
fxt.Test_parts(123, 4567, "123.4567"); fxt.Test_parts(123, 4567, "123.4567");
} }
@Test public void parse() { @Test public void parse() {
fxt.Test_parse("1", "1"); fxt.Test_parse("1", "1");
fxt.Test_parse("1.2", "1.2"); fxt.Test_parse("1.2", "1.2");
fxt.Test_parse("0.1", "0.1"); 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");
fxt.Test_truncate_decimal("1.1", "1"); fxt.Test_truncate_decimal("1.1", "1");
fxt.Test_truncate_decimal("1.9", "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, 1000, 1); // 0.001
fxt.Test_frac_1000(1, 3, 333); // 0.33333333 fxt.Test_frac_1000(1, 3, 333); // 0.33333333
fxt.Test_frac_1000(1234, 1000, 234); // 1.234 fxt.Test_frac_1000(1234, 1000, 234); // 1.234
fxt.Test_frac_1000(12345, 10000, 234); // 1.2345 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,123, 2, true);
fxt.Test_comp_lt(1,99999999, 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, 2, "0.0", "0.5");
fxt.Test_to_str_fmt(1, 3, "0.0", "0.3"); 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(10000, 7, "0,000.000", "1,428.571");
fxt.Test_to_str_fmt(1, 2, "00.00", "00.50"); 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", 3, "123.456");
fxt.Test_round("123.456", 2, "123.46"); fxt.Test_round("123.456", 2, "123.46");
fxt.Test_round("123.456", 1, "123.5"); fxt.Test_round("123.456", 1, "123.5");

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; package gplx;
public class Double_ { public class Double_ {
public static final String Cls_val_name = "double"; public static final String Cls_val_name = "double";
public static final Class<?> Cls_ref_type = Double.class; public static final Class<?> Cls_ref_type = Double.class;
@ -42,7 +43,9 @@ public class Double_ {
int v_as_int = (int)v; int v_as_int = (int)v;
return v == v_as_int return v == v_as_int
? Int_.To_str(v_as_int) // convert to int, and call print String to eliminate any trailing decimal places ? 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) { public static int Compare(double lhs, double rhs) {
if (lhs == rhs) return CompareAble_.Same; if (lhs == rhs) return CompareAble_.Same;

View File

@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx; package gplx;
import gplx.core.strings.*; import gplx.core.consoles.*; import gplx.core.brys.fmtrs.*; 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 { 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 int archive_dirs_max = 8;
private Io_url log_dir, err_fil; private Io_url log_dir, err_fil;
private final Ordered_hash queued_list = Ordered_hash_.New(); private final Ordered_hash queued_list = Ordered_hash_.New();
@ -85,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 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_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) { 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) { if (queue_enabled) {
String url_raw = url == null ? "mem" : url.Raw(); String url_raw = url == null ? "mem" : url.Raw();
Usr_log_fil fil = (Usr_log_fil)queued_list.Get_by(url_raw); Usr_log_fil fil = (Usr_log_fil)queued_list.Get_by(url_raw);
@ -100,6 +106,7 @@ public class Gfo_usr_dlg__log_base implements Gfo_usr_dlg__log {
if (enabled) if (enabled)
Io_mgr.Instance.AppendFilStr(url, txt); Io_mgr.Instance.AppendFilStr(url, txt);
} }
}
} }
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, "enabled_")) enabled = m.ReadYn("v"); if (ctx.Match(k, "enabled_")) enabled = m.ReadYn("v");

View File

@ -21,6 +21,7 @@ public interface Hash_adp extends gplx.core.lists.EnumerAble {
Object Get_by_or_fail(Object key); Object Get_by_or_fail(Object key);
void Add(Object key, Object val); void Add(Object key, Object val);
Hash_adp Add_and_more(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); void Add_as_key_and_val(Object val);
boolean Add_if_dupe_use_1st(Object key, Object val); boolean Add_if_dupe_use_1st(Object key, Object val);
void Add_if_dupe_use_nth(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 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 void Add(Object key, Object val) {}
public Hash_adp Add_and_more(Object key, Object val) {return this;} 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_as_key_and_val(Object val) {}
public void Add_if_dupe_use_nth(Object key, 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;} public boolean Add_if_dupe_use_1st(Object key, Object val) {return false;}

View File

@ -28,6 +28,7 @@ public class Int_ {
, Null = Int_.Min_value , Null = Int_.Min_value
, Base1 = 1 // for super 1 lists / arrays; EX: PHP; [a, b, c]; [1] => a , 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) , 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) { public static int Cast(Object obj) {

View File

@ -24,7 +24,9 @@ public class Io_url__tst {
class Io_url__fxt { class Io_url__fxt {
public void Clear() {Io_mgr.Instance.InitEngine_mem();} public void Clear() {Io_mgr.Instance.InitEngine_mem();}
public void Test__New__http_or_null(boolean os_is_wnt, String raw, String expd) { 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); 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)); 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; if (raw == null || rawLen == 0) return or;
long rv = 0, factor = 1; int tmp = 0; long rv = 0, factor = 1; int tmp = 0;
for (int i = rawLen; i > 0; i--) { 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; if (tmp == Int_.Min_value) return or;
rv += (tmp * factor); rv += (tmp * factor);
factor *= 10; factor *= 10;

View File

@ -16,6 +16,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
package gplx; package gplx;
public class Math_ { public class Math_ {
public static double Pow(double val, double exponent) {return java.lang.Math.pow(val, exponent);} 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 Pi = java.lang.Math.PI;
public static double E = java.lang.Math.E; public static double E = java.lang.Math.E;
public static int Ceil_as_int(double v) {return (int)Ceil(v);} public static int Ceil_as_int(double v) {return (int)Ceil(v);}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx; package gplx;
public class Type_ {//RF:2017-10-08 public class Type_ {//RF:2017-10-08
public static Class<?> Type_by_obj(Object o) {return o.getClass();} public static Class<?> Type_by_obj(Object o) {return o.getClass();}
public static Class<?> Type_by_primitive(Object o) { public static Class<?> Type_by_primitive(Object o) {
@ -45,6 +46,11 @@ public class Type_ {//RF:2017-10-08
return type.getName(); 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) { public static boolean Is_array(Class<?> t) {
return t.isArray(); return t.isArray();
} }

View File

@ -33,6 +33,9 @@ public class Bitmask_ {
} }
return rv; 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 boolean Has_byte(byte val, byte find) {return find == (val & find);}
public static byte Add_byte(byte flag, byte itm) {return (byte)(flag | itm);} public static byte Add_byte(byte flag, byte itm) {return (byte)(flag | itm);}
} }

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 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 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_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_as_key_and_val(Object val) {Add_base(val, val);}
public void Add_if_dupe_use_nth(Object key, Object 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 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 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 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_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_as_key_and_val(Object val) {Add_base(val, val);}
public void Add_if_dupe_use_nth(Object key, Object 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 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

@ -37,7 +37,9 @@ public interface String_bldr {
String_bldr Add(char c); String_bldr Add(char c);
String_bldr Add(int i); String_bldr Add(int i);
String_bldr Add_obj(Object o); 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 Add_at(int idx, String s);
String_bldr Del(int bgn, int len); 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(String s);
public abstract String_bldr Add(char c); public abstract String_bldr Add(char c);
public abstract String_bldr Add(int i); 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 Add_obj(Object o);
public abstract String_bldr Del(int bgn, int len); 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(String s) {sb.append(s); return this;}
@Override public String_bldr Add(char c) {sb.append(c); 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(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 Add_obj(Object o) {sb.append(o); return this;}
@Override public String_bldr Del(int bgn, int len) {sb.delete(bgn, len); 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(String s) {sb.append(s); return this;}
@Override public String_bldr Add(char c) {sb.append(c); 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(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 Add_obj(Object o) {sb.append(o); return this;}
@Override public String_bldr Del(int bgn, int len) {sb.delete(bgn, len); 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

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -112,6 +112,7 @@ public class Gftest {
bfr.Add(Bry__line_end); bfr.Add(Bry__line_end);
throw Err_.new_wo_type(bfr.To_str_and_clear()); 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) {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_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);} 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++){ for(int i=0; i< ALPHABET.length; i++){
toInt[ALPHABET[i]]= 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 EncodeString(String orig) {return Encode(Bry_.new_u8(orig));}
public static String Encode(byte[] buf){ public static String Encode(byte[] buf){

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.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 java.lang.*;
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 { public class Thread_adp implements Runnable {
private final String thread_name; private final Cancelable cxl; private final boolean cxlable; 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 Gfo_invk invk_itm; private final String invk_cmd; private final GfoMsg invk_msg;
private Thread thread; private Thread thread;
@gplx.Internal protected Thread_adp(String thread_name, Cancelable cxl, Gfo_invk invk_itm, String invk_cmd, GfoMsg invk_msg) { @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; 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__cancelable() {return cxlable;}
public boolean Thread__is_alive() {return thread == null ? false : thread.isAlive();} public boolean Thread__is_alive() {return thread == null ? false : thread.isAlive();}
public void Thread__interrupt() {thread.interrupt();} public void Thread__interrupt() {thread.interrupt();}
public void Thread__stop() {thread.stop();}
public void run() { public void run() {
try { try {
Gfo_invk_.Invk_by_msg(invk_itm, invk_cmd, invk_msg); 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() { 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(); 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 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, 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. 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.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 class Thread_adp_ {
public static void Sleep(int milliseconds) { public static void Sleep(int milliseconds) {
try { try {
Thread.sleep(milliseconds); Thread.sleep(milliseconds);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw Err_.new_exc(e, "core", "thread interrupted", "milliseconds", milliseconds); 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_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_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));} 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.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class Regx_adp { 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 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 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; 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); 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;} public Pattern Under() {return under;}
private void Under_sync() { 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 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 = true;
pattern_is_invalid_exception = e; 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) { public Regx_match Match(String input, int bgn) {
@ -56,11 +60,29 @@ public class Regx_adp {
Regx_group[] ary = Regx_group.Ary_empty; Regx_group[] ary = Regx_group.Ary_empty;
int groups_len = match.groupCount(); int groups_len = match.groupCount();
if (success && groups_len > 0) { 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]; ary = new Regx_group[groups_len];
for (int i = 0; i < groups_len; i++) 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)); 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); return new Regx_match(success, match_bgn, match_end, ary);
} }
public String ReplaceAll(String input, String replace) {return under.matcher(input).replaceAll(replace);} 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,7 +15,7 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.regxs; import gplx.*; import gplx.langs.*; package gplx.langs.regxs; import gplx.*; import gplx.langs.*;
public class Regx_adp_ { public class Regx_adp_ {
public static Regx_adp new_(String pattern) {return new Regx_adp(pattern);} 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) { public static List_adp Find_all(String src, String pat) {
int src_len = String_.Len(src); int src_len = String_.Len(src);
Regx_adp regx = Regx_adp_.new_(pat); Regx_adp regx = Regx_adp_.new_(pat);
@ -34,7 +34,7 @@ public class Regx_adp_ {
return regx.ReplaceAll(raw, replace); return regx.ReplaceAll(raw, replace);
} }
public static boolean Match(String input, String pattern) { 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(); 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 + 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() { @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) { Regx_match[] matches_(int... bgnAry) {
int aryLen = Array_.Len(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_bgn() {return find_bgn;} private final int find_bgn;
public int Find_end() {return find_end;} private final int find_end; public int Find_end() {return find_end;} private final int find_end;
public int Find_len() {return find_end - find_bgn;} 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 Regx_group[] Groups() {return groups;} private final Regx_group[] groups;
public static final Regx_match[] Ary_empty = new Regx_match[0]; 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); Node xatr = list.getNamedItem(key);
return (xatr == null) ? or : xatr.getNodeValue(); 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) { public XmlAtr Fetch(String key) {
Node xatr = list.getNamedItem(key); if (xatr == null) throw Err_.new_missing_key(key); Node xatr = list.getNamedItem(key); if (xatr == null) throw Err_.new_missing_key(key);
return new XmlAtr(xatr); return new XmlAtr(xatr);

View File

@ -29,15 +29,45 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
public class XmlDoc_ { 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) { static Document doc_(String raw) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder bldr = null; DocumentBuilder bldr = null;
try {bldr = factory.newDocumentBuilder();} try {
catch (ParserConfigurationException e) {throw Err_.new_exc(e, "xml", "failed to create newDocumentBuilder");} // 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); StringReader reader = new StringReader(raw);
InputSource source = new InputSource(reader); InputSource source = new InputSource(reader);
Document doc = null; Document doc = null;
@ -47,5 +77,4 @@ public class XmlDoc_ {
return doc; return doc;
} }
public static final String Err_XmlException = "gplx.xmls.XmlException"; public static final String Err_XmlException = "gplx.xmls.XmlException";
} }
//#}

View File

@ -80,7 +80,7 @@ class GfmlLxr_group implements GfmlLxr {
public GfmlTkn MakeTkn(CharStream stream, int hookLength) { public GfmlTkn MakeTkn(CharStream stream, int hookLength) {
while (stream.AtMid()) { while (stream.AtMid()) {
if (!ignoreOutput) if (!ignoreOutput)
sb.Add_mid(stream.Ary(), stream.Pos(), hookLength); sb.Add_mid_len(stream.Ary(), stream.Pos(), hookLength);
stream.MoveNextBy(hookLength); stream.MoveNextBy(hookLength);
String found = String_.cast(trie.FindMatch(stream)); String found = String_.cast(trie.FindMatch(stream));

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,19 +13,49 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs; import gplx.*; package gplx.dbs;
import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.engines.*; import gplx.dbs.qrys.*; import gplx.dbs.sys.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*;
import gplx.Bool_;
import gplx.Double_;
import gplx.Err_;
import gplx.Gfo_log_;
import gplx.Gfo_usr_dlg;
import gplx.Gfo_usr_dlg_;
import gplx.Int_;
import gplx.Io_url;
import gplx.List_adp;
import gplx.List_adp_;
import gplx.Rls_able;
import gplx.String_;
import gplx.core.stores.DataRdr;
import gplx.core.stores.DataRdr_;
import gplx.dbs.conn_props.Db_conn_props_mgr;
import gplx.dbs.engines.Db_engine;
import gplx.dbs.metas.Dbmeta_idx_fld;
import gplx.dbs.metas.Dbmeta_tbl_mgr;
import gplx.dbs.qrys.Db_qry__select_in_tbl;
import gplx.dbs.qrys.Db_qry_delete;
import gplx.dbs.qrys.Db_qry_insert;
import gplx.dbs.qrys.Db_qry_sql;
import gplx.dbs.qrys.Db_qry_update;
import gplx.dbs.qrys.bats.Db_batch_mgr;
import gplx.dbs.sys.Db_sys_mgr;
import gplx.dbs.wkrs.SqlWkrMgr;
public class Db_conn { public class Db_conn {
private final List_adp rls_list = List_adp_.New(); private final List_adp rls_list = List_adp_.New();
public Db_conn(Db_engine engine) { public Db_conn(Db_engine engine) {
this.engine = engine; this.engine = engine;
this.sys_mgr = new Db_sys_mgr(this); this.sys_mgr = new Db_sys_mgr(this);
this.wkrMgr = new SqlWkrMgr(this);
engine.CtorConn(wkrMgr);
} }
public Db_conn_info Conn_info() {return engine.Conn_info();} public Db_conn_info Conn_info() {return engine.Conn_info();}
public Db_conn_props_mgr Props() {return engine.Props();} public Db_conn_props_mgr Props() {return engine.Props();}
public Db_batch_mgr Batch_mgr() {return engine.Batch_mgr();} public Db_batch_mgr Batch_mgr() {return engine.Batch_mgr();}
public Db_engine Engine() {return engine;} private final Db_engine engine; public Db_engine Engine() {return engine;} private final Db_engine engine;
public Db_sys_mgr Sys_mgr() {return sys_mgr;} private final Db_sys_mgr sys_mgr; // autonum and other functions public Db_sys_mgr Sys_mgr() {return sys_mgr;} private final Db_sys_mgr sys_mgr; // autonum and other functions
public SqlWkrMgr WkrMgr() {return wkrMgr;} private final SqlWkrMgr wkrMgr;
public boolean Eq(Db_conn comp) {return String_.Eq(engine.Conn_info().Db_api(), comp.Conn_info().Db_api());} public boolean Eq(Db_conn comp) {return String_.Eq(engine.Conn_info().Db_api(), comp.Conn_info().Db_api());}
public void Txn_bgn(String name) {engine.Txn_bgn(name);} public void Txn_bgn(String name) {engine.Txn_bgn(name);}
public void Txn_end() {engine.Txn_end();} public void Txn_end() {engine.Txn_end();}

View File

@ -28,6 +28,7 @@ public class Db_crt_ {
public static Criteria_fld New_between (String key, Comparable lo, Comparable hi) {return Criteria_fld.new_(key, Criteria_.between_(lo, hi));} public static Criteria_fld New_between (String key, Comparable lo, Comparable hi) {return Criteria_fld.new_(key, Criteria_.between_(lo, hi));}
public static Criteria_fld New_in (String key, Object... vals) {return Criteria_fld.new_(key, Criteria_.in_(vals));} public static Criteria_fld New_in (String key, Object... vals) {return Criteria_fld.new_(key, Criteria_.in_(vals));}
public static Criteria_fld New_like (String key, String pattern) {return Criteria_fld.new_(key, Criteria_.like_(pattern));} public static Criteria_fld New_like (String key, String pattern) {return Criteria_fld.new_(key, Criteria_.like_(pattern));}
public static Criteria_fld New_like_not (String key, String pattern) {return Criteria_fld.new_(key, Criteria_.Not(Criteria_.like_(pattern)));}
public static Criteria eq_many_(String... ary) { public static Criteria eq_many_(String... ary) {
Criteria rv = null; Criteria rv = null;

View File

@ -29,6 +29,7 @@ public class Dbmeta_fld_list {
public String Add_int_pkey_autonum(String name) {return Add(Dbmeta_fld_itm.new_int(name).Primary_y_().Autonum_y_());} public String Add_int_pkey_autonum(String name) {return Add(Dbmeta_fld_itm.new_int(name).Primary_y_().Autonum_y_());}
public String Add_int_autonum(String name) {return Add(Dbmeta_fld_itm.new_int(name).Autonum_y_());} public String Add_int_autonum(String name) {return Add(Dbmeta_fld_itm.new_int(name).Autonum_y_());}
public String Add_int_dflt(String name, int dflt) {return Add(Dbmeta_fld_itm.new_int(name).Default_(dflt));} public String Add_int_dflt(String name, int dflt) {return Add(Dbmeta_fld_itm.new_int(name).Default_(dflt));}
public String Add_int_null(String name) {return Add(Dbmeta_fld_itm.new_int(name).Nullable_y_());}
public String Add_long(String name) {return Add(Dbmeta_fld_itm.new_long(name));} public String Add_long(String name) {return Add(Dbmeta_fld_itm.new_long(name));}
public String Add_float(String name) {return Add(Dbmeta_fld_itm.new_float(name));} public String Add_float(String name) {return Add(Dbmeta_fld_itm.new_float(name));}
public String Add_double(String name) {return Add(Dbmeta_fld_itm.new_double(name));} public String Add_double(String name) {return Add(Dbmeta_fld_itm.new_double(name));}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,14 +13,32 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines; import gplx.*; import gplx.dbs.*; package gplx.dbs.engines;
import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*;
import gplx.Gfo_usr_dlg;
import gplx.Io_url;
import gplx.core.stores.DataRdr;
import gplx.dbs.Db_conn;
import gplx.dbs.Db_conn_info;
import gplx.dbs.Db_qry;
import gplx.dbs.Db_rdr;
import gplx.dbs.Db_stmt;
import gplx.dbs.Dbmeta_fld_itm;
import gplx.dbs.Dbmeta_idx_itm;
import gplx.dbs.Dbmeta_tbl_itm;
import gplx.dbs.conn_props.Db_conn_props_mgr;
import gplx.dbs.metas.Dbmeta_tbl_mgr;
import gplx.dbs.qrys.bats.Db_batch_mgr;
import gplx.dbs.sqls.Sql_qry_wtr;
import gplx.dbs.wkrs.SqlWkrMgr;
public interface Db_engine { public interface Db_engine {
String Tid(); String Tid();
Db_conn_info Conn_info(); Db_conn_info Conn_info();
Db_conn_props_mgr Props(); Db_conn_props_mgr Props();
Db_batch_mgr Batch_mgr(); Db_batch_mgr Batch_mgr();
Sql_qry_wtr Sql_wtr(); Sql_qry_wtr Sql_wtr();
void CtorConn(SqlWkrMgr wkrMgr);
Db_engine New_clone(Db_conn_info conn_info); Db_engine New_clone(Db_conn_info conn_info);
void Conn_open(); void Conn_open();
void Conn_term(); void Conn_term();

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -15,6 +15,8 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*; package gplx.dbs.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*; import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*;
import gplx.dbs.wkrs.SqlWkrMgr;
public class Mem_engine implements Db_engine { public class Mem_engine implements Db_engine {
private final Hash_adp tbl_hash = Hash_adp_.New(); private final Hash_adp tbl_hash = Hash_adp_.New();
Mem_engine(Db_conn_info conn_info) { Mem_engine(Db_conn_info conn_info) {
@ -27,6 +29,7 @@ public class Mem_engine implements Db_engine {
public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr(); public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr();
public Mem_exec_select Qry_runner() {return qry_runner;} private Mem_exec_select qry_runner; public Mem_exec_select Qry_runner() {return qry_runner;} private Mem_exec_select qry_runner;
public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic(); public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic();
@Override public void CtorConn(SqlWkrMgr wkrMgr) {}
public Db_engine New_clone(Db_conn_info conn_info) {return new Mem_engine(conn_info);} public Db_engine New_clone(Db_conn_info conn_info) {return new Mem_engine(conn_info);}
public Db_stmt Stmt_by_qry(Db_qry qry) {return new Mem_stmt(this, qry);} public Db_stmt Stmt_by_qry(Db_qry qry) {return new Mem_stmt(this, qry);}
public Mem_tbl Tbls__get(String name) {return (Mem_tbl)tbl_hash.Get_by(name);} public Mem_tbl Tbls__get(String name) {return (Mem_tbl)tbl_hash.Get_by(name);}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -15,10 +15,13 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines.mysql; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*; package gplx.dbs.engines.mysql; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*; import gplx.dbs.metas.*; import gplx.core.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*; import gplx.dbs.metas.*;
import gplx.dbs.wkrs.SqlWkrMgr;
import java.sql.*; import java.sql.*;
public class Mysql_engine extends Db_engine_sql_base { public class Mysql_engine extends Db_engine_sql_base {
@Override public String Tid() {return Mysql_conn_info.Tid_const;} @Override public String Tid() {return Mysql_conn_info.Tid_const;}
@Override public Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__mysql();} @Override public Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__mysql();}
@Override public void CtorConn(SqlWkrMgr wkrMgr) {}
@Override public Db_engine New_clone(Db_conn_info connectInfo) { @Override public Db_engine New_clone(Db_conn_info connectInfo) {
Mysql_engine rv = new Mysql_engine(); Mysql_engine rv = new Mysql_engine();
rv.Ctor(connectInfo); rv.Ctor(connectInfo);

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -15,12 +15,15 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines.noops; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*; package gplx.dbs.engines.noops; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*; import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.sqls.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.bats.*;
import gplx.dbs.wkrs.SqlWkrMgr;
public class Noop_engine implements Db_engine { public class Noop_engine implements Db_engine {
public String Tid() {return Noop_conn_info.Tid_const;} public String Tid() {return Noop_conn_info.Tid_const;}
public Db_conn_info Conn_info() {return Db_conn_info_.Null;} public Db_conn_info Conn_info() {return Db_conn_info_.Null;}
public Db_conn_props_mgr Props() {return props;} private final Db_conn_props_mgr props = new Db_conn_props_mgr(); public Db_conn_props_mgr Props() {return props;} private final Db_conn_props_mgr props = new Db_conn_props_mgr();
public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr(); public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr();
public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic(); public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic();
@Override public void CtorConn(SqlWkrMgr wkrMgr) {}
public void Conn_open() {} public void Conn_open() {}
public void Conn_term() {} public void Conn_term() {}
public Db_engine New_clone(Db_conn_info url) {return this;} public Db_engine New_clone(Db_conn_info url) {return this;}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -15,10 +15,15 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines.postgres; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*; package gplx.dbs.engines.postgres; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*; import gplx.dbs.metas.*; import gplx.core.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*; import gplx.dbs.metas.*;
import java.sql.*; import gplx.dbs.wkrs.SqlWkrMgr;
import java.sql.Connection;
import java.sql.ResultSet;
public class Postgres_engine extends Db_engine_sql_base { public class Postgres_engine extends Db_engine_sql_base {
@Override public String Tid() {return Postgres_conn_info.Tid_const;} @Override public String Tid() {return Postgres_conn_info.Tid_const;}
@Override public Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__mysql();} @Override public Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__mysql();}
@Override public void CtorConn(SqlWkrMgr wkrMgr) {}
@Override public Db_engine New_clone(Db_conn_info connectInfo) { @Override public Db_engine New_clone(Db_conn_info connectInfo) {
Postgres_engine rv = new Postgres_engine(); Postgres_engine rv = new Postgres_engine();
rv.Ctor(connectInfo); rv.Ctor(connectInfo);

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -21,6 +21,8 @@ import gplx.core.consoles.Console_adp_;
import gplx.core.consoles.Console_adp__sys; import gplx.core.consoles.Console_adp__sys;
import gplx.core.ios.IoItmFil; import gplx.core.ios.IoItmFil;
import gplx.dbs.wkrs.SqlWkrMgr;
import gplx.dbs.wkrs.randoms.SqliteRandomWkr;
import org.sqlite.SQLiteConnection; import org.sqlite.SQLiteConnection;
public class Sqlite_engine extends Db_engine_sql_base { public class Sqlite_engine extends Db_engine_sql_base {
private final Sqlite_txn_mgr txn_mgr; private final Sqlite_schema_mgr schema_mgr; private final Sqlite_txn_mgr txn_mgr; private final Sqlite_schema_mgr schema_mgr;
@ -30,6 +32,10 @@ public class Sqlite_engine extends Db_engine_sql_base {
} }
@Override public String Tid() {return Sqlite_conn_info.Key_const;} @Override public String Tid() {return Sqlite_conn_info.Key_const;}
@Override public gplx.dbs.sqls.Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__sqlite();} @Override public gplx.dbs.sqls.Sql_qry_wtr Sql_wtr() {return Sql_qry_wtr_.New__sqlite();}
public void CtorConn(SqlWkrMgr wkrMgr) {
wkrMgr.Set(new SqliteRandomWkr());
}
@Override public Db_engine New_clone(Db_conn_info connectInfo) { @Override public Db_engine New_clone(Db_conn_info connectInfo) {
Sqlite_engine rv = new Sqlite_engine(); Sqlite_engine rv = new Sqlite_engine();
rv.Ctor(connectInfo); rv.Ctor(connectInfo);
@ -89,7 +95,7 @@ public class Sqlite_engine extends Db_engine_sql_base {
catch (SQLException e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to set busy timeout; err=~{0}", Err_.Message_gplx_log(e));} catch (SQLException e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to set busy timeout; err=~{0}", Err_.Message_gplx_log(e));}
return rv; return rv;
} }
public static final Sqlite_engine Instance = new Sqlite_engine(); public static final Sqlite_engine Instance = new Sqlite_engine();
} }
class Db_rdr__sqlite extends Db_rdr__basic { @Override public byte Read_byte(String k) {try {return (byte)Int_.Cast(rdr.getObject(k));} catch (Exception e) {throw Err_.new_exc(e, "db", "read failed", "k", k, "type", Byte_.Cls_val_name);}} class Db_rdr__sqlite extends Db_rdr__basic { @Override public byte Read_byte(String k) {try {return (byte)Int_.Cast(rdr.getObject(k));} catch (Exception e) {throw Err_.new_exc(e, "db", "read failed", "k", k, "type", Byte_.Cls_val_name);}}
@Override public boolean Read_bool_by_byte(String k) { @Override public boolean Read_bool_by_byte(String k) {

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -15,6 +15,8 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.dbs.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*; package gplx.dbs.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.*; import gplx.dbs.sqls.*; import gplx.dbs.qrys.bats.*; import gplx.core.stores.*; import gplx.dbs.metas.*; import gplx.dbs.conn_props.*; import gplx.dbs.qrys.*; import gplx.dbs.sqls.*; import gplx.dbs.qrys.bats.*;
import gplx.dbs.wkrs.SqlWkrMgr;
public class TdbEngine implements Db_engine { public class TdbEngine implements Db_engine {
public String Tid() {return Tdb_conn_info.Tid_const;} public String Tid() {return Tdb_conn_info.Tid_const;}
public Db_conn_info Conn_info() {return conn_info;} private Db_conn_info conn_info; public Db_conn_info Conn_info() {return conn_info;} private Db_conn_info conn_info;
@ -22,6 +24,7 @@ public class TdbEngine implements Db_engine {
public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr(); public Db_batch_mgr Batch_mgr() {return batch_mgr;} private final Db_batch_mgr batch_mgr = new Db_batch_mgr();
public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic(); public Sql_qry_wtr Sql_wtr() {return sql_wtr;} private final Sql_qry_wtr sql_wtr = Sql_qry_wtr_.New__basic();
public TdbDatabase Db() {return db;} TdbDatabase db; public TdbDatabase Db() {return db;} TdbDatabase db;
@Override public void CtorConn(SqlWkrMgr wkrMgr) {}
public void Conn_open() { public void Conn_open() {
Tdb_conn_info tdb_url = (Tdb_conn_info)conn_info; Tdb_conn_info tdb_url = (Tdb_conn_info)conn_info;
String url_str = tdb_url.Server(); String url_str = tdb_url.Server();

View File

@ -0,0 +1,20 @@
/*
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.dbs.wkrs;
public interface SqlWkr {
String Key();
}

View File

@ -0,0 +1,43 @@
/*
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.dbs.wkrs;
import gplx.dbs.Db_conn;
import gplx.dbs.wkrs.randoms.SqlRandomWkr;
import java.util.HashMap;
import java.util.Map;
public class SqlWkrMgr {
private final Map<String, SqlWkr> map = new HashMap<>();
private final Db_conn conn;
public SqlWkrMgr(Db_conn conn) {
this.conn = conn;
}
public SqlWkr Get(String key) {
return map.get(key);
}
public void Set(SqlWkr wkr) {
map.put(wkr.Key(), wkr);
}
public Object ExecRandomObj(String select, String from, String where) {
SqlRandomWkr wkr = (SqlRandomWkr)map.get(SqlWkrMgr.WKR_RANDOM);
return wkr.SelectRandomRow(conn, select, from, where)[0];
}
public static final String WKR_RANDOM = "random";
}

View File

@ -0,0 +1,23 @@
/*
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.dbs.wkrs.randoms;
import gplx.dbs.Db_conn;
import gplx.dbs.wkrs.SqlWkr;
public interface SqlRandomWkr extends SqlWkr {
Object[] SelectRandomRow(Db_conn conn, String select, String from, String where);
}

View File

@ -0,0 +1,60 @@
/*
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.dbs.wkrs.randoms;
import gplx.RandomAdp_;
import gplx.dbs.Db_conn;
import gplx.dbs.Db_rdr;
import gplx.dbs.Db_rdr_;
import gplx.dbs.wkrs.SqlWkrMgr;
public class SqliteRandomWkr implements SqlRandomWkr {
@Override public String Key() {return SqlWkrMgr.WKR_RANDOM;}
// NOTE: selects only 1 random row to simplify method signature
// * uses COUNT, LIMIT, OFFSET, so should also work for MySQL
// * to return many rows, look at https://stackoverflow.com/questions/4114940/select-random-rows-in-sqlite
// EX: SELECT * FROM table WHERE id IN (SELECT id FROM table ORDER BY RANDOM() LIMIT x)
// Also, note that SQLite does not support TYPE_FORWARD_ONLY so can't jump back and forth thru ResultSet
@Override public Object[] SelectRandomRow(Db_conn conn, String select, String from, String where) {
Db_rdr rdr = Db_rdr_.Empty;
try {
String sqlSuffix = ("FROM " + from + " WHERE " + where);
// get rowCount of resultSet
rdr = conn.Stmt_sql("SELECT COUNT(*) AS RowCount " + sqlSuffix).Exec_select__rls_auto();
int rowCount = rdr.Read_int("RowCount");
// get random row
int random = RandomAdp_.new_().Next(rowCount);
rdr = conn.Stmt_sql("SELECT " + select + " " + sqlSuffix + " LIMIT 1 OFFSET " + random).Exec_select__rls_auto();
// return result
int fldsLen = rdr.Fld_len();
Object[] rv = new Object[fldsLen];
for (int i = 0; i < fldsLen; i++) {
rv[i] = rdr.Read_at(i);
}
return rv;
}
catch (Exception exc) { // for debugging; should log
throw exc;
}
finally {
rdr.Rls();
}
}
}

View File

@ -0,0 +1,51 @@
/*
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.dbs.wkrs.randoms;
import gplx.dbs.Db_conn;
import gplx.dbs.wkrs.SqlWkrMgr;
import java.util.ArrayList;
import java.util.List;
public class TestRandomWkr implements SqlRandomWkr {
private final List<Object[]> list = new ArrayList<>();
private int index = 0;
public void AddRow(Object... ary) {
list.add(ary);
}
public void Clear() {
list.clear();
index = 0;
}
public String SelectRandomRowSelect() {return selectRandomRowSelect;} private String selectRandomRowSelect;
public String SelectRandomRowFrom() {return selectRandomRowFrom;} private String selectRandomRowFrom;
public String SelectRandomRowWhere() {return selectRandomRowWhere;} private String selectRandomRowWhere;
@Override public String Key() {return SqlWkrMgr.WKR_RANDOM;}
@Override public Object[] SelectRandomRow(Db_conn conn, String select, String from, String where) {
this.selectRandomRowSelect = select;
this.selectRandomRowFrom = from;
this.selectRandomRowWhere = where;
return list.get(index++);
}
public static TestRandomWkr New(Db_conn conn) {
TestRandomWkr wkr = new TestRandomWkr();
conn.WkrMgr().Set(wkr);
return wkr;
}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,10 +13,31 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.gfui.kits.swts; import gplx.*; import gplx.gfui.*; import gplx.gfui.kits.*; package gplx.gfui.kits.swts;
import gplx.Bool_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Byte_ascii;
import gplx.Err_;
import gplx.GfoMsg;
import gplx.Gfo_evt_itm;
import gplx.Gfo_evt_mgr;
import gplx.Gfo_evt_mgr_;
import gplx.Gfo_evt_mgr_owner;
import gplx.Gfo_invk;
import gplx.Gfo_invk_;
import gplx.GfsCtx;
import gplx.Int_;
import gplx.Io_mgr;
import gplx.Io_url;
import gplx.Keyval_hash;
import gplx.Long_;
import gplx.Object_;
import gplx.String_;
import gplx.Type_;
import gplx.UsrDlg_;
import gplx.core.envs.System_; import gplx.core.envs.System_;
import gplx.core.primitives.*;
import gplx.core.threads.Thread_adp_;
import gplx.gfui.controls.elems.GfuiElem; import gplx.gfui.controls.elems.GfuiElem;
import gplx.gfui.controls.gxws.GxwCbkHost; import gplx.gfui.controls.gxws.GxwCbkHost;
import gplx.gfui.controls.gxws.GxwCore_base; import gplx.gfui.controls.gxws.GxwCore_base;
@ -24,27 +45,32 @@ import gplx.gfui.controls.gxws.GxwElem;
import gplx.gfui.controls.gxws.Gxw_html; import gplx.gfui.controls.gxws.Gxw_html;
import gplx.gfui.controls.gxws.Gxw_html_load_tid_; import gplx.gfui.controls.gxws.Gxw_html_load_tid_;
import gplx.gfui.controls.standards.Gfui_html; import gplx.gfui.controls.standards.Gfui_html;
import gplx.gfui.controls.standards.Gfui_tab_mgr; import gplx.gfui.ipts.IptEvtDataMouse;
import gplx.gfui.draws.ColorAdp; import gplx.gfui.ipts.IptMouseBtn;
import gplx.gfui.draws.ColorAdp_; import gplx.gfui.ipts.IptMouseBtn_;
import gplx.gfui.ipts.*; import gplx.gfui.ipts.IptMouseWheel_;
import gplx.gfui.kits.core.Swt_kit; import gplx.gfui.kits.core.Swt_kit;
import java.security.acl.Owner;
import gplx.*;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.*; import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.*; import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.graphics.*; import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.widgets.*; import org.eclipse.swt.browser.LocationListener;
import java.security.acl.Owner; import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.SWT; import org.eclipse.swt.browser.StatusTextEvent;
import org.eclipse.swt.browser.*; import org.eclipse.swt.browser.StatusTextListener;
import org.eclipse.swt.events.*; import org.eclipse.swt.browser.TitleEvent;
import org.eclipse.swt.graphics.*; import org.eclipse.swt.browser.TitleListener;
import org.eclipse.swt.widgets.*; import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
public class Swt_html implements Gxw_html, Swt_control, FocusListener, Gfo_evt_mgr_owner { public class Swt_html implements Gxw_html, Swt_control, FocusListener, Gfo_evt_mgr_owner {
private Swt_html_lnr_location lnr_location; private Swt_html_lnr_status lnr_status; private Swt_html_lnr_location lnr_location; private Swt_html_lnr_status lnr_status;
@ -206,7 +232,10 @@ class Swt_html_lnr_status implements StatusTextListener {
public void Host_set(Gfo_evt_itm host) {this.host = host;} Gfo_evt_itm host; public void Host_set(Gfo_evt_itm host) {this.host = host;} Gfo_evt_itm host;
@Override public void changed(StatusTextEvent ev) { @Override public void changed(StatusTextEvent ev) {
if (html_box.Kit().Kit_mode__term()) return; // shutting down raises status changed events; ignore, else SWT exception thrown; DATE:2014-05-29 if (html_box.Kit().Kit_mode__term()) return; // shutting down raises status changed events; ignore, else SWT exception thrown; DATE:2014-05-29
String ev_text = ev.text;
// 2020-09-22|ISSUE#:799|normalize URL due to SWT 4.16
String ev_text = Swt_html_utl.NormalizeSwtUrl(ev.text);
String load_by_url_path = html_box.Load_by_url_path(); String load_by_url_path = html_box.Load_by_url_path();
if (load_by_url_path != null) ev_text = String_.Replace(ev_text, load_by_url_path, ""); // remove "C:/xowa/tab_1.html" if (load_by_url_path != null) ev_text = String_.Replace(ev_text, load_by_url_path, ""); // remove "C:/xowa/tab_1.html"
// if (String_.Has(ev_text, "Loading [MathJax]")) return; // suppress MathJax messages; // NOTE: disabled for 2.1 (which no longer outputs messages to status); DATE:2013-05-03 // if (String_.Has(ev_text, "Loading [MathJax]")) return; // suppress MathJax messages; // NOTE: disabled for 2.1 (which no longer outputs messages to status); DATE:2013-05-03
@ -227,17 +256,28 @@ class Swt_html_lnr_location implements LocationListener {
@Override public void changed(LocationEvent arg) {Pub_evt(arg, Gfui_html.Evt_location_changed);} @Override public void changed(LocationEvent arg) {Pub_evt(arg, Gfui_html.Evt_location_changed);}
@Override public void changing(LocationEvent arg) {Pub_evt(arg, Gfui_html.Evt_location_changing);} @Override public void changing(LocationEvent arg) {Pub_evt(arg, Gfui_html.Evt_location_changing);}
private void Pub_evt(LocationEvent arg, String evt) { private void Pub_evt(LocationEvent arg, String evt) {
String location = arg.location; // 2020-09-22|ISSUE#:799|normalize URL due to SWT 4.16
if (String_.Eq(location, "about:blank")) return; // location changing event fires once when page is loaded; ignore String location = Swt_html_utl.NormalizeSwtUrl(arg.location);
if ( html_box.Browser_tid() == Swt_html.Browser_tid_webkit // webkit prefixes "about:blank" to anchors; causes TOC to fail when clicking on links; EX:about:blank#TOC1; DATE:2015-06-09
&& String_.Has_at_bgn(location, "about:blank")) { // location_changing fires once when page is loaded -> ignore
location = String_.Mid(location, 11); // 11 = "about:blank".length if (String_.Eq(location, String_.Empty)) {
return;
} }
if ( html_box.Html_doc_html_load_tid() == Gxw_html_load_tid_.Tid_url // navigating to file://page.html will fire location event; ignore if url mode
// navigating to file://page.html will fire location event; ignore if url mode (loading pages from file)
if (html_box.Html_doc_html_load_tid() == Gxw_html_load_tid_.Tid_url
&& String_.Has_at_bgn(location, "file:") && String_.Has_at_bgn(location, "file:")
&& String_.Has_at_end(location, ".html") && String_.Has_at_end(location, ".html")
) ) {
return; return;
}
if (String_.Has_at_bgn(location, "javascript:")) {
html_box.Html_js_eval_script(location);
arg.doit = false;
return;
}
try { try {
Gfo_evt_mgr_.Pub_obj(host, evt, "v", location); Gfo_evt_mgr_.Pub_obj(host, evt, "v", location);
arg.doit = false; // cancel navigation event, else there will be an error when trying to go to invalid location arg.doit = false; // cancel navigation event, else there will be an error when trying to go to invalid location

View File

@ -0,0 +1,40 @@
/*
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.gfui.kits.swts;
import gplx.String_;
public class Swt_html_utl {
private static final String URL_PREFIX_ABOUT = "about:";
private static final String URL_PREFIX_BLANK = "blank";
public static String NormalizeSwtUrl(String url) {
String rv = url;
// 2020-09-19|ISSUE#:799|strip "about:" from url due to SWT 4.16
rv = String_.Has_at_bgn(rv, URL_PREFIX_ABOUT)
? String_.Mid(rv, URL_PREFIX_ABOUT.length())
: rv;
// 2015-06-09|webkit prefixes "about:blank" to anchors; causes TOC to fail when clicking on links; EX:about:blank#TOC1
// 2020-09-22|removed webkit check due to SWT 4.16; `html_box.Browser_tid() == Swt_html.Browser_tid_webkit`
// still strip "blank"; note that SWT 4.16 changes anchors from "file:///#anchor" to "en.w/wiki/page/#anchor"
rv = String_.Has_at_bgn(rv, URL_PREFIX_BLANK)
? String_.Mid(rv, URL_PREFIX_BLANK.length())
: rv;
return rv;
}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,10 +13,26 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.core.gfobjs; import gplx.*; import gplx.core.*; package gplx.core.gfobjs;
import gplx.langs.jsons.*;
import gplx.Err_;
import gplx.Io_mgr;
import gplx.Io_url;
import gplx.langs.jsons.Json_ary;
import gplx.langs.jsons.Json_doc;
import gplx.langs.jsons.Json_itm;
import gplx.langs.jsons.Json_itm_;
import gplx.langs.jsons.Json_itm_bool;
import gplx.langs.jsons.Json_itm_decimal;
import gplx.langs.jsons.Json_itm_int;
import gplx.langs.jsons.Json_itm_long;
import gplx.langs.jsons.Json_itm_str;
import gplx.langs.jsons.Json_kv;
import gplx.langs.jsons.Json_nde;
import gplx.langs.jsons.Json_parser;
public class Gfobj_rdr__json { public class Gfobj_rdr__json {
private final Json_parser parser = new Json_parser(); private final Json_parser parser = new Json_parser();
public Gfobj_grp Load(Io_url url) { public Gfobj_grp Load(Io_url url) {
byte[] src = Io_mgr.Instance.LoadFilBryOrNull(url); if (src == null) return null; byte[] src = Io_mgr.Instance.LoadFilBryOrNull(url); if (src == null) return null;
return this.Parse(src); return this.Parse(src);
@ -56,7 +72,7 @@ public class Gfobj_rdr__json {
case Json_itm_.Tid__nde: case Json_itm_.Tid__nde:
Gfobj_nde sub_gnde = Gfobj_nde.New(); Gfobj_nde sub_gnde = Gfobj_nde.New();
gnde.Add_nde(key_str, sub_gnde); gnde.Add_nde(key_str, sub_gnde);
Parse_nde(Json_nde.cast(val), sub_gnde); Parse_nde(Json_nde.Cast(val), sub_gnde);
break; break;
default: throw Err_.new_unhandled_default(val_tid); default: throw Err_.new_unhandled_default(val_tid);
} }
@ -77,7 +93,7 @@ public class Gfobj_rdr__json {
} }
case Json_itm_.Tid__nde: { case Json_itm_.Tid__nde: {
Gfobj_nde sub_ary = Gfobj_nde.New(); Gfobj_nde sub_ary = Gfobj_nde.New();
Parse_nde(Json_nde.cast(jsub), sub_ary); Parse_nde(Json_nde.Cast(jsub), sub_ary);
ary[i] = sub_ary; ary[i] = sub_ary;
break; break;
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,17 +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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.core.primitives; import gplx.*; import gplx.core.*; package gplx.core.primitives;
import gplx.Byte_ascii;
import gplx.Decimal_adp;
import gplx.Decimal_adp_;
import gplx.Int_;
import gplx.Math_;
public class Gfo_number_parser { public class Gfo_number_parser {
public int Rv_as_int() {return (int)num_val;} private long num_val = 0; public int Rv_as_int() {return (int)num_val;} private long num_val = 0;
public long Rv_as_long() {return num_val;} public long Rv_as_long() {return num_val;}
public Decimal_adp Rv_as_dec() {return dec_val == null ? Decimal_adp_.long_(num_val) : dec_val;} private Decimal_adp dec_val = null; public Decimal_adp Rv_as_dec() {return dec_val == null ? Decimal_adp_.long_(num_val) : dec_val;} private Decimal_adp dec_val = null;
public boolean Is_int() {return dec_val == null && (num_val >= Int_.Min_value && num_val <= Int_.Max_value);} public boolean Is_int() {return dec_val == null && (num_val >= Int_.Min_value && num_val <= Int_.Max_value);}
public boolean Has_err() {return has_err;} private boolean has_err; public boolean Has_err() {return has_err;} private boolean has_err;
public boolean Has_frac() {return has_frac;} private boolean has_frac; public boolean Has_frac() {return has_frac;} private boolean has_frac;
public boolean Hex_enabled() {return hex_enabled;} public Gfo_number_parser Hex_enabled_(boolean v) {hex_enabled = v; return this;} private boolean hex_enabled; public boolean Hex_enabled() {return hex_enabled;} public Gfo_number_parser Hex_enabled_(boolean v) {hex_enabled = v; return this;} private boolean hex_enabled;
public Gfo_number_parser Ignore_chars_(byte[] v) {this.ignore_chars = v; return this;} private byte[] ignore_chars; public Gfo_number_parser Ignore_chars_(byte[] v) {this.ignore_chars = v; return this;} private byte[] ignore_chars;
public Gfo_number_parser Ignore_space_at_end_y_() {this.ignore_space_at_end = true; return this;} private boolean ignore_space_at_end; public Gfo_number_parser Ignore_space_at_end_y_() {this.ignore_space_at_end = true; return this;} private boolean ignore_space_at_end;
public void Clear() { public void Clear() {
ignore_chars = null; ignore_chars = null;
} }
@ -112,6 +119,7 @@ public class Gfo_number_parser {
has_exp = true; has_exp = true;
has_neg = false; has_neg = false;
has_plus = false; // allow +1E+2 has_plus = false; // allow +1E+2
has_num = false; // 2020-09-07|ISSUE#:795|scientific notation requires coefficient; set has_num to false which will fail below if no coefficient
} }
break; break;
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_A:

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,11 +13,18 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.core.primitives; import gplx.*; import gplx.core.*; package gplx.core.primitives;
import org.junit.*;
import gplx.Bry_;
import gplx.Decimal_adp;
import gplx.Decimal_adp_;
import gplx.Tfds;
import org.junit.Before;
import org.junit.Test;
public class Gfo_number_parser_tst { public class Gfo_number_parser_tst {
@Before public void init() {fxt.Clear();} private final Gfo_number_parser_fxt fxt = new Gfo_number_parser_fxt(); @Before public void init() {fxt.Clear();} private final Gfo_number_parser_fxt fxt = new Gfo_number_parser_fxt();
@Test public void Integer() { @Test public void Integer() {
fxt.Test_int("1", 1); fxt.Test_int("1", 1);
fxt.Test_int("1234", 1234); fxt.Test_int("1234", 1234);
fxt.Test_int("1234567890", 1234567890); fxt.Test_int("1234567890", 1234567890);
@ -25,25 +32,26 @@ public class Gfo_number_parser_tst {
fxt.Test_int("+1", 1); fxt.Test_int("+1", 1);
fxt.Test_int("00001", 1); fxt.Test_int("00001", 1);
} }
@Test public void Long() { @Test public void Long() {
fxt.Test_long("9876543210", 9876543210L); fxt.Test_long("9876543210", 9876543210L);
} }
@Test public void Decimal() { @Test public void Decimal() {
fxt.Test_dec("1.23", Decimal_adp_.parse("1.23")); fxt.Test_dec("1.23", Decimal_adp_.parse("1.23"));
fxt.Test_dec("1.023", Decimal_adp_.parse("1.023")); fxt.Test_dec("1.023", Decimal_adp_.parse("1.023"));
fxt.Test_dec("-1.23", Decimal_adp_.parse("-1.23")); fxt.Test_dec("-1.23", Decimal_adp_.parse("-1.23"));
} }
@Test public void Double_long() { @Test public void Double_long() {
fxt.Test_dec(".42190046219457", Decimal_adp_.parse(".42190046219457")); fxt.Test_dec(".42190046219457", Decimal_adp_.parse(".42190046219457"));
} }
@Test public void Exponent() { @Test public void Exponent() {
fxt.Test_int("1E2", 100); fxt.Test_int("1E2", 100);
fxt.Test_dec("1.234E2", Decimal_adp_.parse("123.4")); fxt.Test_dec("1.234E2", Decimal_adp_.parse("123.4"));
fxt.Test_dec("1.234E-2", Decimal_adp_.parse(".01234")); fxt.Test_dec("1.234E-2", Decimal_adp_.parse(".01234"));
fxt.Test_dec("123.4E-2", Decimal_adp_.parse("1.234")); fxt.Test_dec("123.4E-2", Decimal_adp_.parse("1.234"));
fxt.Test_dec("+6.0E-3", Decimal_adp_.parse(".006")); fxt.Test_dec("+6.0E-3", Decimal_adp_.parse(".006"));
fxt.Test_err("e24", true); // 2020-09-07|ISSUE#:795|scientific notation requires coefficient
} }
@Test public void Err() { @Test public void Err() {
fxt.Test_err("+", true); fxt.Test_err("+", true);
fxt.Test_err("-", true); fxt.Test_err("-", true);
fxt.Test_err("a", true); fxt.Test_err("a", true);
@ -52,14 +60,14 @@ public class Gfo_number_parser_tst {
fxt.Test_err("1,,1", true); fxt.Test_err("1,,1", true);
fxt.Test_err("1", false); fxt.Test_err("1", false);
} }
@Test public void Hex() { @Test public void Hex() {
fxt.Test_hex("0x1" , 1); fxt.Test_hex("0x1" , 1);
fxt.Test_hex("0xF" , 15); fxt.Test_hex("0xF" , 15);
fxt.Test_hex("0x20" , 32); fxt.Test_hex("0x20" , 32);
fxt.Test_hex("x20" , 0, false); fxt.Test_hex("x20" , 0, false);
fxt.Test_hex("d" , 0, false); // PURPOSE: d was being converted to 13; no.w:Hovedbanen; DATE:2014-04-13 fxt.Test_hex("d" , 0, false); // PURPOSE: d was being converted to 13; no.w:Hovedbanen; DATE:2014-04-13
} }
@Test public void Ignore() { @Test public void Ignore() {
fxt.Init_ignore("\n\t"); fxt.Init_ignore("\n\t");
fxt.Test_int("1" , 1); fxt.Test_int("1" , 1);
fxt.Test_int("1\n" , 1); fxt.Test_int("1\n" , 1);
@ -69,7 +77,7 @@ public class Gfo_number_parser_tst {
} }
} }
class Gfo_number_parser_fxt { class Gfo_number_parser_fxt {
private final Gfo_number_parser parser = new Gfo_number_parser(); private final Gfo_number_parser parser = new Gfo_number_parser();
public void Clear() {parser.Clear();} public void Clear() {parser.Clear();}
public void Init_ignore(String chars) {parser.Ignore_chars_(Bry_.new_a7(chars));} public void Init_ignore(String chars) {parser.Ignore_chars_(Bry_.new_a7(chars));}
public void Test_int(String raw, int expd) { public void Test_int(String raw, int expd) {

View File

@ -0,0 +1,46 @@
package gplx.core.serials.binarys;
import gplx.Bry_;
import gplx.core.serials.core.SerialLoadMgr;
import gplx.core.serials.core.SerialLoadWkr;
import gplx.core.texts.Base64Converter;
public class BinaryLoadMgr implements SerialLoadMgr {
public static final int CORE_VERSION = 0;
private byte[] data;
private int headerEnd;
private int dataVersion;
@Override
public int CoreVersion() {
return CORE_VERSION;
}
@Override
public int DataVersion() {return dataVersion;}
@Override
public void ReadHeader(byte[] data) {
this.data = data;
this.dataVersion = Base64Converter.GetIndexInt((char)data[1]);
this.headerEnd = 3; // 1=coreVersion; 2=dataVersion; 3=\n
}
@Override
public byte[] Data() {
return data;
}
@Override
public int HeaderEnd() {
return headerEnd;
}
@Override
public SerialLoadWkr NewLoadWkr() {
return new BinaryLoadWkr().Ctor(this);
}
public byte[] FldDlm() {return fldDlm;} private final byte[] fldDlm = Bry_.new_a7("|");
public byte[] RowDlm() {return rowDlm;} private final byte[] rowDlm = Bry_.new_a7("\n");
}

View File

@ -0,0 +1,75 @@
package gplx.core.serials.binarys;
import gplx.Bry_;
import gplx.Bry_find_;
import gplx.Err_;
import gplx.String_;
import gplx.core.serials.core.SerialLoadMgr;
import gplx.core.serials.core.SerialLoadWkr;
public class BinaryLoadWkr implements SerialLoadWkr {
private BinaryLoadMgr mgr;
private byte[] fldDlm;
private byte[] rowDlm;
private byte[] src;
private int srcLen;
private int cur;
@Override
public SerialLoadWkr Ctor(SerialLoadMgr mgrObj) {
this.mgr = (BinaryLoadMgr)mgrObj;
this.fldDlm = mgr.FldDlm();
this.rowDlm = mgr.RowDlm();
return this;
}
@Override
public void Init(byte[] src, int cur) {
this.src = src;
this.srcLen = src.length;
this.cur = cur;
}
@Override
public String LoadStr() {
return String_.new_u8(LoadBry());
}
@Override
public int LoadInt() {
return LoadInt(rowDlm);
}
@Override
public byte[] LoadBry() {
int bryLen = LoadInt(fldDlm);
// extract bry
int bryBgn = cur;
int bryEnd = bryBgn + bryLen;
if (bryEnd > srcLen) {
throw Err_.new_wo_type(String_.Format("End position is out of bounds; src={0} currentPosition={1} byteArrayLength={2} remainder={3}", src, cur, bryLen, Bry_.Mid(src, bryBgn, bryEnd)));
}
cur = bryEnd + rowDlm.length;
return Bry_.Mid(src, bryBgn, bryEnd);
}
private int LoadInt(byte[] dlm) {
int bgn = cur;
// find position of delimiter
int end = Bry_find_.Find_fwd(src, dlm, cur, srcLen);
if (end == Bry_find_.Not_found) {
throw Err_.new_wo_type(String_.Format("Failed to find delimiter for integer's end position; src={0} currentPosition={1} delimiter={2}", src, cur, fldDlm));
}
cur = end + dlm.length;
// parse int
int val = Bry_.To_int_or(src, bgn, end, -1);
if (val == -1) {
throw Err_.new_wo_type(String_.Format("Failed to parse integer; src={0} currentPosition={1} string={2}", src, cur, Bry_.Mid(src, bgn, end)));
}
return val;
}
}

View File

@ -0,0 +1,16 @@
package gplx.core.serials.binarys;
import gplx.Bry_;
import gplx.core.serials.core.SerialSaveMgr;
import gplx.core.serials.core.SerialSaveWkr;
public class BinarySaveMgr implements SerialSaveMgr {
public int CoreVersion() {return BinaryLoadMgr.CORE_VERSION;}
public byte[] FldDlm() {return fldDlm;} private final byte[] fldDlm = Bry_.new_a7("|");
public byte[] RowDlm() {return rowDlm;} private final byte[] rowDlm = Bry_.new_a7("\n");
@Override
public SerialSaveWkr NewSaveWkr() {
return new BinarySaveWkr().Ctor(this);
}
}

View File

@ -0,0 +1,60 @@
package gplx.core.serials.binarys;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.core.serials.core.SerialSaveMgr;
import gplx.core.serials.core.SerialSaveWkr;
import gplx.core.texts.Base64Converter;
public class BinarySaveWkr implements SerialSaveWkr {
private byte[] fldDlm;
private byte[] rowDlm;
private BinarySaveMgr mgr;
private final Bry_bfr bfr = Bry_bfr_.New();
@Override
public SerialSaveWkr Ctor(SerialSaveMgr mgrObj) {
this.mgr = (BinarySaveMgr)mgrObj;
this.fldDlm = mgr.FldDlm();
this.rowDlm = mgr.RowDlm();
return this;
}
@Override
public void Init() {
bfr.Clear();
}
@Override
public void SaveHdr(int dataVersion) {
// EX: AA -> SerialCoreMgrID+DataVersionID
bfr.Add_byte((byte)Base64Converter.GetIndexChar(mgr.CoreVersion()));
bfr.Add_byte((byte)Base64Converter.GetIndexChar(dataVersion)).Add(rowDlm);
}
@Override
public void SaveInt(int val) {
SaveInt(val, rowDlm);
}
@Override
public void SaveStr(String val) {
this.SaveBry(Bry_.new_u8(val));
}
@Override
public void SaveBry(byte[] val) {
SaveInt(val.length, fldDlm);
bfr.Add(val).Add(rowDlm);
}
private void SaveInt(int val, byte[] dlm) {
bfr.Add_int_variable(val).Add(dlm);
}
@Override
public byte[] ToBry() {
return bfr.To_bry();
}
}

View File

@ -0,0 +1,24 @@
package gplx.core.serials.core;
import gplx.Err_;
import gplx.core.serials.binarys.BinaryLoadMgr;
import gplx.core.serials.binarys.BinarySaveMgr;
import gplx.core.texts.Base64Converter;
public class SerialCoreFactory {
public static SerialSaveMgr NewSaveMgr(int coreVersion) {
if (coreVersion == BinaryLoadMgr.CORE_VERSION) {
return new BinarySaveMgr();
}
throw Err_.new_unhandled_default(coreVersion);
}
public static SerialLoadMgr NewLoadMgr(byte[] data) {
int coreVersion = Base64Converter.GetIndexInt((char)data[0]);
if (coreVersion == BinaryLoadMgr.CORE_VERSION) {
BinaryLoadMgr loadMgr = new BinaryLoadMgr();
loadMgr.ReadHeader(data);
return loadMgr;
}
throw Err_.new_unhandled_default(coreVersion);
}
}

View File

@ -0,0 +1,10 @@
package gplx.core.serials.core;
public interface SerialLoadMgr {
int CoreVersion();
int DataVersion();
SerialLoadWkr NewLoadWkr();
void ReadHeader(byte[] data);
byte[] Data();
int HeaderEnd();
}

View File

@ -0,0 +1,9 @@
package gplx.core.serials.core;
public interface SerialLoadWkr {
SerialLoadWkr Ctor(SerialLoadMgr mgr);
void Init(byte[] src, int cur);
int LoadInt();
byte[] LoadBry();
String LoadStr();
}

View File

@ -0,0 +1,6 @@
package gplx.core.serials.core;
public interface SerialSaveMgr {
int CoreVersion();
SerialSaveWkr NewSaveWkr();
}

View File

@ -0,0 +1,11 @@
package gplx.core.serials.core;
public interface SerialSaveWkr {
SerialSaveWkr Ctor(SerialSaveMgr mgr);
void Init();
void SaveHdr(int dataVersion);
void SaveInt(int val);
void SaveStr(String val);
void SaveBry(byte[] val);
byte[] ToBry();
}

View File

@ -81,8 +81,8 @@ public class Gfh_tag_ { // NOTE: not serialized; used by tag_rdr
, Id__rp = 59 , Id__rp = 59
, Id__rt = 60 , Id__rt = 60
, Id__form = 61 , Id__form = 61
, Id__mark = 62
; ;
// private static final int Id__ary_max = 60;
public static final byte[] public static final byte[]
Bry__a = Bry_.new_a7("a") Bry__a = Bry_.new_a7("a")
, Bry__ul = Bry_.new_a7("ul") , Bry__ul = Bry_.new_a7("ul")
@ -167,6 +167,7 @@ public class Gfh_tag_ { // NOTE: not serialized; used by tag_rdr
.Add_str_int("rp" , Id__rp) .Add_str_int("rp" , Id__rp)
.Add_str_int("rt" , Id__rt) .Add_str_int("rt" , Id__rt)
.Add_str_int("form" , Id__form) .Add_str_int("form" , Id__form)
.Add_str_int("mark" , Id__mark)
; ;
public static String To_str(int tid) { public static String To_str(int tid) {
switch (tid) { switch (tid) {
@ -235,6 +236,7 @@ public class Gfh_tag_ { // NOTE: not serialized; used by tag_rdr
case Id__rp: return "rp"; case Id__rp: return "rp";
case Id__rt: return "rt"; case Id__rt: return "rt";
case Id__form: return "form"; case Id__form: return "form";
case Id__mark: return "mark";
default: throw Err_.new_unhandled(tid); default: throw Err_.new_unhandled(tid);
} }
} }

View File

@ -25,6 +25,7 @@ public class Gfh_tag_rdr {
public byte[] Src() {return src;} private byte[] src; public byte[] Src() {return src;} private byte[] src;
public int Src_end() {return src_end;} private int src_end; public int Src_end() {return src_end;} private int src_end;
public Bry_err_wkr Err_wkr() {return err_wkr;} private final Bry_err_wkr err_wkr = new Bry_err_wkr(); public Bry_err_wkr Err_wkr() {return err_wkr;} private final Bry_err_wkr err_wkr = new Bry_err_wkr();
public Gfh_tag_rdr Skip_ws_after_slash_y_() {skip_ws_after_slash_y = true; return this;} private boolean skip_ws_after_slash_y;
public Gfh_tag_rdr Reg(String tag_name, int tag_id) {name_hash.Add_str_int(tag_name, tag_id); return this;} public Gfh_tag_rdr Reg(String tag_name, int tag_id) {name_hash.Add_str_int(tag_name, tag_id); return this;}
public Gfh_tag_rdr Init(byte[] ctx_name, byte[] src, int src_bgn, int src_end) { public Gfh_tag_rdr Init(byte[] ctx_name, byte[] src, int src_bgn, int src_end) {
this.src = src; this.pos = src_bgn; this.src_end = src_end; this.src = src; this.pos = src_bgn; this.src_end = src_end;
@ -205,6 +206,9 @@ public class Gfh_tag_rdr {
case Byte_ascii.Slash: // EX: "<a/>" case Byte_ascii.Slash: // EX: "<a/>"
name_end = name_pos; name_end = name_pos;
tag_end = name_pos + 1; if (tag_end == src_end) return Tag__eos(tag_bgn);// EX: "<a/EOS" tag_end = name_pos + 1; if (tag_end == src_end) return Tag__eos(tag_bgn);// EX: "<a/EOS"
if (skip_ws_after_slash_y) {// skip ws after slash; EX:"<br />"; ISSUE#:542: DATE:2020-03-09
tag_end = Bry_find_.Find_fwd_while_ws(src, tag_end, src_end);
}
if (src[tag_end] == Byte_ascii.Angle_end) { if (src[tag_end] == Byte_ascii.Angle_end) {
atrs_end = name_end; atrs_end = name_end;
inline = true; inline = true;
@ -267,6 +271,9 @@ public class Gfh_tag_rdr {
case Byte_ascii.Slash: // EX: "<a/>" case Byte_ascii.Slash: // EX: "<a/>"
name_end = name_pos; name_end = name_pos;
tag_end = name_pos + 1; if (tag_end == src_end) return Tag__eos(tag_bgn);// EX: "<a/EOS" tag_end = name_pos + 1; if (tag_end == src_end) return Tag__eos(tag_bgn);// EX: "<a/EOS"
if (skip_ws_after_slash_y) {// skip ws after slash; EX:"<br />"; ISSUE#:542: DATE:2020-03-09
tag_end = Bry_find_.Find_fwd_while_ws(src, tag_end, src_end);
}
if (src[tag_end] == Byte_ascii.Angle_end) { if (src[tag_end] == Byte_ascii.Angle_end) {
atrs_end = name_end; atrs_end = name_end;
inline = true; inline = true;

View File

@ -0,0 +1,157 @@
package gplx.langs.javascripts;
import gplx.Err_;
import gplx.String_;
import gplx.langs.javascripts.util.regex.JsPattern_;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class JsString_ {
public static boolean charAtEq(String s, int i, char m) {
int len = s.length();
if (i < 0 || i >= len) {
return false;
} else {
return s.charAt(i) == m;
}
}
public static boolean charAtEqNot(String s, int i, char m) {
int len = s.length();
if (i < 0 || i >= len) {
return false;
} else {
return s.charAt(i) != m;
}
}
public static String charAt(String s, int i) {
int len = s.length();
if (i < 0 || i >= len) {
return String_.Empty;
} else {
return Character.toString(s.charAt(i));
}
}
public static String slice(String str, int beginIndex) {
return slice(str, beginIndex, str.length());
}
// REF.JOS:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
public static String slice(String str, int beginIndex, int endIndex) {
int srcLen = str.length();
// bgn
if (beginIndex < 0) {
beginIndex = srcLen + beginIndex;
if (beginIndex < 0) {
beginIndex = 0;
}
}
else if (beginIndex > srcLen) {
return "";
}
// end
if (endIndex < 0) {
endIndex = srcLen + endIndex;
if (endIndex < 0) {
endIndex = 0;
}
}
else if (endIndex > srcLen) {
endIndex = srcLen;
}
if (endIndex < beginIndex) {
return "";
}
return str.substring(beginIndex, endIndex);
}
private static final int
REPLACE_TYPE_STR = 0
, REPLACE_TYPE_MATCHER = 1
, REPLACE_TYPE_ARG1 = 2
, REPLACE_TYPE_ARG2 = 3
, REPLACE_TYPE_ARG3 = 4
;
public interface JsStringReplaceArg1 {
String processMatcher(String all);
}
public interface JsStringReplaceArg2 {
String processMatcher(String all, String arg1);
}
public interface JsStringReplaceArg3 {
String processMatcher(String all, String arg1, String arg2);
}
public interface JsStringReplaceMatcher {
String processMatcher(Matcher m);
}
public static String replace(String s, ConcurrentHashMap<String, Pattern> map, String p, String repl) {
return replace(s, map, p, JsPattern_.NONE, repl);
}
public static String replace(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, String repl) {
return replaceObject(src, map, pat, patFlags, repl, REPLACE_TYPE_STR);
}
public static String replaceArg1(String src, ConcurrentHashMap<String, Pattern> map, String pat, JsStringReplaceArg1 func) {
return replaceObject(src, map, pat, JsPattern_.NONE, func, REPLACE_TYPE_ARG1);
}
public static String replaceArg1(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, JsStringReplaceArg1 func) {
return replaceObject(src, map, pat, patFlags, func, REPLACE_TYPE_ARG1);
}
public static String replaceArg2(String src, ConcurrentHashMap<String, Pattern> map, String pat, JsStringReplaceArg2 func) {
return replaceObject(src, map, pat, JsPattern_.NONE, func, REPLACE_TYPE_ARG2);
}
public static String replaceArg2(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, JsStringReplaceArg2 func) {
return replaceObject(src, map, pat, patFlags, func, REPLACE_TYPE_ARG2);
}
public static String replaceArg3(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, JsStringReplaceArg3 func) {
return replaceObject(src, map, pat, patFlags, func, REPLACE_TYPE_ARG3);
}
public static String replaceMatcher(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, JsStringReplaceMatcher func) {
return replaceObject(src, map, pat, patFlags, func, REPLACE_TYPE_MATCHER);
}
private static String replaceObject(String src, ConcurrentHashMap<String, Pattern> map, String pat, int patFlags, Object replObj, int replType) {
Pattern pattern = JsPattern_.getOrCompile(map, pat, patFlags);
// match
Matcher m = pattern.matcher(src);
StringBuffer sb = null;
while (m.find()) {
// get repl
String repl = null;
switch (replType) {
case REPLACE_TYPE_STR:
repl = (String)replObj;
break;
case REPLACE_TYPE_MATCHER:
repl = ((JsStringReplaceMatcher)replObj).processMatcher(m);
break;
case REPLACE_TYPE_ARG1:
repl = ((JsStringReplaceArg1)replObj).processMatcher(m.group(0));
break;
case REPLACE_TYPE_ARG2:
repl = ((JsStringReplaceArg2)replObj).processMatcher(m.group(0), m.group(1));
break;
case REPLACE_TYPE_ARG3:
repl = ((JsStringReplaceArg3)replObj).processMatcher(m.group(0), m.group(1), m.group(2));
break;
default:
throw Err_.new_unhandled_default(replType);
}
if (sb == null) {
sb = new StringBuffer();
}
m.appendReplacement(sb, repl);
}
// return
if (sb != null) {
m.appendTail(sb);
return sb.toString();
}
else {
return src;
}
}
}

View File

@ -0,0 +1,18 @@
package gplx.langs.javascripts.util.regex;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
public class JsPattern_ {
public static final int NONE = 0;
public static Pattern getOrCompile(ConcurrentHashMap<String, Pattern> map, String pat) {return getOrCompile(map, pat, NONE);}
public static Pattern getOrCompile(ConcurrentHashMap<String, Pattern> map, String pat, int patFlags) {
// get pattern
Pattern pattern = map.get(pat);
if (pattern == null) {
pattern = Pattern.compile(pat, patFlags);
map.put(pat, pattern);
}
return pattern;
}
}

View File

@ -0,0 +1,69 @@
/*
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.langs.jsons;
import gplx.Bry_;
import gplx.List_adp;
import gplx.List_adp_;
import gplx.String_;
public class JsonDocBldr {
private final List_adp stack = List_adp_.New();
private final Json_doc doc = new Json_doc();
private Json_grp root;
private Json_grp cur;
JsonDocBldr() {}
public JsonDocBldr Clear(boolean isRootNode) {
this.root = isRootNode ? Json_nde.NewByDoc(doc, 0) : Json_ary.NewByDoc(doc, 0, 0);
doc.Ctor(Bry_.Empty, root);
this.cur = root;
stack.Clear();
return this;
}
public JsonDocBldr NdeBgn(String key) {
Json_nde nde = Json_nde.NewByDoc(doc, 1);
if (cur.Tid() == Json_itm_.Tid__nde) {
Json_kv kv = new Json_kv(Json_itm_str.NewByVal(key), nde);
cur.Add(kv);
}
else {
cur.Add(nde);
}
stack.Add(cur);
cur = nde;
return this;
}
public JsonDocBldr NdeEnd() {
this.cur = (Json_grp)List_adp_.Pop_last(stack);
return this;
}
public JsonDocBldr KvBool(String key, boolean val) {return Kv(key, Json_itm_bool.Get(val));}
public JsonDocBldr KvInt(String key, int val) {return Kv(key, Json_itm_int.NewByVal(val));}
public JsonDocBldr KvStr(String key, byte[] val) {return Kv(key, Json_itm_str.NewByVal(String_.new_u8(val)));}
public JsonDocBldr KvStr(String key, String val) {return Kv(key, Json_itm_str.NewByVal(val));}
private JsonDocBldr Kv(String key, Json_itm val) {
Json_kv rv = new Json_kv(Json_itm_str.NewByVal(key), val);
cur.Add(rv);
return this;
}
public Json_doc ToDoc() {
return doc;
}
public Json_nde ToRootNde() {
return doc.Root_nde();
}
public static JsonDocBldr NewRootNde() {return new JsonDocBldr().Clear(true);}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,11 +13,18 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Array_;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Byte_ascii;
import gplx.Err_;
public class Json_ary extends Json_itm_base implements Json_grp { public class Json_ary extends Json_itm_base implements Json_grp {
public Json_ary(int src_bgn, int src_end) {this.Ctor(src_bgn, src_end);} private Json_ary() {}
@Override public byte Tid() {return Json_itm_.Tid__ary;} @Override public byte Tid() {return Json_itm_.Tid__ary;}
public void Src_end_(int v) {this.src_end = v;} public void Src_end_(int v) {}
@Override public Object Data() {return null;} @Override public Object Data() {return null;}
@Override public byte[] Data_bry() {return null;} @Override public byte[] Data_bry() {return null;}
public int Len() {return subs_len;} private int subs_len = 0, subs_max = 0; public int Len() {return subs_len;} private int subs_len = 0, subs_max = 0;
@ -26,7 +33,7 @@ public class Json_ary extends Json_itm_base implements Json_grp {
return (Json_nde)rv; return (Json_nde)rv;
} }
public Json_itm Get_at(int i) {return subs[i];} public Json_itm Get_at(int i) {return subs[i];}
public Json_nde Get_as_nde(int i) {return Json_nde.cast(subs[i]);} public Json_nde Get_as_nde(int i) {return Json_nde.Cast(subs[i]);}
public Json_ary Add_many(Json_itm... ary) { public Json_ary Add_many(Json_itm... ary) {
int len = ary.length; int len = ary.length;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
@ -75,4 +82,6 @@ public class Json_ary extends Json_itm_base implements Json_grp {
if (v == null || v.Tid() != Json_itm_.Tid__ary) throw Err_.new_("json", "itm is not array"); if (v == null || v.Tid() != Json_itm_.Tid__ary) throw Err_.new_("json", "itm is not array");
return (Json_ary)v; return (Json_ary)v;
} }
public static Json_ary NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_ary();}
public static Json_ary NewByVal() {return new Json_ary();}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,10 +13,17 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.core.primitives.*;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Err_;
import gplx.String_;
import gplx.core.primitives.Gfo_number_parser;
public class Json_doc { public class Json_doc {
private final byte[][] tmp_qry_bry = new byte[1][]; private final byte[][] tmp_qry_bry = new byte[1][];
public void Ctor(byte[] src, Json_grp new_root) { public void Ctor(byte[] src, Json_grp new_root) {
this.src = src; this.src = src;
this.root_grp = new_root; this.root_grp = new_root;
@ -30,9 +37,9 @@ public class Json_doc {
public Json_grp Root_grp() {return root_grp;} private Json_grp root_grp; public Json_grp Root_grp() {return root_grp;} private Json_grp root_grp;
public Json_nde Root_nde() {return root_nde;} private Json_nde root_nde; public Json_nde Root_nde() {return root_nde;} private Json_nde root_nde;
public Json_ary Root_ary() {return root_ary;} private Json_ary root_ary; public Json_ary Root_ary() {return root_ary;} private Json_ary root_ary;
public Bry_bfr Bfr() {return bfr;} private final Bry_bfr bfr = Bry_bfr_.New(); public Bry_bfr Bfr() {return bfr;} private final Bry_bfr bfr = Bry_bfr_.New();
public Gfo_number_parser Utl_num_parser() {return utl_num_parser;} private final Gfo_number_parser utl_num_parser = new Gfo_number_parser(); public Gfo_number_parser Utl_num_parser() {return utl_num_parser;} private final Gfo_number_parser utl_num_parser = new Gfo_number_parser();
public byte[] Tmp_u8_bry() {return tmp_u8_bry;} private final byte[] tmp_u8_bry = new byte[6]; // tmp bry[] for decoding sequences like \u0008 public byte[] Tmp_u8_bry() {return tmp_u8_bry;} private final byte[] tmp_u8_bry = new byte[6]; // tmp bry[] for decoding sequences like \u0008
public byte[] Get_val_as_bry_or(byte[] qry_bry, byte[] or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_bry_or(tmp_qry_bry, or);} public byte[] Get_val_as_bry_or(byte[] qry_bry, byte[] or) {tmp_qry_bry[0] = qry_bry; return Get_val_as_bry_or(tmp_qry_bry, or);}
public byte[] Get_val_as_bry_or(byte[][] qry_bry, byte[] or) { public byte[] Get_val_as_bry_or(byte[][] qry_bry, byte[] or) {
Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0); Json_itm nde = Find_nde(root_nde, qry_bry, qry_bry.length - 1, 0);
@ -66,10 +73,10 @@ public class Json_doc {
byte[] path = paths[paths_idx]; byte[] path = paths[paths_idx];
int subs_len = owner.Len(); int subs_len = owner.Len();
for (int i = 0; i < subs_len; i++) { for (int i = 0; i < subs_len; i++) {
Json_kv itm = Json_kv.cast(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes Json_kv itm = Json_kv.Cast(owner.Get_at(i)); if (itm == null) continue; // ignore simple props, arrays, ndes
if (!itm.Key_eq(path)) continue; if (!itm.Key_eq(path)) continue;
if (paths_idx == paths_last) return itm.Val(); if (paths_idx == paths_last) return itm.Val();
Json_nde sub_nde = Json_nde.cast(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit Json_nde sub_nde = Json_nde.Cast(itm.Val()); if (sub_nde == null) return null; // match, but has not a nde; exit
return Find_nde(sub_nde, paths, paths_last, paths_idx + 1); return Find_nde(sub_nde, paths, paths_last, paths_idx + 1);
} }
return null; return null;

View File

@ -1,40 +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.langs.jsons; import gplx.*; import gplx.langs.*;
public class Json_doc_bldr {
public Json_nde Nde(Json_doc jdoc) {return factory.Nde(jdoc, -1);}
public Json_nde Nde(Json_doc jdoc, Json_grp owner) {
Json_nde rv = factory.Nde(jdoc, -1);
owner.Add(rv);
return rv;
}
public Json_itm Str(byte[] v) {return Str(String_.new_u8(v));}
public Json_itm Str(String v) {return Json_itm_tmp.new_str_(v);}
public Json_itm Int(int v) {return Json_itm_tmp.new_int_(v);}
public Json_kv Kv_int(Json_grp owner, String key, int val) {Json_kv rv = factory.Kv(Json_itm_tmp.new_str_(key), Json_itm_tmp.new_int_(val)); owner.Add(rv); return rv;}
public Json_kv Kv_str(Json_grp owner, String key, String val) {Json_kv rv = factory.Kv(Json_itm_tmp.new_str_(key), Json_itm_tmp.new_str_(val)); owner.Add(rv); return rv;}
public Json_ary Kv_ary(Json_grp owner, String key, Json_itm... subs) {
Json_itm key_itm = Json_itm_tmp.new_str_(key);
Json_ary val_ary = factory.Ary(-1, -1);
Json_kv kv = factory.Kv(key_itm, val_ary);
owner.Add(kv);
int len = subs.length;
for (int i = 0; i < len; i++)
val_ary.Add(subs[i]);
return val_ary;
}
Json_doc doc = new Json_doc(); Json_factory factory = new Json_factory();
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,9 +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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.objects.strings.unicodes.*;
import gplx.core.encoders.*; import gplx.Bool_;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Byte_ascii;
import gplx.Double_;
import gplx.Object_;
import gplx.String_;
import gplx.core.encoders.Hex_utl_;
import gplx.objects.strings.unicodes.Ustring;
import gplx.objects.strings.unicodes.Ustring_;
public class Json_doc_wtr { public class Json_doc_wtr {
private int indent = -2; private int indent = -2;
private Bry_bfr bfr = Bry_bfr_.Reset(255); private Bry_bfr bfr = Bry_bfr_.Reset(255);
@ -96,6 +107,7 @@ public class Json_doc_wtr {
bfr.Add_byte_nl(); bfr.Add_byte_nl();
return this; return this;
} }
public Json_doc_wtr Kv(boolean comma, String key, byte[] val) {return Kv(comma, Bry_.new_u8(key), val);}
public Json_doc_wtr Kv(boolean comma, byte[] key, byte[] val) { public Json_doc_wtr Kv(boolean comma, byte[] key, byte[] val) {
Key_internal(comma, key); Key_internal(comma, key);
Str(val); Str(val);
@ -108,12 +120,15 @@ public class Json_doc_wtr {
bfr.Add_byte_nl(); bfr.Add_byte_nl();
return this; return this;
} }
public Json_doc_wtr Kv(boolean comma, String key, int v) {return Kv(comma, Bry_.new_u8(key), v);}
public Json_doc_wtr Kv(boolean comma, byte[] key, int v) { public Json_doc_wtr Kv(boolean comma, byte[] key, int v) {
Key_internal(comma, key); Key_internal(comma, key);
Int(v); Int(v);
bfr.Add_byte_nl(); bfr.Add_byte_nl();
return this; return this;
} }
public Json_doc_wtr Kv(boolean comma, String key, double v) {return Kv(comma, Bry_.new_u8(key), Bry_.new_u8(Double_.To_str(v)));}
public Json_doc_wtr Kv(boolean comma, String key, boolean v) {return Kv(comma, Bry_.new_u8(key), v ? Bool_.Y_bry : Bool_.N_bry);}
public Json_doc_wtr Key(boolean comma, String key) {return Key(comma, Bry_.new_u8(key));} public Json_doc_wtr Key(boolean comma, String key) {return Key(comma, Bry_.new_u8(key));}
public Json_doc_wtr Key(boolean comma, byte[] key) { public Json_doc_wtr Key(boolean comma, byte[] key) {
Key_internal(comma, key); Key_internal(comma, key);
@ -148,5 +163,5 @@ public class Json_doc_wtr {
} }
public byte[] Bld() {return bfr.To_bry_and_clear();} public byte[] Bld() {return bfr.To_bry_and_clear();}
public String Bld_as_str() {return bfr.To_str_and_clear();} public String Bld_as_str() {return bfr.To_str_and_clear();}
private static final byte[] Escaped__quote = Bry_.new_a7("\\\""); private static final byte[] Escaped__quote = Bry_.new_a7("\\\"");
} }

View File

@ -1,28 +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.langs.jsons; import gplx.*; import gplx.langs.*;
public class Json_factory {
public Json_itm Null() {return Json_itm_null.Null;}
public Json_itm Bool_n() {return Json_itm_bool.Bool_n;}
public Json_itm Bool_y() {return Json_itm_bool.Bool_y;}
public Json_itm_int Int(Json_doc doc, int bgn, int end) {return new Json_itm_int(doc, bgn, end);}
public Json_itm_long Long(Json_doc doc, int bgn, int end) {return new Json_itm_long(doc, bgn, end);}
public Json_itm Decimal(Json_doc doc, int bgn, int end) {return new Json_itm_decimal(doc, bgn, end);}
public Json_itm Str(Json_doc doc, int bgn, int end, boolean exact) {return new Json_itm_str(doc, bgn, end, exact);}
public Json_kv Kv(Json_itm key, Json_itm val) {return new Json_kv(key, val);}
public Json_ary Ary(int bgn, int end) {return new Json_ary(bgn, end);}
public Json_nde Nde(Json_doc doc, int bgn) {return new Json_nde(doc, bgn);}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,21 +13,23 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_bfr;
import gplx.Object_;
public interface Json_itm { public interface Json_itm {
byte Tid(); byte Tid();
int Src_bgn(); Object Data();
int Src_end(); byte[] Data_bry();
Object Data(); boolean Data_eq(byte[] comp);
byte[] Data_bry(); void Print_as_json(Bry_bfr bfr, int depth);
void Print_as_json(Bry_bfr bfr, int depth);
boolean Data_eq(byte[] comp);
} }
class Json_itm_null extends Json_itm_base { class Json_itm_null extends Json_itm_base {
Json_itm_null() {this.Ctor(-1, -1);} Json_itm_null() {}
@Override public byte Tid() {return Json_itm_.Tid__null;} @Override public byte Tid() {return Json_itm_.Tid__null;}
@Override public Object Data() {return null;} @Override public Object Data() {return null;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Object_.Bry__null);} @Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(Object_.Bry__null);}
@Override public byte[] Data_bry() {return Object_.Bry__null;} @Override public byte[] Data_bry() {return Object_.Bry__null;}
public static final Json_itm_null Null = new Json_itm_null(); public static final Json_itm_null Null = new Json_itm_null();
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,15 +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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
public abstract class Json_itm_base implements Json_itm { public abstract class Json_itm_base implements Json_itm {
public abstract byte Tid(); public abstract byte Tid();
public void Ctor(int src_bgn, int src_end) {this.src_bgn = src_bgn; this.src_end = src_end;}
public int Src_bgn() {return src_bgn;} private int src_bgn;
public int Src_end() {return src_end;} protected int src_end;
public abstract Object Data(); public abstract Object Data();
public abstract byte[] Data_bry(); public abstract byte[] Data_bry();
public String Print_as_json() {Bry_bfr bfr = Bry_bfr_.New(); Print_as_json(bfr, 0); return bfr.To_str_and_clear();} public String Print_as_json() {
Bry_bfr bfr = Bry_bfr_.New();
Print_as_json(bfr, 0);
return bfr.To_str_and_clear();
}
public abstract void Print_as_json(Bry_bfr bfr, int depth); public abstract void Print_as_json(Bry_bfr bfr, int depth);
@gplx.Virtual public boolean Data_eq(byte[] comp) {return false;} @gplx.Virtual public boolean Data_eq(byte[] comp) {return false;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,14 +13,22 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_bfr;
public class Json_itm_bool extends Json_itm_base { public class Json_itm_bool extends Json_itm_base {
private boolean data; private boolean data;
public Json_itm_bool(boolean data) {this.data = data; this.Ctor(-1, -1);} private Json_itm_bool(boolean data) {
this.data = data;
}
@Override public byte Tid() {return Json_itm_.Tid__bool;} @Override public byte Tid() {return Json_itm_.Tid__bool;}
public boolean Data_as_bool() {return data;} public boolean Data_as_bool() {return data;}
@Override public Object Data() {return data;} @Override public Object Data() {return data;}
@Override public byte[] Data_bry() {return data ? Json_itm_.Bry__true : Json_itm_.Bry__false;} @Override public byte[] Data_bry() {return data ? Json_itm_.Bry__true : Json_itm_.Bry__false;}
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Bry__true: Json_itm_.Bry__false);} @Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add(data ? Json_itm_.Bry__true: Json_itm_.Bry__false);}
public static final Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
public static final Json_itm_bool Bool_n = new Json_itm_bool(false), Bool_y = new Json_itm_bool(true);
public static final Json_itm_bool Get(boolean v) {return v ? Bool_y : Bool_n;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,20 +13,54 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Decimal_adp;
import gplx.Decimal_adp_;
import gplx.Double_;
import gplx.String_;
public class Json_itm_decimal extends Json_itm_base { public class Json_itm_decimal extends Json_itm_base {
private final Json_doc doc; private Decimal_adp data; private byte[] data_bry; private final Json_doc doc;
public Json_itm_decimal(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;} private final int src_bgn, src_end;
private Decimal_adp data;
private byte[] data_bry;
private Json_itm_decimal(Json_doc doc, int src_bgn, int src_end, Decimal_adp data) {
this.doc = doc;
this.src_bgn = src_bgn;
this.src_end = src_end;
this.data = data;
}
@Override public byte Tid() {return Json_itm_.Tid__decimal;} @Override public byte Tid() {return Json_itm_.Tid__decimal;}
@Override public Object Data() {return this.Data_as_decimal();} @Override public Object Data() {return this.Data_as_decimal();}
@Override public byte[] Data_bry() { @Override public byte[] Data_bry() {
if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); if (data_bry == null) {
data_bry = data == null
? Bry_.Mid(doc.Src(), src_bgn, src_end)
: Bry_.new_u8(Double_.To_str_loose(data.To_double()));
}
return data_bry; return data_bry;
} }
public Decimal_adp Data_as_decimal() { public Decimal_adp Data_as_decimal() {
if (data == null) if (data == null) {
data = Decimal_adp_.parse(String_.new_a7(this.Data_bry())); String s = String_.new_a7(this.Data_bry());
s = String_.Replace(s, "e", "E"); // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
data = Decimal_adp_.parse(s);
}
return data; return data;
} }
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());} @Override public void Print_as_json(Bry_bfr bfr, int depth) {
if (doc == null) {
bfr.Add_str_a7(Double_.To_str_loose(data.To_double()));
}
else {
bfr.Add_mid(doc.Src(), src_bgn, src_end);
}
}
public static Json_itm_decimal NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_decimal(doc, src_bgn, src_end, null);}
public static Json_itm_decimal NewByVal(Decimal_adp val) {return new Json_itm_decimal(null, -1, -1, val);}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,21 +13,52 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Int_;
public class Json_itm_int extends Json_itm_base { public class Json_itm_int extends Json_itm_base {
private final Json_doc doc; private final Json_doc doc;
private byte[] data_bry; private int data; private boolean data_is_null = true; private final int src_bgn, src_end;
public Json_itm_int(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;} private byte[] data_bry;
private int data;
private boolean data_needs_making;
private Json_itm_int(Json_doc doc, int src_bgn, int src_end, boolean data_needs_making, int data) {
this.doc = doc;
this.src_bgn = src_bgn;
this.src_end = src_end;
this.data_needs_making = data_needs_making;
if (!data_needs_making)
this.data = data;
}
@Override public byte Tid() {return Json_itm_.Tid__int;} @Override public byte Tid() {return Json_itm_.Tid__int;}
@Override public Object Data() {return Data_as_int();}
@Override public byte[] Data_bry() {
if (data_bry == null) {
data_bry = doc == null
? Int_.To_bry(data)
: Bry_.Mid(doc.Src(), src_bgn, src_end);
}
return data_bry;
}
public int Data_as_int() { public int Data_as_int() {
if (data_is_null) { if (data_needs_making) {
data = doc.Utl_num_parser().Parse(doc.Src(), Src_bgn(), Src_end()).Rv_as_int(); data = doc.Utl_num_parser().Parse(doc.Src(), src_bgn, src_end).Rv_as_int();
data_is_null = false; data_needs_making = false;
} }
return data; return data;
} }
@Override public Object Data() {return Data_as_int();} @Override public void Print_as_json(Bry_bfr bfr, int depth) {
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); return data_bry;} if (doc == null)
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());} bfr.Add_int_variable(data);
public static Json_itm_int cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__int ? null : (Json_itm_int)v;} else
bfr.Add_mid(doc.Src(), src_bgn, src_end);
}
public static Json_itm_int NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_int(doc, src_bgn, src_end, true, -1);}
public static Json_itm_int NewByVal(int val) {return new Json_itm_int(null, -1, -1, false, val);}
public static Json_itm_int Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__int ? null : (Json_itm_int)v;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,21 +13,51 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Long_;
public class Json_itm_long extends Json_itm_base { public class Json_itm_long extends Json_itm_base {
private final Json_doc doc; private final Json_doc doc;
private byte[] data_bry; private long data; private boolean data_is_null = true; private final int src_bgn, src_end;
public Json_itm_long(Json_doc doc, int src_bgn, int src_end) {this.Ctor(src_bgn, src_end); this.doc = doc;} private byte[] data_bry;
private long data;
private boolean data_needs_making = true;
private Json_itm_long(Json_doc doc, int src_bgn, int src_end, boolean data_needs_making, long data) {
this.doc = doc;
this.src_bgn = src_bgn;
this.src_end = src_end;
this.data_needs_making = data_needs_making;
if (!data_needs_making)
this.data = data;
}
@Override public byte Tid() {return Json_itm_.Tid__long;} @Override public byte Tid() {return Json_itm_.Tid__long;}
@Override public Object Data() {return Data_as_long();}
@Override public byte[] Data_bry() {
if (data_bry == null) {
data_bry = doc == null
? Bry_.new_u8(Long_.To_str(data))
: Bry_.Mid(doc.Src(), src_bgn, src_end);
}
return data_bry;
}
public long Data_as_long() { public long Data_as_long() {
if (data_is_null) { if (data_needs_making) {
data = doc.Utl_num_parser().Parse(doc.Src(), Src_bgn(), Src_end()).Rv_as_long(); data = doc.Utl_num_parser().Parse(doc.Src(), src_bgn, src_end).Rv_as_long();
data_is_null = false; data_needs_making = false;
} }
return data; return data;
} }
@Override public Object Data() {return Data_as_long();} @Override public void Print_as_json(Bry_bfr bfr, int depth) {
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Bry_.Mid(doc.Src(), this.Src_bgn(), this.Src_end()); return data_bry;} if (doc == null)
@Override public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_mid(doc.Src(), this.Src_bgn(), this.Src_end());} bfr.Add_long_variable(data);
public static Json_itm_long cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__long ? null : (Json_itm_long)v;} else
bfr.Add_mid(doc.Src(), src_bgn, src_end);
}
public static Json_itm_long NewByDoc(Json_doc doc, int src_bgn, int src_end) {return new Json_itm_long(doc, src_bgn, src_end, true, -1);}
public static Json_itm_long NewByVal(long val) {return new Json_itm_long(null, -1, -1, false, val);}
public static Json_itm_long Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__long ? null : (Json_itm_long)v;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,38 +13,97 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.core.intls.*;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Byte_ascii;
import gplx.String_;
import gplx.core.intls.Utf16_;
import gplx.langs.htmls.Gfh_utl;
public class Json_itm_str extends Json_itm_base { public class Json_itm_str extends Json_itm_base {
private final boolean exact; private final Json_doc doc; private final Json_doc doc;
private String data_str; private byte[] data_bry = null; private final int src_bgn, src_end;
public Json_itm_str(Json_doc doc, int src_bgn, int src_end, boolean exact) {this.Ctor(src_bgn + 1, src_end - 1); this.doc = doc; this.exact = exact;} private String data_str;
@Override public byte Tid() {return Json_itm_.Tid__str;} private byte[] data_bry;
@Override public void Print_as_json(Bry_bfr bfr, int depth) { private boolean data_needs_making;
bfr.Add_byte(Byte_ascii.Quote); private boolean escaped;
gplx.langs.htmls.Gfh_utl.Escape_html_to_bfr(bfr, doc.Src(), this.Src_bgn(), this.Src_end(), true, true, true, true, false); // false to apos for backwards compatibility
bfr.Add_byte(Byte_ascii.Quote); private Json_itm_str(Json_doc doc, int src_bgn, int src_end, String data_str, boolean escaped) {
this.doc = doc;
this.src_bgn = src_bgn;
this.src_end = src_end;
this.data_str = data_str;
this.data_bry = null;
this.data_needs_making = true;
this.escaped = escaped;
} }
@Override public byte Tid() {return Json_itm_.Tid__str;}
@Override public Object Data() {return this.Data_as_str();} @Override public Object Data() {return this.Data_as_str();}
public void Overwrite_bry(byte[] v) {
this.data_bry = v; //needed by MapLink/MapFrame
this.data_needs_making = false;
}
@Override public byte[] Data_bry() {
if (data_bry == null) {
data_bry = Data_make_bry();
}
return data_bry;
}
public String Data_as_str() { public String Data_as_str() {
if (data_str == null) { if (data_str == null) {
if (data_bry == null) data_bry = Data_make_bry();
data_bry = Data_make_bry();
data_str = String_.new_u8(data_bry); data_str = String_.new_u8(data_bry);
} }
return data_str; return data_str;
} }
@Override public byte[] Data_bry() {if (data_bry == null) data_bry = Data_make_bry(); return data_bry;}
@Override public boolean Data_eq(byte[] comp) { @Override public boolean Data_eq(byte[] comp) {
if (exact) return Bry_.Eq(doc.Src(), this.Src_bgn(), this.Src_end(), comp); return Bry_.Match(this.Data_bry(), comp);
if (data_bry == null) data_bry = Data_make_bry();
return Bry_.Match(data_bry, comp);
} }
private byte[] Data_make_bry() { private byte[] Data_make_bry() {
byte[] src = doc.Src(); int bgn = this.Src_bgn(), end = this.Src_end(); // data already made; return it;
if (exact) return Bry_.Mid(src, bgn, end); if (!data_needs_making)
Bry_bfr bfr = doc.Bfr(); return data_bry;
byte[] utf8_bry = doc.Tmp_u8_bry();
// mark data as made
this.data_needs_making = false;
// get src, bgn, end, depending on whether or not itm is from jdoc or standalone
byte[] src;
int bgn;
int end;
if (doc == null) {
src = Bry_.new_u8_safe(this.data_str);
bgn = 0;
end = src == null ? 0 : src.length;
}
else {
src = doc.Src();
bgn = src_bgn;
end = src_end;
}
// not escaped -> return the src
if (!escaped) {
this.data_bry = Bry_.Mid(src, bgn, end);
return data_bry;
}
// escaped; get some temp vars
Bry_bfr bfr;
byte[] utf8_bry;
if (doc == null) {
bfr = Bry_bfr_.New();
utf8_bry = new byte[6];
}
else { // PERF:reuse bfr / bry on jdoc itself
bfr = doc.Bfr();
utf8_bry = doc.Tmp_u8_bry();
}
// loop and unescape
for (int i = bgn; i < end; i++) { for (int i = bgn; i < end; i++) {
byte b = src[i]; byte b = src[i];
switch (b) { switch (b) {
@ -90,6 +149,17 @@ public class Json_itm_str extends Json_itm_base {
break; break;
} }
} }
return bfr.To_bry_and_clear(); this.data_bry = bfr.To_bry_and_clear();
return data_bry;
} }
@Override public void Print_as_json(Bry_bfr bfr, int depth) {
bfr.Add_byte(Byte_ascii.Quote);
byte[] data_bry = this.Data_bry();
int data_len = data_bry.length;
Gfh_utl.Escape_html_to_bfr(bfr, data_bry, 0, data_len, true, true, true, true, false); // false to apos for backwards compatibility
bfr.Add_byte(Byte_ascii.Quote);
}
public static Json_itm_str NewByDoc(Json_doc doc, int src_bgn, int src_end, boolean escaped) {return new Json_itm_str(doc, src_bgn + 1, src_end - 1, null, escaped);}
public static Json_itm_str NewByVal(String val) {return new Json_itm_str(null, -1, -1, val, false);}
} }

View File

@ -1,29 +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.langs.jsons; import gplx.*; import gplx.langs.*;
public class Json_itm_tmp implements Json_itm { // TEST:
public Json_itm_tmp(byte tid, String data) {this.tid = tid; this.data = data;}
public byte Tid() {return tid;} private byte tid;
public byte[] Data_bry() {return Bry_.new_u8(Object_.Xto_str_strict_or_empty(data));}
public int Src_bgn() {return -1;}
public int Src_end() {return -1;}
public Object Data() {return data;} private String data;
public void Print_as_json(Bry_bfr bfr, int depth) {bfr.Add_str_u8(data);}
public boolean Data_eq(byte[] comp) {return false;}
public void Clear() {}
public static Json_itm new_str_(String v) {return new Json_itm_tmp(Json_itm_.Tid__str, "\"" + v + "\"");}
public static Json_itm new_int_(int v) {return new Json_itm_tmp(Json_itm_.Tid__int, Int_.To_str(v));}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,7 +13,11 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Bry_bfr;
import gplx.Byte_ascii;
public class Json_kv extends Json_itm_base { public class Json_kv extends Json_itm_base {
public Json_kv(Json_itm key, Json_itm val) {this.key = key; this.val = val;} public Json_kv(Json_itm key, Json_itm val) {this.key = key; this.val = val;}
@Override public byte Tid() {return Json_itm_.Tid__kv;} @Override public byte Tid() {return Json_itm_.Tid__kv;}
@ -22,7 +26,7 @@ public class Json_kv extends Json_itm_base {
public byte[] Key_as_bry() {return key.Data_bry();} public byte[] Key_as_bry() {return key.Data_bry();}
public String Key_as_str() {return (String)key.Data();} public String Key_as_str() {return (String)key.Data();}
public byte[] Val_as_bry() {return val.Data_bry();} public byte[] Val_as_bry() {return val.Data_bry();}
public Json_nde Val_as_nde() {return Json_nde.cast(val);} public Json_nde Val_as_nde() {return Json_nde.Cast(val);}
public Json_ary Val_as_ary() {return Json_ary.cast(val);} public Json_ary Val_as_ary() {return Json_ary.cast(val);}
public boolean Key_eq(byte[] comp) {return ((Json_itm_str)key).Data_eq(comp);} public boolean Key_eq(byte[] comp) {return ((Json_itm_str)key).Data_eq(comp);}
@Override public Object Data() {return null;} @Override public Object Data() {return null;}
@ -33,5 +37,5 @@ public class Json_kv extends Json_itm_base {
val.Print_as_json(bfr, depth); val.Print_as_json(bfr, depth);
} }
public static final Json_kv[] Ary_empty = new Json_kv[0]; public static final Json_kv[] Ary_empty = new Json_kv[0];
public static Json_kv cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__kv ? null : (Json_kv)v;} public static Json_kv Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__kv ? null : (Json_kv)v;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,36 +13,42 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import org.junit.*;
import gplx.Bool_;
import gplx.Bry_;
import gplx.Decimal_adp;
import gplx.Decimal_adp_;
import gplx.Keyval;
import gplx.Keyval_;
import gplx.Tfds;
import org.junit.Test;
public class Json_kv_ary_srl_tst { public class Json_kv_ary_srl_tst {
@Before public void init() {fxt.Clear();} private Json_kv_ary_srl_fxt fxt = new Json_kv_ary_srl_fxt(); private final Json_kv_ary_srl_fxt fxt = new Json_kv_ary_srl_fxt();
@Test public void Null() {fxt.Test_parse("{'k0':null}" , fxt.ary_(fxt.kv_str_("k0", null)));} @Test public void Null() {fxt.Test_parse("{'k0':null}" , fxt.ary_(fxt.New_kv_str("k0", null)));}
@Test public void Bool_n() {fxt.Test_parse("{'k0':false}" , fxt.ary_(fxt.kv_bool_("k0", false)));} @Test public void Bool_n() {fxt.Test_parse("{'k0':false}" , fxt.ary_(fxt.New_kv_bool("k0", false)));}
@Test public void Num() {fxt.Test_parse("{'k0':123}" , fxt.ary_(fxt.kv_int_("k0", 123)));} @Test public void Num() {fxt.Test_parse("{'k0':123}" , fxt.ary_(fxt.New_kv_int("k0", 123)));}
@Test public void Str() {fxt.Test_parse("{'k0':'v0'}" , fxt.ary_(fxt.kv_str_("k0", "v0")));} @Test public void Num_exp() {fxt.Test_parse("{'k0':1.23e2}" , fxt.ary_(fxt.New_kv_int("k0", 123)));} // exponent can be either "e" or "E" in JSON, but Java decimal parse only takes "E"; ISSUE#:565; DATE:2020-03-25
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.kv_dec_("k0", Decimal_adp_.parse("1.23"))));} @Test public void Str() {fxt.Test_parse("{'k0':'v0'}" , fxt.ary_(fxt.New_kv_str("k0", "v0")));}
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("1", 1), fxt.kv_int_("2", 2), fxt.kv_int_("3", 3)))));} @Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.ary_(fxt.New_kv_dec("k0", Decimal_adp_.parse("1.23"))));}
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_())));} @Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_(fxt.New_kv_int("1", 1), fxt.New_kv_int("2", 2), fxt.New_kv_int("3", 3)))));}
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1,'k01':2}}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_(fxt.kv_int_("k00", 1), fxt.kv_int_("k01", 2)))));} @Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_())));}
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.ary_(fxt.kv_obj_("k0", fxt.ary_())));} @Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1,'k01':2}}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_(fxt.New_kv_int("k00", 1), fxt.New_kv_int("k01", 2)))));}
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.ary_(fxt.New_kv_obj("k0", fxt.ary_())));}
} }
class Json_kv_ary_srl_fxt { class Json_kv_ary_srl_fxt {
public void Clear() { private final Json_parser parser = new Json_parser();
if (parser == null) {
parser = new Json_parser();
}
} private Json_parser parser;
public void Test_parse(String raw_str, Keyval[] expd) { public void Test_parse(String raw_str, Keyval[] expd) {
byte[] raw_bry = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str)); byte[] raw_bry = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
Json_doc doc = parser.Parse(raw_bry); Json_doc doc = parser.Parse(raw_bry);
Keyval[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root_nde()); Keyval[] actl = Json_kv_ary_srl.Val_by_itm_nde(doc.Root_nde());
Tfds.Eq_str_lines(Keyval_.Ary_to_str(expd), Keyval_.Ary_to_str(actl)); Tfds.Eq_str_lines(Keyval_.Ary_to_str(expd), Keyval_.Ary_to_str(actl));
} }
public Keyval[] ary_(Keyval... ary) {return ary;} public Keyval[] ary_(Keyval... ary) {return ary;}
public Keyval kv_obj_(String key, Object val) {return Keyval_.new_(key, val);} public Keyval New_kv_obj(String key, Object val) {return Keyval_.new_(key, val);}
public Keyval kv_str_(String key, String val) {return Keyval_.new_(key, val);} public Keyval New_kv_str(String key, String val) {return Keyval_.new_(key, val);}
public Keyval kv_int_(String key, int val) {return Keyval_.new_(key, val);} public Keyval New_kv_int(String key, int val) {return Keyval_.new_(key, val);}
public Keyval kv_bool_(String key, boolean val) {return Keyval_.new_(key, Bool_.To_str_lower(val));} public Keyval New_kv_bool(String key, boolean val) {return Keyval_.new_(key, Bool_.To_str_lower(val));}
public Keyval kv_dec_(String key, Decimal_adp val) {return Keyval_.new_(key, val.To_str());} public Keyval New_kv_dec(String key, Decimal_adp val) {return Keyval_.new_(key, val.To_str());}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,27 +13,57 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.Array_;
import gplx.Bool_;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Byte_ascii;
import gplx.DateAdp;
import gplx.DateAdp_;
import gplx.Decimal_adp_;
import gplx.Err_;
import gplx.Hash_adp_bry;
import gplx.Int_;
import gplx.Long_;
import gplx.String_;
public class Json_nde extends Json_itm_base implements Json_grp { public class Json_nde extends Json_itm_base implements Json_grp {
private Json_itm[] subs = Json_itm_.Ary_empty; private int subs_len = 0, subs_max = 0; private final int src_bgn;
private int src_end;
private Json_itm[] subs = Json_itm_.Ary_empty;
private int subs_len = 0, subs_max = 0;
private Hash_adp_bry subs_hash; private Hash_adp_bry subs_hash;
public Json_nde(Json_doc jdoc, int src_bgn) {this.jdoc = jdoc; this.Ctor(src_bgn, -1);}
private Json_nde(Json_doc jdoc, int src_bgn) {
this.jdoc = jdoc;
this.src_bgn = src_bgn;
}
@Override public byte Tid() {return Json_itm_.Tid__nde;} @Override public byte Tid() {return Json_itm_.Tid__nde;}
public Json_doc Doc() {return jdoc;} private final Json_doc jdoc; public Json_doc Doc() {return jdoc;} private final Json_doc jdoc;
public void Src_end_(int v) {this.src_end = v;} public void Src_end_(int v) {this.src_end = v;}
@Override public Object Data() {return null;} @Override public Object Data() {return null;}
@Override public byte[] Data_bry() {return null;} @Override public byte[] Data_bry() {return null;}
public int Len() {return subs_len;} public int Len() {return subs_len;}
public Json_itm Get_at(int i) {return subs[i];} public Json_itm Get_at(int i) {return subs[i];}
public Json_itm Get_as_itm_or_null(String key) {return Get_as_itm_or_null(Bry_.new_u8(key));}
public Json_itm Get_as_itm_or_null(byte[] key) {if (subs_hash == null) subs_hash = subs_hash_init(); return (Json_itm)subs_hash.Get_by_bry(key);} public Json_itm Get_as_itm_or_null(byte[] key) {if (subs_hash == null) subs_hash = subs_hash_init(); return (Json_itm)subs_hash.Get_by_bry(key);}
public Json_ary Get_as_ary(int idx) {return Json_ary.cast(Get_at(idx));} public Json_ary Get_as_ary(int idx) {return Json_ary.cast(Get_at(idx));}
public Json_nde Get_as_nde(String key) {return Json_nde.cast(Get_as_itm_or_null(Bry_.new_u8(key)));} public Json_nde Get_as_nde(String key) {return Json_nde.Cast(Get_as_itm_or_null(Bry_.new_u8(key)));}
public Json_nde Get_as_nde(int idx) {return Json_nde.cast(Get_at(idx));} public Json_nde Get_as_nde(int idx) {return Json_nde.Cast(Get_at(idx));}
public Json_ary Get_as_ary(String key) {return Get_as_ary(Bry_.new_u8(key));} public Json_ary Get_as_ary(String key) {return Get_as_ary(Bry_.new_u8(key));}
public Json_ary Get_as_ary(byte[] key) { public Json_ary Get_as_ary(byte[] key) {
Json_itm rv = Get_as_itm_or_null(key); if (rv == null) throw Err_.new_("json", "key missing", "key", key); Json_itm rv = Get_as_itm_or_null(key); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
return Json_ary.cast(rv); return Json_ary.cast(rv);
} }
public Json_ary Get_as_ary_or_null(String key) {return Get_as_ary_or_null(Bry_.new_u8(key));}
public Json_ary Get_as_ary_or_null(byte[] key) {
Json_itm rv = Get_as_itm_or_null(key);
return rv == null
? null
: Json_ary.cast(rv);
}
public byte[] Get_as_bry(String key) { public byte[] Get_as_bry(String key) {
byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key); byte[] rv = Get_as_bry_or(Bry_.new_u8(key), null); if (rv == null) throw Err_.new_("json", "key missing", "key", key);
return rv; return rv;
@ -83,21 +113,25 @@ public class Json_nde extends Json_itm_base implements Json_grp {
public boolean Has(byte[] key) {return Get_bry(key, null) != null;} public boolean Has(byte[] key) {return Get_bry(key, null) != null;}
public Json_kv Get_at_as_kv(int i) { public Json_kv Get_at_as_kv(int i) {
Json_itm rv_itm = Get_at(i); Json_itm rv_itm = Get_at(i);
Json_kv rv = Json_kv.cast(rv_itm); if (rv == null) throw Err_.new_("json", "sub is not kv", "i", i, "src", Bry_.Mid(jdoc.Src(), this.Src_bgn(), src_end)); Json_kv rv = Json_kv.Cast(rv_itm);
if (rv == null) {
byte[] snip = jdoc == null ? Bry_.new_a7("no source") : Bry_.Mid(jdoc.Src(), src_bgn, src_end);
throw Err_.new_("json", "sub is not kv", "i", i, "src", snip);
}
return rv; return rv;
} }
public Json_kv Get_kv(byte[] key) {return Json_kv.cast(Get_itm(key));} public Json_kv Get_kv(byte[] key) {return Json_kv.Cast(Get_itm(key));}
public Json_nde Get(String key) {return Get(Bry_.new_u8(key));} public Json_nde Get(String key) {return Get(Bry_.new_u8(key));}
public Json_nde Get(byte[] key) { public Json_nde Get(byte[] key) {
Json_kv kv = Json_kv.cast(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key); Json_kv kv = Json_kv.Cast(this.Get_itm(key)); if (kv == null) throw Err_.new_("json", "kv not found", "key", key);
Json_nde rv = Json_nde.cast(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key); Json_nde rv = Json_nde.Cast(kv.Val()); if (rv == null) throw Err_.new_("json", "nde not found", "key", key);
return rv; return rv;
} }
public Json_itm Get_itm(byte[] key) { public Json_itm Get_itm(byte[] key) {
for (int i = 0; i < subs_len; i++) { for (int i = 0; i < subs_len; i++) {
Json_itm itm = subs[i]; Json_itm itm = subs[i];
if (itm.Tid() == Json_itm_.Tid__kv) { if (itm != null && itm.Tid() == Json_itm_.Tid__kv) {
Json_kv itm_as_kv = (Json_kv)itm; Json_kv itm_as_kv = (Json_kv)itm;
if (Bry_.Eq(key, itm_as_kv.Key().Data_bry())) if (Bry_.Eq(key, itm_as_kv.Key().Data_bry()))
return itm; return itm;
@ -122,6 +156,17 @@ public class Json_nde extends Json_itm_base implements Json_grp {
Json_itm val = kv.Val(); Json_itm val = kv.Val();
return (val == null) ? or : val.Data_bry(); return (val == null) ? or : val.Data_bry();
} }
public void AddKvBool(String key, boolean val) {AddKv(key, Json_itm_bool.Get(val));}
public void AddKvInt(String key, int val) {AddKv(key, Json_itm_int.NewByVal(val));}
public void AddKvDouble(String key, double val) {AddKv(key, Json_itm_decimal.NewByVal(Decimal_adp_.double_(val)));}
public void AddKvStr(String key, byte[] val) {AddKv(key, Json_itm_str.NewByVal(String_.new_u8(val)));}
public void AddKvStr(String key, String val) {AddKv(key, Json_itm_str.NewByVal(val));}
public void AddKvNde(String key, Json_nde val) {AddKv(key, val);}
public void AddKvAry(String key, Json_ary val) {AddKv(key, val);}
private void AddKv(String key, Json_itm val) {
Json_kv rv = new Json_kv(Json_itm_str.NewByVal(key), val);
Add(rv);
}
public Json_nde Add_many(Json_itm... ary) { public Json_nde Add_many(Json_itm... ary) {
int len = ary.length; int len = ary.length;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
@ -165,5 +210,8 @@ public class Json_nde extends Json_itm_base implements Json_grp {
} }
return rv; return rv;
} }
public static Json_nde cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__nde ? null : (Json_nde)v;}
public static Json_nde NewByDoc(Json_doc doc, int src_bgn) {return new Json_nde(doc, src_bgn);}
public static Json_nde NewByVal() {return new Json_nde(null, -1);}
public static Json_nde Cast(Json_itm v) {return v == null || v.Tid() != Json_itm_.Tid__nde ? null : (Json_nde)v;}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,40 +13,49 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.core.primitives.*;
import gplx.Bool_;
import gplx.Bry_;
import gplx.Byte_ascii;
import gplx.Char_;
import gplx.Err;
import gplx.Err_;
import gplx.Int_;
import gplx.String_;
import gplx.core.primitives.Gfo_number_parser;
public class Json_parser { public class Json_parser {
private byte[] src; private int src_len, pos; private final Gfo_number_parser num_parser = new Gfo_number_parser(); private byte[] src;
public Json_factory Factory() {return factory;} private final Json_factory factory = new Json_factory(); private int src_len, pos;
private final Gfo_number_parser num_parser = new Gfo_number_parser();
public Json_doc Parse_by_apos_ary(String... ary) {return Parse_by_apos(String_.Concat_lines_nl(ary));} public Json_doc Parse_by_apos_ary(String... ary) {return Parse_by_apos(String_.Concat_lines_nl(ary));}
public Json_doc Parse_by_apos(String s) {return Parse(Bry_.Replace(Bry_.new_u8(s), Byte_ascii.Apos, Byte_ascii.Quote));} public Json_doc Parse_by_apos(String s) {return Parse(Bry_.Replace(Bry_.new_u8(s), Byte_ascii.Apos, Byte_ascii.Quote));}
public Json_doc Parse(String src) {return Parse(Bry_.new_u8(src));} public Json_doc Parse(String src) {return Parse(Bry_.new_u8(src));}
public Json_doc Parse(byte[] src) { public Json_doc Parse(byte[] src) {
synchronized (factory) { this.src = src; if (src == null) return null;
this.src = src; if (src == null) return null; this.src_len = src.length; if (src_len == 0) return null;
this.src_len = src.length; if (src_len == 0) return null; this.pos = 0;
this.pos = 0; Skip_ws();
Skip_ws(); boolean root_is_nde = true;
boolean root_is_nde = true; switch (src[pos]) {
switch (src[pos]) { case Byte_ascii.Curly_bgn: root_is_nde = Bool_.Y; break;
case Byte_ascii.Curly_bgn: root_is_nde = Bool_.Y; break; case Byte_ascii.Brack_bgn: root_is_nde = Bool_.N; break;
case Byte_ascii.Brack_bgn: root_is_nde = Bool_.N; break; default: return null;
default: return null;
}
Skip_ws();
Json_doc doc = new Json_doc();
Json_grp root = null;
if (root_is_nde)
root = Make_nde(doc);
else
root = Make_ary(doc);
doc.Ctor(src, root);
return doc;
} }
Skip_ws();
Json_doc doc = new Json_doc();
Json_grp root = null;
if (root_is_nde)
root = Make_nde(doc);
else
root = Make_ary(doc);
doc.Ctor(src, root);
return doc;
} }
private Json_nde Make_nde(Json_doc doc) { private Json_nde Make_nde(Json_doc doc) {
++pos; // brack_bgn ++pos; // brack_bgn
Json_nde nde = new Json_nde(doc, pos); Json_nde nde = Json_nde.NewByDoc(doc, pos);
while (pos < src_len) { while (pos < src_len) {
Skip_ws(); Skip_ws();
if (src[pos] == Byte_ascii.Curly_end) {++pos; return nde;} if (src[pos] == Byte_ascii.Curly_end) {++pos; return nde;}
@ -72,9 +81,9 @@ public class Json_parser {
while (pos < src_len) { while (pos < src_len) {
byte b = src[pos]; byte b = src[pos];
switch (b) { switch (b) {
case Byte_ascii.Ltr_n: return Make_literal(Bry_null_ull , 3, factory.Null()); case Byte_ascii.Ltr_n: return Make_literal(Bry_null_ull , 3, Json_itm_null.Null);
case Byte_ascii.Ltr_f: return Make_literal(Bry_bool_alse , 4, factory.Bool_n()); case Byte_ascii.Ltr_f: return Make_literal(Bry_bool_alse , 4, Json_itm_bool.Bool_n);
case Byte_ascii.Ltr_t: return Make_literal(Bry_bool_rue , 3, factory.Bool_y()); case Byte_ascii.Ltr_t: return Make_literal(Bry_bool_rue , 3, Json_itm_bool.Bool_y);
case Byte_ascii.Quote: return Make_string(doc); case Byte_ascii.Quote: return Make_string(doc);
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_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.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
@ -97,7 +106,7 @@ public class Json_parser {
} }
private Json_itm Make_string(Json_doc doc) { private Json_itm Make_string(Json_doc doc) {
int bgn = pos++; // ++: quote_bgn int bgn = pos++; // ++: quote_bgn
boolean exact = true; boolean escaped = false;
while (pos < src_len) { while (pos < src_len) {
switch (src[pos]) { switch (src[pos]) {
case Byte_ascii.Backslash: case Byte_ascii.Backslash:
@ -106,10 +115,10 @@ public class Json_parser {
case Byte_ascii.Ltr_u: pos += 5; break; // \uFFFF 1 u + 4 hex-dec; ISSUE#:486; DATE:2019-06-02 case Byte_ascii.Ltr_u: pos += 5; break; // \uFFFF 1 u + 4 hex-dec; ISSUE#:486; DATE:2019-06-02
default: ++pos; break; // \? " \ / b f n r t default: ++pos; break; // \? " \ / b f n r t
} }
exact = false; escaped = true;
break; break;
case Byte_ascii.Quote: case Byte_ascii.Quote:
return factory.Str(doc, bgn, ++pos, exact); // ++: quote_end return Json_itm_str.NewByDoc(doc, bgn, ++pos, escaped); // ++: quote_end
default: default:
++pos; ++pos;
break; break;
@ -139,16 +148,16 @@ public class Json_parser {
} }
num_parser.Parse(src, num_bgn, pos); num_parser.Parse(src, num_bgn, pos);
if (num_parser.Has_frac()) if (num_parser.Has_frac())
return factory.Decimal(doc, num_bgn, pos); return Json_itm_decimal.NewByDoc(doc, num_bgn, pos);
else { else {
if (num_parser.Is_int()) if (num_parser.Is_int())
return factory.Int(doc, num_bgn, pos); return Json_itm_int.NewByDoc(doc, num_bgn, pos);
else else
return factory.Long(doc, num_bgn, pos); return Json_itm_long.NewByDoc(doc, num_bgn, pos);
} }
} }
private Json_ary Make_ary(Json_doc doc) { private Json_ary Make_ary(Json_doc doc) {
Json_ary rv = factory.Ary(pos++, pos); // brack_bgn Json_ary rv = Json_ary.NewByDoc(doc, pos++, pos); // brack_bgn
while (pos < src_len) { while (pos < src_len) {
Skip_ws(); Skip_ws();
if (src[pos] == Byte_ascii.Brack_end) {++pos; return rv;} if (src[pos] == Byte_ascii.Brack_end) {++pos; return rv;}
@ -180,5 +189,9 @@ public class Json_parser {
String msg = String_.Format(fmt, args) + " " + Int_.To_str(bgn) + " " + String_.new_u8__by_len(src, bgn, 20); String msg = String_.Format(fmt, args) + " " + Int_.To_str(bgn) + " " + String_.new_u8__by_len(src, bgn, 20);
return Err_.new_wo_type(msg); return Err_.new_wo_type(msg);
} }
private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull"); private static final byte[] Bry_bool_rue = Bry_.new_a7("rue"), Bry_bool_alse = Bry_.new_a7("alse"), Bry_null_ull = Bry_.new_a7("ull");
public static Json_doc ParseToJdoc(String src) {
Json_parser parser = new Json_parser();
return parser.Parse(src);
}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,8 +13,13 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import gplx.core.primitives.*;
import gplx.Keyval_;
import gplx.Ordered_hash;
import gplx.String_;
import gplx.core.primitives.Int_obj_val;
public class Json_parser__list_nde__base extends Json_parser__itm__base { public class Json_parser__list_nde__base extends Json_parser__itm__base {
public void Parse_grp(String context, Json_grp grp) { public void Parse_grp(String context, Json_grp grp) {
this.context = context; this.context = context;
@ -22,11 +27,11 @@ public class Json_parser__list_nde__base extends Json_parser__itm__base {
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
Json_nde sub = null; Json_nde sub = null;
if (grp.Tid() == Json_itm_.Tid__nde) { if (grp.Tid() == Json_itm_.Tid__nde) {
Json_kv kv = Json_nde.cast(grp).Get_at_as_kv(i); Json_kv kv = Json_nde.Cast(grp).Get_at_as_kv(i);
sub = kv.Val_as_nde(); sub = kv.Val_as_nde();
} }
else { else {
sub = Json_nde.cast(grp.Get_at(i)); sub = Json_nde.Cast(grp.Get_at(i));
} }
Parse_nde(context, sub); Parse_nde(context, sub);
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,83 +13,92 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.jsons; import gplx.*; import gplx.langs.*; package gplx.langs.jsons;
import org.junit.*;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Decimal_adp;
import gplx.Decimal_adp_;
import gplx.Tfds;
import gplx.core.tests.Gftest;
import org.junit.Test;
public class Json_parser_tst { public class Json_parser_tst {
private final Json_parser_fxt fxt = new Json_parser_fxt(); private final Json_parser_fxt fxt = new Json_parser_fxt();
@Before public void init() {fxt.Clear();} @Test public void Null() {fxt.Test_parse_obj("{'k0':null}" , null);}
@Test public void Null() {fxt.Test_parse_val0("{'k0':null}" , null);} @Test public void Bool_n() {fxt.Test_parse_obj("{'k0':false}" , false);}
@Test public void Bool_n() {fxt.Test_parse_val0("{'k0':false}" , false);} @Test public void Bool_y() {fxt.Test_parse_obj("{'k0':true}" , true);}
@Test public void Bool_y() {fxt.Test_parse_val0("{'k0':true}" , true);} @Test public void Num() {fxt.Test_parse_obj("{'k0':123}" , 123);}
@Test public void Num() {fxt.Test_parse_val0("{'k0':123}" , 123);} @Test public void Num_neg() {fxt.Test_parse_obj("{'k0':-123}" , -123);}
@Test public void Num_neg() {fxt.Test_parse_val0("{'k0':-123}" , -123);} @Test public void Str() {fxt.Test_parse_obj("{'k0':'v0'}" , "v0");}
@Test public void Str() {fxt.Test_parse_val0("{'k0':'v0'}" , "v0");} @Test public void Str_esc_quote() {fxt.Test_parse_obj("{'k0':'a\\\"b'}" , "a\"b");}
@Test public void Str_esc_quote() {fxt.Test_parse_val0("{'k0':'a\\\"b'}" , "a\"b");} @Test public void Str_encoded_basic() {fxt.Test_parse_obj("{'k0':'a\\u0021b'}" , "a!b");}
@Test public void Str_encoded_basic() {fxt.Test_parse_val0("{'k0':'a\\u0021b'}" , "a!b");} @Test public void Str_encoded_surrogate() {fxt.Test_parse_obj("{'k0':'a\\ud83c\\udf0eb'}", "a🌎b");} // check for UTF surrogate-pairs; symbol is earth globe americas (U+1F30E); ISSUE#:487; DATE:2019-06-02
@Test public void Str_encoded_surrogate() {fxt.Test_parse_val0("{'k0':'a\\ud83c\\udf0eb'}", "a🌎b");} // check for UTF surrogate-pairs; symbol is earth globe americas (U+1F30E); ISSUE#:487; DATE:2019-06-02 @Test public void Num_dec() {fxt.Test_parse_dec("{'k0':1.23}" , Decimal_adp_.parse("1.23"));}
@Test public void Num_dec() {fxt.Test_parse("{'k0':1.23}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "1.23")));} @Test public void Num_exp() {fxt.Test_parse_obj("{'k0':1e+2}" , 100);}
@Test public void Num_exp() {fxt.Test_parse("{'k0':1e+2}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "1e+2")));} @Test public void Num_mix() {fxt.Test_parse_dec("{'k0':-1.23e-1}" , Decimal_adp_.parse("-1.23e-1"));}
@Test public void Num_mix() {fxt.Test_parse("{'k0':-1.23e-1}" , fxt.itm_nde_().Add_many(fxt.itm_kv_dec_("k0", "-1.23e-1")));} @Test public void Str_many() {fxt.Test_parse("{'k0':'v0','k1':'v1','k2':'v2'}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", "v0"), fxt.Init_kv("k1", "v1"), fxt.Init_kv("k2", "v2")));}
@Test public void Str_many() {fxt.Test_parse("{'k0':'v0','k1':'v1','k2':'v2'}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", "v0"), fxt.itm_kv_("k1", "v1"), fxt.itm_kv_("k2", "v2")));} @Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0")));}
@Test public void Ary_empty() {fxt.Test_parse("{'k0':[]}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0")));} @Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0", 1, 2, 3)));}
@Test public void Ary_int() {fxt.Test_parse("{'k0':[1,2,3]}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0", 1, 2, 3)));} @Test public void Ary_str() {fxt.Test_parse("{'k0':['a','b','c']}" , fxt.Init_nde().Add_many(fxt.Init_kvary_str_("k0", "a", "b", "c")));}
@Test public void Ary_str() {fxt.Test_parse("{'k0':['a','b','c']}", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_str_("k0", "a", "b", "c")));} @Test public void Ary_ws() {fxt.Test_parse("{'k0': [ 1 , 2 , 3 ] }" , fxt.Init_nde().Add_many(fxt.Init_kv_ary_int("k0", 1, 2, 3)));}
@Test public void Ary_ws() {fxt.Test_parse("{'k0': [ 1 , 2 , 3 ] }", fxt.itm_nde_().Add_many(fxt.itm_kv_ary_int_("k0", 1, 2, 3)));} @Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1}}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde().Add_many(fxt.Init_kv("k00", 1)))));}
@Test public void Subs_int() {fxt.Test_parse("{'k0':{'k00':1}}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_().Add_many(fxt.itm_kv_("k00", 1)))));} @Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde())));}
@Test public void Subs_empty() {fxt.Test_parse("{'k0':{}}", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_())));} @Test public void Subs_ws() {fxt.Test_parse("{'k0': { 'k00' : 1 } }" , fxt.Init_nde().Add_many(fxt.Init_kv("k0", fxt.Init_nde().Add_many(fxt.Init_kv("k00", 1)))));}
@Test public void Subs_ws() {fxt.Test_parse("{'k0': { 'k00' : 1 } }", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", fxt.itm_nde_().Add_many(fxt.itm_kv_("k00", 1)))));} @Test public void Ws() {fxt.Test_parse(" { 'k0' : 'v0' } " , fxt.Init_nde().Add_many(fxt.Init_kv("k0", "v0")));}
@Test public void Ws() {fxt.Test_parse(" { 'k0' : 'v0' } ", fxt.itm_nde_().Add_many(fxt.itm_kv_("k0", "v0")));} @Test public void Root_is_ary() {fxt.Test_parse("[1,2,3]" , fxt.Init_ary().Add_many(fxt.Init_int(1), fxt.Init_int(2), fxt.Init_int(3)));}
@Test public void Root_is_ary() {fxt.Test_parse("[ 1 , 2 , 3 ]", fxt.itm_ary_().Add_many(fxt.itm_int_(1), fxt.itm_int_(2), fxt.itm_int_(3)));}
public static String Replace_apos_as_str(String v) {return String_.new_u8(Replace_apos(Bry_.new_u8(v)));}
public static byte[] Replace_apos(byte[] v) {return Bry_.Replace(v, Byte_ascii.Apos, Byte_ascii.Quote);}
} }
class Json_parser_fxt { class Json_parser_fxt {
public void Clear() { private final Json_parser parser = new Json_parser();
if (parser == null) { private final Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
parser = new Json_parser(); public Json_itm Init_int(int v) {return Json_itm_int.NewByVal(v);}
factory = parser.Factory(); public Json_itm Init_str(String v) {return Json_itm_str.NewByVal(v);}
} public Json_ary Init_ary() {return Json_ary.NewByVal();}
} Json_parser parser; Json_factory factory; Bry_bfr tmp_bfr = Bry_bfr_.Reset(255); public Json_nde Init_nde() {return Json_nde.NewByVal();}
public Json_itm itm_int_(int v) {return Json_itm_tmp.new_int_(v);} public Json_kv Init_kv_null(String k) {return new Json_kv(Init_str(k), Json_itm_null.Null);}
Json_itm itm_str_(String v) {return Json_itm_tmp.new_str_(v);} public Json_kv Init_kv(String k, String v) {return new Json_kv(Init_str(k), Init_str(v));}
public Json_ary itm_ary_() {return factory.Ary(-1, -1);} public Json_kv Init_kv(String k, int v) {return new Json_kv(Init_str(k), Init_int(v));}
public Json_nde itm_nde_() {return factory.Nde(null, -1);} public Json_kv Init_kv(String k, boolean v) {return new Json_kv(Init_str(k), v ? Json_itm_bool.Bool_y : Json_itm_bool.Bool_n);}
public Json_kv itm_kv_null_(String k) {return factory.Kv(itm_str_(k), factory.Null());} public Json_kv Init_kv(String k, Json_nde v) {return new Json_kv(Init_str(k), v);}
public Json_kv itm_kv_(String k, String v) {return factory.Kv(itm_str_(k), itm_str_(v));} public Json_kv Init_kv_ary_int(String k, int... v) {
public Json_kv itm_kv_(String k, int v) {return factory.Kv(itm_str_(k), itm_int_(v));} Json_ary ary = Json_ary.NewByVal();
public Json_kv itm_kv_(String k, boolean v) {return factory.Kv(itm_str_(k), v ? factory.Bool_y() : factory.Bool_n());}
public Json_kv itm_kv_dec_(String k, String v) {return factory.Kv(itm_str_(k), new Json_itm_tmp(Json_itm_.Tid__decimal, v));}
public Json_kv itm_kv_(String k, Json_nde v) {return factory.Kv(itm_str_(k), v);}
public Json_kv itm_kv_ary_int_(String k, int... v) {
Json_ary ary = factory.Ary(-1, -1);
int len = v.length; int len = v.length;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
ary.Add(itm_int_(v[i])); ary.Add(Init_int(v[i]));
return factory.Kv(itm_str_(k), ary); return new Json_kv(Init_str(k), ary);
} }
public Json_kv itm_kv_ary_str_(String k, String... v) { public Json_kv Init_kvary_str_(String k, String... v) {
Json_ary ary = factory.Ary(-1, -1); Json_ary ary = Json_ary.NewByVal();
int len = v.length; int len = v.length;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
ary.Add(itm_str_(v[i])); ary.Add(Init_str(v[i]));
return factory.Kv(itm_str_(k), ary); return new Json_kv(Init_str(k), ary);
} }
public void Test_parse(String raw_str, Json_itm... expd_ary) { public void Test_parse(String raw_str, Json_itm... expd_ary) {
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str)); byte[] raw = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
Json_doc doc = parser.Parse(raw); Json_doc doc = parser.Parse(raw);
doc.Root_grp().Print_as_json(tmp_bfr, 0); doc.Root_grp().Print_as_json(tmp_bfr, 0);
String actl = tmp_bfr.To_str_and_clear(); String actl = tmp_bfr.To_str_and_clear();
String expd = Xto_str(raw, doc, expd_ary, 0, expd_ary.length); String expd = Xto_str(raw, doc, expd_ary, 0, expd_ary.length);
Tfds.Eq_str_lines(expd, actl, actl); Tfds.Eq_str_lines(expd, actl, actl);
} }
public void Test_parse_val0(String raw_str, Object expd) { public void Test_parse_obj(String raw_str, Object expd) {
byte[] raw = Json_parser_tst.Replace_apos(Bry_.new_u8(raw_str)); Json_kv kv = Parse_and_get_kv0(raw_str);
Json_doc doc = parser.Parse(raw);
Json_kv kv = Json_kv.cast(doc.Root_nde().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
Object actl = kv.Val().Data(); // NOTE: Data_bry is escaped val; EX: a\"b has DataBry of a"b Object actl = kv.Val().Data(); // NOTE: Data_bry is escaped val; EX: a\"b has DataBry of a"b
Tfds.Eq(expd, actl); Gftest.Eq__obj_or_null(expd, actl);
} }
String Xto_str(byte[] raw, Json_doc doc, Json_itm[] ary, int bgn, int end) { public void Test_parse_dec(String raw_str, Decimal_adp expd) {
Json_kv kv = Parse_and_get_kv0(raw_str);
Json_itm_decimal decimal_itm = (Json_itm_decimal)kv.Val();
Gftest.Eq__bool(true, decimal_itm.Data_as_decimal().Eq(expd));
}
private Json_kv Parse_and_get_kv0(String raw_str) {
byte[] raw = Bry_.new_u8(Json_doc.Make_str_by_apos(raw_str));
Json_doc doc = parser.Parse(raw);
return Json_kv.Cast(doc.Root_nde().Get_at(0)); // assume root has kv as first sub; EX: {"a":"b"}
}
private String Xto_str(byte[] raw, Json_doc doc, Json_itm[] ary, int bgn, int end) {
for (int i = bgn; i < end; i++) { for (int i = bgn; i < end; i++) {
Json_itm itm = ary[i]; Json_itm itm = ary[i];
itm.Print_as_json(tmp_bfr, 0); itm.Print_as_json(tmp_bfr, 0);

View File

@ -0,0 +1,112 @@
/*
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.langs.mustaches;
import gplx.Bool_;
import gplx.Bry_;
import gplx.String_;
import gplx.langs.jsons.Json_ary;
import gplx.langs.jsons.Json_itm;
import gplx.langs.jsons.Json_itm_;
import gplx.langs.jsons.Json_kv;
import gplx.langs.jsons.Json_nde;
import gplx.objects.Object_;
public class JsonMustacheNde implements Mustache_doc_itm {
private final Json_nde nde;
public JsonMustacheNde(Json_nde nde) {this.nde = nde;}
public boolean Mustache__write(String key, Mustache_bfr bfr) {
Json_itm itm = nde.Get_itm(Bry_.new_u8(key));
if (itm == null) { // mustacheKey does not exist in current jsonNde
return false;
}
else { // mustacheKey exists
switch (itm.Tid()) {
// array / bool node -> ignore; EX: `{{#person}}Never shown{{/person}}`
case Json_itm_.Tid__bool:
case Json_itm_.Tid__ary:
case Json_itm_.Tid__nde:
return false;
// item node -> render it; EX: `Hello {{name}}`
default:
bfr.Add_bry(Json_kv.Cast(itm).Val_as_bry());
return true;
}
}
}
public Mustache_doc_itm[] Mustache__subs(String key) {
Json_itm itm = nde.Get_itm(Bry_.new_u8(key));
if (itm == null) { // mustacheKey does not exist in current jsonNde
return Mustache_doc_itm_.Ary__bool__n;
}
else { // mustacheKey exists
if (itm.Tid() == Json_itm_.Tid__kv) {
Json_kv kv = Json_kv.Cast(itm);
switch (kv.Val().Tid()) {
// bool node -> render; EX: `{{#person}}Never shown{{/person}}`
case Json_itm_.Tid__bool:
boolean dataVal = Bool_.Cast(kv.Val().Data());
return dataVal ? Mustache_doc_itm_.Ary__bool__y : Mustache_doc_itm_.Ary__bool__n;
// array node -> render; EX: `{{#repo}} <b>{{name}}</b>{{/repo}}`
case Json_itm_.Tid__ary:
return ToJsonMustachNdeAry(itm);
// item node -> render only if key matchers
default:
return new Mustache_doc_itm[] {new JsonMustacheVal(true, key, kv.Val().Data())};
}
}
else {
return Mustache_doc_itm_.Ary__bool__n;
}
}
}
private static Mustache_doc_itm[] ToJsonMustachNdeAry(Json_itm itm) {
Json_ary dataAry = Json_ary.cast_or_null(Json_kv.Cast(itm).Val());
int subs_len = dataAry.Len();
Mustache_doc_itm[] rv = new Mustache_doc_itm[subs_len];
for (int i = 0; i < subs_len; i++) {
Json_itm sub = dataAry.Get_at(i);
if (sub.Tid() == Json_itm_.Tid__nde) {
rv[i] = new JsonMustacheNde((Json_nde)sub);
}
else {
rv[i] = new JsonMustacheVal(false, Mustache_tkn_def.ItemString, sub.Data());
}
}
return rv;
}
}
class JsonMustacheVal implements Mustache_doc_itm {
private final boolean fromArray;
private final String jsonKey;
private final Object jsonVal;
public JsonMustacheVal(boolean fromArray, String jsonKey, Object jsonVal) {
this.fromArray = fromArray;
this.jsonKey = jsonKey;
this.jsonVal = jsonVal;
}
public boolean Mustache__write(String mustacheKey, Mustache_bfr bfr) {
if ( (String_.Eq(mustacheKey, jsonKey)) // print if `{{match}}`; EX: `{{#prop}}{{prop}}{{/prop}}`
|| (String_.Eq(mustacheKey, Mustache_tkn_def.ItemString) && fromArray)) { // print if `{{.}}` and from array; EX: `{{#array}}{{.}}{{/array}}`
bfr.Add_bry(Bry_.new_u8(Object_.To_str(jsonVal)));
return true;
}
else {
return false;
}
}
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import gplx.langs.jsons.*;
public interface Mustache_doc_itm { public interface Mustache_doc_itm {
boolean Mustache__write(String key, Mustache_bfr bfr); boolean Mustache__write(String key, Mustache_bfr bfr);
Mustache_doc_itm[] Mustache__subs(String key); Mustache_doc_itm[] Mustache__subs(String key);
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,47 +13,57 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import org.junit.*; import gplx.core.primitives.*;
import gplx.Bry_;
import gplx.Hash_adp;
import gplx.Hash_adp_;
import gplx.Tfds;
import gplx.core.primitives.Bool_obj_ref;
import gplx.langs.jsons.Json_doc;
import gplx.langs.jsons.Json_nde;
import gplx.langs.jsons.Json_parser;
import org.junit.Test;
public class Mustache_itm_render_tst { public class Mustache_itm_render_tst {
private final Mustache_itm_render_fxt fxt = new Mustache_itm_render_fxt(); private final Mustache_itm_render_fxt fxt = new Mustache_itm_render_fxt();
@Test public void Text() { @Test public void Text() {
fxt.Test__parse("a b c", "a b c"); fxt.Test__parse("a b c", "a b c");
} }
@Test public void Variable() { @Test public void Variable() {
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "1").Add_prop("prop2", "2")); fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "1").Add_prop("prop2", "2"));
fxt.Test__parse("{{prop1}}", "1"); fxt.Test__parse("{{prop1}}", "1");
fxt.Test__parse("a{{prop1}}b{{prop2}}c", "a1b2c"); fxt.Test__parse("a{{prop1}}b{{prop2}}c", "a1b2c");
} }
@Test public void Escape() { @Test public void Escape() {
fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "<")); fxt.Init__root(fxt.Make_mock(0).Add_prop("prop1", "<"));
fxt.Test__parse("{{{prop1}}}", "<"); fxt.Test__parse("{{{prop1}}}", "<");
fxt.Test__parse("{{prop1}}", "&lt;"); fxt.Test__parse("{{prop1}}", "&lt;");
} }
@Test public void Section_bool() { @Test public void Section_bool() {
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n")); fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c", "abc"); fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c", "abc");
fxt.Test__parse("a{{#bool_n}}b{{/bool_n}}c", "ac"); fxt.Test__parse("a{{#bool_n}}b{{/bool_n}}c", "ac");
fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c{{#bool_n}}d{{/bool_n}}e", "abce"); fxt.Test__parse("a{{#bool_y}}b{{/bool_y}}c{{#bool_n}}d{{/bool_n}}e", "abce");
} }
@Test public void Section_not() { @Test public void Section_not() {
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n")); fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y").Add_bool_n("bool_n"));
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c", "ac"); fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c", "ac");
fxt.Test__parse("a{{^bool_n}}b{{/bool_n}}c", "abc"); fxt.Test__parse("a{{^bool_n}}b{{/bool_n}}c", "abc");
fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c{{^bool_n}}d{{/bool_n}}e", "acde"); fxt.Test__parse("a{{^bool_y}}b{{/bool_y}}c{{^bool_n}}d{{/bool_n}}e", "acde");
} }
@Test public void Section_ws() { @Test public void Section_ws() {
fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y")); fxt.Init__root(fxt.Make_mock(0).Add_bool_y("bool_y"));
fxt.Test__parse("a\n {{#bool_y}} \nb\n {{/bool_y}} \nc", "a\nb\nc"); fxt.Test__parse("a\n {{#bool_y}} \nb\n {{/bool_y}} \nc", "a\nb\nc");
} }
@Test public void Section_subs_flat() { @Test public void Section_subs_flat() {
fxt.Init__root(fxt.Make_mock(0).Add_subs("subs1" fxt.Init__root(fxt.Make_mock(0).Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "1").Add_subs("subs2") , fxt.Make_mock(1).Add_prop("prop1", "1").Add_subs("subs2")
, fxt.Make_mock(2).Add_prop("prop1", "2").Add_subs("subs2") , fxt.Make_mock(2).Add_prop("prop1", "2").Add_subs("subs2")
)); ));
fxt.Test__parse("a{{#subs1}}({{prop1}}){{/subs1}}d", "a(1)(2)d"); fxt.Test__parse("a{{#subs1}}({{prop1}}){{/subs1}}d", "a(1)(2)d");
} }
@Test public void Section_subs_nest_1() { @Test public void Section_subs_nest_1() {
fxt.Init__root fxt.Init__root
( fxt.Make_mock(0).Add_subs("subs1" ( fxt.Make_mock(0).Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2" , fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
@ -65,7 +75,7 @@ public class Mustache_itm_render_tst {
, "a12" , "a12"
); );
} }
@Test public void Section_subs_nest_2() { @Test public void Section_subs_nest_2() {
fxt.Init__root fxt.Init__root
( fxt.Make_mock(0).Add_subs("subs1" ( fxt.Make_mock(0).Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2" , fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
@ -80,7 +90,7 @@ public class Mustache_itm_render_tst {
, "a12b" , "a12b"
); );
} }
@Test public void Section_subs_nest_3() { @Test public void Section_subs_nest_3() {
fxt.Init__root fxt.Init__root
( fxt.Make_mock(0).Add_subs("subs1" ( fxt.Make_mock(0).Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2" , fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
@ -98,7 +108,7 @@ public class Mustache_itm_render_tst {
, "a12ab34b" , "a12ab34b"
); );
} }
@Test public void Section_bool_subs() { // handle prop written after boolean; should not pick up inner prop @Test public void Section_bool_subs() { // handle prop written after boolean; should not pick up inner prop
fxt.Init__root fxt.Init__root
( fxt.Make_mock(0).Add_bool_y("bool1").Add_prop("prop2", "2").Add_subs("subs1" ( fxt.Make_mock(0).Add_bool_y("bool1").Add_prop("prop2", "2").Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "11") , fxt.Make_mock(1).Add_prop("prop1", "11")
@ -109,7 +119,7 @@ public class Mustache_itm_render_tst {
, "abc11dc12def2g" , "abc11dc12def2g"
); );
} }
@Test public void Section_owner() { @Test public void Section_owner() {
fxt.Init__root fxt.Init__root
( fxt.Make_mock(0).Add_subs("subs1" ( fxt.Make_mock(0).Add_subs("subs1"
, fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2" , fxt.Make_mock(1).Add_prop("prop1", "a").Add_subs("subs2"
@ -121,11 +131,18 @@ public class Mustache_itm_render_tst {
, "a1" , "a1"
); );
} }
@Test public void Dot() {
fxt.Test__parse
( "{'subs':['a', 'b', 'c', 'd']}"
, "{{#subs}}{{.}},{{/subs}}"
, "a,b,c,d,"
);
}
} }
class Mustache_itm_render_fxt { class Mustache_itm_render_fxt {
private final Mustache_tkn_parser parser = new Mustache_tkn_parser(); private final Mustache_tkn_parser parser = new Mustache_tkn_parser();
private final Mustache_render_ctx ctx = new Mustache_render_ctx(); private final Mustache_render_ctx ctx = new Mustache_render_ctx();
private final Mustache_bfr bfr = Mustache_bfr.New(); private final Mustache_bfr bfr = Mustache_bfr.New();
private Mustache_doc_itm__mock root; private Mustache_doc_itm__mock root;
public Mustache_doc_itm__mock Make_mock(int id) {return new Mustache_doc_itm__mock(id);} public Mustache_doc_itm__mock Make_mock(int id) {return new Mustache_doc_itm__mock(id);}
public void Init__root(Mustache_doc_itm__mock v) {this.root = v;} public void Init__root(Mustache_doc_itm__mock v) {this.root = v;}
@ -136,9 +153,19 @@ class Mustache_itm_render_fxt {
actl_itm.Render(bfr, ctx); actl_itm.Render(bfr, ctx);
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear()); Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
} }
public void Test__parse(String jdoc, String src_str, String expd) {
Json_nde jnde = Json_parser.ParseToJdoc(Json_doc.Make_str_by_apos(jdoc)).Root_nde();
JsonMustacheNde nde = new JsonMustacheNde(jnde);
byte[] src_bry = Bry_.new_a7(src_str);
Mustache_tkn_itm actl_itm = parser.Parse(src_bry, 0, src_bry.length);
ctx.Init(nde);
actl_itm.Render(bfr, ctx);
Tfds.Eq_str_lines(expd, bfr.To_str_and_clear());
}
} }
class Mustache_doc_itm__mock implements Mustache_doc_itm { class Mustache_doc_itm__mock implements Mustache_doc_itm {
private final Hash_adp hash_prop = Hash_adp_.New(), hash_bool = Hash_adp_.New(), hash_subs = Hash_adp_.New(); private final Hash_adp hash_prop = Hash_adp_.New(), hash_bool = Hash_adp_.New(), hash_subs = Hash_adp_.New();
public Mustache_doc_itm__mock(int id) {this.id = id;} public Mustache_doc_itm__mock(int id) {this.id = id;}
public int id; public int id;
public Mustache_doc_itm__mock Add_prop(String key, String val) {hash_prop.Add(key, Bry_.new_u8(val)); return this;} public Mustache_doc_itm__mock Add_prop(String key, String val) {hash_prop.Add(key, Bry_.new_u8(val)); return this;}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,15 +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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import gplx.Bool_;
import gplx.List_adp;
import gplx.List_adp_;
public class Mustache_render_ctx { public class Mustache_render_ctx {
private final List_adp stack = List_adp_.New(); private final List_adp stack = List_adp_.New();
private Mustache_doc_itm cur; private Mustache_doc_itm cur;
private Mustache_doc_itm[] subs; private int subs_idx, subs_len; private byte cur_is_bool; private Mustache_doc_itm[] subs;
private int subs_idx, subs_len;
private byte cur_is_bool;
public Mustache_render_ctx Init(Mustache_doc_itm cur) { public Mustache_render_ctx Init(Mustache_doc_itm cur) {
this.cur = cur; this.cur = cur;
this.subs = null; this.subs = null;
this.subs_idx = subs_len = 0; this.cur_is_bool = Bool_.__byte; this.subs_idx = subs_len = 0;
this.cur_is_bool = Bool_.__byte;
return this; return this;
} }
public boolean Render_variable(Mustache_bfr bfr, String key) { public boolean Render_variable(Mustache_bfr bfr, String key) {
@ -30,13 +39,15 @@ public class Mustache_render_ctx {
Mustache_doc_itm itm = cur; Mustache_doc_itm itm = cur;
while (itm != Mustache_doc_itm_.Null_itm) { while (itm != Mustache_doc_itm_.Null_itm) {
boolean resolved = itm.Mustache__write(key, bfr); boolean resolved = itm.Mustache__write(key, bfr);
// current itm handles key -> exit
if (resolved) { if (resolved) {
rv = true; rv = true;
break; break;
} }
// current itm does not handle key -> go up stack
else { else {
--stack_pos; --stack_pos;
if (stack_pos == -1) // nothing else in stack if (stack_pos == -1) // nothing else in stack
break; break;
else else
itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).cur; itm = ((Mustache_stack_itm)stack.Get_at(stack_pos)).cur;
@ -47,12 +58,15 @@ public class Mustache_render_ctx {
public void Section_bgn(String key) { public void Section_bgn(String key) {
Mustache_stack_itm stack_itm = new Mustache_stack_itm(cur, subs, subs_idx, subs_len, cur_is_bool); // note that cur is "owner" since subs_idx == 0 Mustache_stack_itm stack_itm = new Mustache_stack_itm(cur, subs, subs_idx, subs_len, cur_is_bool); // note that cur is "owner" since subs_idx == 0
stack.Add(stack_itm); stack.Add(stack_itm);
subs = cur.Mustache__subs(key); if (subs == null) subs = Mustache_doc_itm_.Ary__empty; // subs == null if property does not exist; EX: "folder{{#files}}file{{/files}}" and folder = new Folder(File[0]); subs = cur.Mustache__subs(key);
if (subs == null) // subs == null if property does not exist; EX: "folder{{#files}}file{{/files}}" and folder = new Folder(File[0]);
subs = Mustache_doc_itm_.Ary__empty;
subs_len = subs.length; subs_len = subs.length;
subs_idx = -1; subs_idx = -1;
} }
public boolean Section_do(boolean inverted) { public boolean Section_do(boolean inverted) {
if (++subs_idx >= subs_len) return false; if (++subs_idx >= subs_len)
return false;
Mustache_doc_itm sub = subs[subs_idx]; Mustache_doc_itm sub = subs[subs_idx];
if (subs_idx == 0) { // special logic to handle 1st item; note that there always be at least one item if (subs_idx == 0) { // special logic to handle 1st item; note that there always be at least one item
if (sub == Mustache_doc_itm_.Itm__bool__n) { if (sub == Mustache_doc_itm_.Itm__bool__n) {
@ -90,9 +104,9 @@ class Mustache_stack_itm {
this.subs_idx = subs_idx; this.subs_idx = subs_idx;
this.subs_len = subs_len; this.subs_len = subs_len;
} }
public final Mustache_doc_itm cur; public final Mustache_doc_itm cur;
public final byte cur_is_bool; public final byte cur_is_bool;
public final Mustache_doc_itm[] subs; public final Mustache_doc_itm[] subs;
public final int subs_idx; public final int subs_idx;
public final int subs_len; public final int subs_len;
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,7 +13,13 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import gplx.Bry_;
import gplx.Byte_;
import gplx.Byte_ascii;
import gplx.String_;
class Mustache_tkn_def { class Mustache_tkn_def {
public byte[] Variable_lhs = Dflt_variable_lhs; public byte[] Variable_lhs = Dflt_variable_lhs;
public byte[] Variable_rhs = Dflt_variable_rhs; public byte[] Variable_rhs = Dflt_variable_rhs;
@ -31,9 +37,13 @@ class Mustache_tkn_def {
, Grp_end = Byte_ascii.Slash // {{/section}} , Grp_end = Byte_ascii.Slash // {{/section}}
, Inverted = Byte_ascii.Pow // {{^inverted}} , Inverted = Byte_ascii.Pow // {{^inverted}}
, Comment = Byte_ascii.Bang // {{!comment}} , Comment = Byte_ascii.Bang // {{!comment}}
, Partial = Byte_ascii.Angle_bgn // {{>partial}} , Partial = Byte_ascii.Angle_end // {{>partial}}
, Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}} , Delimiter_bgn = Byte_ascii.Eq // {{=<% %>=}}
, Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}} , Delimiter_end = Byte_ascii.Curly_end // {{=<% %>=}}
, Item = Byte_ascii.Dot // {{.}}
;
public static final String
ItemString = String_.new_u8(Byte_.To_bry(Item))
; ;
public Mustache_tkn_def() { public Mustache_tkn_def() {
Variable_lhs_len = Variable_lhs.length; Variable_lhs_len = Variable_lhs.length;

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,7 +13,15 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import gplx.Bool_;
import gplx.Bry_;
import gplx.Byte_ascii;
import gplx.Err_;
import gplx.Io_url;
import gplx.String_;
public interface Mustache_tkn_itm { public interface Mustache_tkn_itm {
int Tid(); int Tid();
String Key(); String Key();
@ -23,17 +31,17 @@ public interface Mustache_tkn_itm {
} }
class Mustache_tkn_itm_ {// for types, see http://mustache.github.io/mustache.5.html class Mustache_tkn_itm_ {// for types, see http://mustache.github.io/mustache.5.html
public static final int Tid__root = 0, Tid__text = 1, Tid__variable = 2, Tid__escape = 3, Tid__section = 4, Tid__inverted = 5, Tid__comment = 6, Tid__partial = 7, Tid__delimiter = 8; public static final int Tid__root = 0, Tid__text = 1, Tid__variable = 2, Tid__escape = 3, Tid__section = 4, Tid__inverted = 5, Tid__comment = 6, Tid__partial = 7, Tid__delimiter = 8;
public static final Mustache_tkn_itm[] Ary_empty = new Mustache_tkn_itm[0]; public static final Mustache_tkn_itm[] Ary_empty = new Mustache_tkn_itm[0];
} }
abstract class Mustache_tkn_base implements Mustache_tkn_itm { abstract class Mustache_tkn_base implements Mustache_tkn_itm {
public Mustache_tkn_base(int tid, byte[] key_bry) {this.tid = tid; this.key = String_.new_u8(key_bry);} public Mustache_tkn_base(int tid, byte[] key_bry) {this.tid = tid; this.key = String_.new_u8(key_bry);}
public int Tid() {return tid;} private final int tid; public int Tid() {return tid;} private final int tid;
public String Key() {return key;} private final String key; public String Key() {return key;} private final String key;
@gplx.Virtual public Mustache_tkn_itm[] Subs_ary() {return Mustache_tkn_itm_.Ary_empty;} @gplx.Virtual public Mustache_tkn_itm[] Subs_ary() {return Mustache_tkn_itm_.Ary_empty;}
@gplx.Virtual public void Subs_ary_(Mustache_tkn_itm[] v) {throw Err_.new_unsupported();} // fail if trying to set and not overridden @gplx.Virtual public void Subs_ary_(Mustache_tkn_itm[] v) {throw Err_.new_unsupported();} // fail if trying to set and not overridden
@gplx.Virtual public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {throw Err_.new_unsupported();} // should be abstract @gplx.Virtual public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {throw Err_.new_unsupported();} // should be abstract
} }
class Mustache_tkn_root extends Mustache_tkn_base { // EX: {{variable}} -> &lt;a&gt; class Mustache_tkn_root extends Mustache_tkn_base { // EX: {{variable}} -> &lt;a&gt;
private Mustache_tkn_itm[] subs_ary; private Mustache_tkn_itm[] subs_ary;
public Mustache_tkn_root() {super(Mustache_tkn_itm_.Tid__root, Bry_.Empty);} public Mustache_tkn_root() {super(Mustache_tkn_itm_.Tid__root, Bry_.Empty);}
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;} @Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
@ -46,8 +54,8 @@ class Mustache_tkn_root extends Mustache_tkn_base { // EX: {{variable}} -> &lt;
} }
} }
} }
class Mustache_tkn_text extends Mustache_tkn_base { // EX: text -> text class Mustache_tkn_text extends Mustache_tkn_base { // EX: text -> text
private final byte[] src; private final int src_bgn, src_end; private final byte[] src; private final int src_bgn, src_end;
public Mustache_tkn_text(byte[] src, int src_bgn, int src_end) {super(Mustache_tkn_itm_.Tid__text, Bry_.Empty); public Mustache_tkn_text(byte[] src, int src_bgn, int src_end) {super(Mustache_tkn_itm_.Tid__text, Bry_.Empty);
this.src = src; this.src = src;
this.src_bgn = src_bgn; this.src_bgn = src_bgn;
@ -57,25 +65,25 @@ class Mustache_tkn_text extends Mustache_tkn_base { // EX: text -> text
bfr.Add_mid(src, src_bgn, src_end); bfr.Add_mid(src, src_bgn, src_end);
} }
} }
class Mustache_tkn_comment extends Mustache_tkn_base { // EX: {{!section}}comment{{/section}} -> class Mustache_tkn_comment extends Mustache_tkn_base { // EX: {{!section}}comment{{/section}} ->
public Mustache_tkn_comment() {super(Mustache_tkn_itm_.Tid__comment, Bry_.Empty);} public Mustache_tkn_comment() {super(Mustache_tkn_itm_.Tid__comment, Bry_.Empty);}
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {} @Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {}
} }
class Mustache_tkn_variable extends Mustache_tkn_base { // EX: {{variable}} -> &lt;a&gt; class Mustache_tkn_variable extends Mustache_tkn_base { // EX: {{variable}} -> &lt;a&gt;
public Mustache_tkn_variable(byte[] key) {super(Mustache_tkn_itm_.Tid__variable, key);} public Mustache_tkn_variable(byte[] key) {super(Mustache_tkn_itm_.Tid__variable, key);}
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) { @Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
String key = this.Key(); String key = this.Key();
ctx.Render_variable(bfr.Escape_(Bool_.Y), key); ctx.Render_variable(bfr.Escape_(Bool_.Y), key);
} }
} }
class Mustache_tkn_escape extends Mustache_tkn_base { // EX: {{{variable}}} -> <a> class Mustache_tkn_escape extends Mustache_tkn_base { // EX: {{{variable}}} -> <a>
public Mustache_tkn_escape(byte[] key) {super(Mustache_tkn_itm_.Tid__escape, key);} public Mustache_tkn_escape(byte[] key) {super(Mustache_tkn_itm_.Tid__escape, key);}
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) { @Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
String key = this.Key(); String key = this.Key();
ctx.Render_variable(bfr.Escape_(Bool_.N), key); ctx.Render_variable(bfr.Escape_(Bool_.N), key);
} }
} }
class Mustache_tkn_section extends Mustache_tkn_base { // EX: {{#section}}val{{/section}} -> val (if boolean) or valvalval (if list) class Mustache_tkn_section extends Mustache_tkn_base { // EX: {{#section}}val{{/section}} -> val (if boolean) or valvalval (if list)
private Mustache_tkn_itm[] subs_ary; private Mustache_tkn_itm[] subs_ary;
public Mustache_tkn_section(byte[] key) {super(Mustache_tkn_itm_.Tid__section, key);} public Mustache_tkn_section(byte[] key) {super(Mustache_tkn_itm_.Tid__section, key);}
@Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;} @Override public Mustache_tkn_itm[] Subs_ary() {return subs_ary;}
@ -102,9 +110,17 @@ class Mustache_tkn_inverted extends Mustache_tkn_base { // EX: {{^section}}missi
@Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;} @Override public void Subs_ary_(Mustache_tkn_itm[] v) {subs_ary = v;}
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {Mustache_tkn_section.Render_static(Bool_.Y, this, bfr, ctx);} @Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {Mustache_tkn_section.Render_static(Bool_.Y, this, bfr, ctx);}
} }
class Mustache_tkn_partial extends Mustache_tkn_base { // EX: {{>a}} -> abc (deferred eval) class Mustache_tkn_partial extends Mustache_tkn_base { // EX: {{>a}} -> abc (deferred eval)
public Mustache_tkn_partial(byte[] key) {super(Mustache_tkn_itm_.Tid__partial, key);} private Mustache_tkn_itm template_root;
public Mustache_tkn_partial(byte[] key, Io_url dir) {
super(Mustache_tkn_itm_.Tid__partial, key);
Mustache_tkn_parser parser = new Mustache_tkn_parser(dir);
template_root = parser.Parse(String_.new_a7(Bry_.Trim_bgn(key, Byte_ascii.Space, 0)));
}
@Override public void Render(Mustache_bfr bfr, Mustache_render_ctx ctx) {
template_root.Render(bfr, ctx);
}
} }
class Mustache_tkn_delimiter extends Mustache_tkn_base {// EX: {{=<% %>=}} -> <% variable %> class Mustache_tkn_delimiter extends Mustache_tkn_base { // EX: {{=<% %>=}} -> <% variable %>
public Mustache_tkn_delimiter(byte[] key) {super(Mustache_tkn_itm_.Tid__delimiter, key);} public Mustache_tkn_delimiter(byte[] key) {super(Mustache_tkn_itm_.Tid__delimiter, key);}
} }

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. or alternatively under the terms of the Apache License Version 2.0.
@ -13,10 +13,32 @@ 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/ */
package gplx.langs.mustaches; import gplx.*; import gplx.langs.*; package gplx.langs.mustaches;
import gplx.Bry_;
import gplx.Bry_find_;
import gplx.Byte_ascii;
import gplx.Err;
import gplx.Err_;
import gplx.Io_mgr;
import gplx.Io_url;
import gplx.List_adp;
import gplx.List_adp_;
public class Mustache_tkn_parser { public class Mustache_tkn_parser {
private byte[] src; private int src_end; private byte[] src; private int src_end;
private final Mustache_tkn_def tkn_def = new Mustache_tkn_def(); private Io_url template_root;
private final Mustache_tkn_def tkn_def = new Mustache_tkn_def();
public Mustache_tkn_parser() {
}
public Mustache_tkn_parser(Io_url template_root) {
this.template_root = template_root;
}
public Mustache_tkn_itm Parse(String template) { return Parse(template, Bry_.Empty); }
public Mustache_tkn_itm Parse(String template, byte[] default_text) {
byte[] template_data = Io_mgr.Instance.LoadFilBryOr(template_root.GenSubFil_nest(template + ".mustache"), default_text);
return Parse(template_data, 0, template_data.length);
}
public Mustache_tkn_itm Parse(byte[] src) {return Parse(src, 0, src.length);} public Mustache_tkn_itm Parse(byte[] src) {return Parse(src, 0, src.length);}
public Mustache_tkn_itm Parse(byte[] src, int src_bgn, int src_end) { public Mustache_tkn_itm Parse(byte[] src, int src_bgn, int src_end) {
this.src = src; this.src_end = src_end; this.src = src; this.src_end = src_end;
@ -80,7 +102,7 @@ public class Mustache_tkn_parser {
default: throw Err_.new_unhandled(tkn_data.tid); default: throw Err_.new_unhandled(tkn_data.tid);
case Mustache_tkn_def.Variable: tkn = new Mustache_tkn_variable(val_bry); break; case Mustache_tkn_def.Variable: tkn = new Mustache_tkn_variable(val_bry); break;
case Mustache_tkn_def.Comment: tkn = new Mustache_tkn_comment(); break; case Mustache_tkn_def.Comment: tkn = new Mustache_tkn_comment(); break;
case Mustache_tkn_def.Partial: tkn = new Mustache_tkn_partial(val_bry); break; case Mustache_tkn_def.Partial: tkn = new Mustache_tkn_partial(val_bry, template_root); break;
case Mustache_tkn_def.Delimiter_bgn: tkn = new Mustache_tkn_delimiter(val_bry); break; // TODO_OLD: implement delimiter; EX: {{=<% %>=}} case Mustache_tkn_def.Delimiter_bgn: tkn = new Mustache_tkn_delimiter(val_bry); break; // TODO_OLD: implement delimiter; EX: {{=<% %>=}}
case Mustache_tkn_def.Escape_bgn: tkn = new Mustache_tkn_escape(val_bry); break; case Mustache_tkn_def.Escape_bgn: tkn = new Mustache_tkn_escape(val_bry); break;
case Mustache_tkn_def.Section: tkn = new Mustache_tkn_section(val_bry); break; case Mustache_tkn_def.Section: tkn = new Mustache_tkn_section(val_bry); break;

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