/* 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.xowa.xtns.math.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.math.*; import gplx.dbs.*; import gplx.xowa.bldrs.*; import gplx.xowa.parsers.logs.*; import gplx.xowa.xtns.math.texvcs.*; import gplx.xowa.xtns.math.texvcs.tkns.*; class Xomath_check_mgr { private int count_total, count_xnde_invalid, count_xnde_w_atrs, count_texvc_invalid, count_texvc_adjusted; public void Exec(Xowe_wiki wiki) { // get db, conn, rdr Xob_db_file log_db = Xob_db_file.New__file_make(wiki.Fsys_mgr().Root_dir()); Db_conn log_conn = log_db.Conn(); Xop_log_basic_tbl log_tbl = new Xop_log_basic_tbl(log_conn); Db_rdr rdr = log_conn.Stmt_select_all(log_tbl.Tbl_name(), log_tbl.flds).Exec_select__rls_auto(); // loop try { while (rdr.Move_next()) { // get page_id, src int page_id = rdr.Read_int(log_tbl.fld__page_id); byte[] src = rdr.Read_bry_by_str(log_tbl.fld__src_str); count_total++; src = Assert_flanking_math_ndes(page_id, src); if (src == null) { count_xnde_invalid++; continue; } Check_texvc(page_id, src); } } finally {rdr.Rls();} Gfo_usr_dlg_.Instance.Note_many("", "", "done: total=~{0}, xnde_invalid=~{1} xnde_w_atrs=~{2} texvc_invalid=~{3} texvc_adjusted=~{4}" , count_total, count_xnde_invalid, count_xnde_w_atrs, count_texvc_invalid, count_texvc_adjusted); } private final byte[] math_lhs_bry = Bry_.new_a7("<math"), math_rhs_bry = Bry_.new_a7("</math>"), nl_repl_bry = Bry_.new_a7(" "); private byte[] Assert_flanking_math_ndes(int page_id, byte[] src) { // assert "<math" at start if (!Bry_.Has_at_bgn(src, math_lhs_bry)) { Gfo_usr_dlg_.Instance.Warn_many("", "", "math.check:xnde_invalid b/c '<math' is not at beginning; page_id=~{0}, src=~{1}", page_id, Bry_.Replace(src, Byte_ascii.Nl_bry, nl_repl_bry)); return null; } // assert "</math>" at end if (!Bry_.Has_at_end(src, math_rhs_bry)) { Gfo_usr_dlg_.Instance.Warn_many("", "", "math.check:xnde_invalid b/c '</math>' is not at end; page_id=~{0}, src=~{1}", page_id, Bry_.Replace(src, Byte_ascii.Nl_bry, nl_repl_bry)); return null; } // assert "<math>" int math_lhs_end = Bry_find_.Find_fwd(src, Byte_ascii.Gt_bry, math_lhs_bry.length); if (math_lhs_end != math_lhs_bry.length) { count_xnde_w_atrs++; Gfo_usr_dlg_.Instance.Log_many("", "", "math.check:xnde_w_atrs; page_id=~{0}, src=~{1}", page_id, Bry_.Replace(src, Byte_ascii.Nl_bry, nl_repl_bry)); } // remove "<math>", "</math>" return Bry_.Mid(src, math_lhs_end + 1, src.length - math_rhs_bry.length); } private final Texvc_parser parser = new Texvc_parser(); private final Texvc_checker checker = new Texvc_checker(); private final Texvc_ctx ctx = new Texvc_ctx(); private final Bry_bfr tmp_bfr = Bry_bfr_.New(); private void Check_texvc(int page_id, byte[] src) { try { Texvc_root root = new Texvc_root(); ctx.Clear(); parser.Parse(ctx, root, src); checker.Check(src, root); tmp_bfr.Clear(); root.Print_tex_bry(tmp_bfr, src, 0); byte[] texvc_bry = tmp_bfr.To_bry_and_clear(); if (!Bry_.Eq(src, texvc_bry)) { count_texvc_adjusted++; Gfo_usr_dlg_.Instance.Log_many("", "", "math.check:texvc_adjusted; page_id=~{0}, src=~{1} texvc=~{2}", page_id, Bry_.Replace(src, Byte_ascii.Nl_bry, nl_repl_bry), Bry_.Replace(texvc_bry, Byte_ascii.Nl_bry, nl_repl_bry)); } } catch (Exception exc) { count_texvc_invalid++; Gfo_usr_dlg_.Instance.Warn_many("", "", "math.check:texvc_invalid; page_id=~{0}, src=~{1} err=~{2}", page_id, Bry_.Replace(src, Byte_ascii.Nl_bry, nl_repl_bry), Err_.Message_gplx_log(exc)); } } }