1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

'v3.7.2.1'

This commit is contained in:
gnosygnu
2016-07-10 23:35:32 -04:00
parent f5f48bb9b1
commit b333db45f8
366 changed files with 4468 additions and 3460 deletions

View File

@@ -58,11 +58,13 @@ public class Pf_func_ {
}
else if (lhs_len == 0 || rhs_len == 0) // one side is empty String and the other side is String; return false;
return false;
lhs_parser.Parse(lhs, 0, lhs_len);
if (lhs_parser.Has_err()) return false;
rhs_parser.Parse(rhs, 0, rhs_len);
if (rhs_parser.Has_err()) return false;
return lhs_parser.Has_frac() || rhs_parser.Has_frac() ? lhs_parser.Rv_as_dec().Eq(rhs_parser.Rv_as_dec()) : lhs_parser.Rv_as_int() == rhs_parser.Rv_as_int();
synchronized (lhs_parser) { // LOCK:static-obj; DATE:2016-07-06
lhs_parser.Parse(lhs, 0, lhs_len);
if (lhs_parser.Has_err()) return false;
rhs_parser.Parse(rhs, 0, rhs_len);
if (rhs_parser.Has_err()) return false;
return lhs_parser.Has_frac() || rhs_parser.Has_frac() ? lhs_parser.Rv_as_dec().Eq(rhs_parser.Rv_as_dec()) : lhs_parser.Rv_as_int() == rhs_parser.Rv_as_int();
}
}
public static void Reg(Xow_domain_itm domain_itm, gplx.xowa.langs.funcs.Xol_func_regy func_regy, Xol_lang_itm lang) {
Xol_kwd_mgr kwd_mgr = lang.Kwd_mgr();

View File

@@ -24,6 +24,7 @@ public class Pfunc_expr_shunter {
Val_stack val_stack = new Val_stack();
Func_tkn_stack prc_stack = new Func_tkn_stack();
public static final Decimal_adp Null_rslt = null;
private final Object thread_lock = new Object();
public Bry_bfr Err() {return err_bfr;} Bry_bfr err_bfr = Bry_bfr_.New();
public Decimal_adp Err_set(Xop_ctx ctx, int msgId) {return Err_set(ctx, msgId, Bry_.Empty);}
public Decimal_adp Err_set(Xop_ctx ctx, int msg_id, byte[] arg) {
@@ -37,127 +38,129 @@ public class Pfunc_expr_shunter {
err_bfr.Add(bry);
}
public Decimal_adp Evaluate(Xop_ctx ctx, byte[] src) { // REF.MW: Expr.php
int src_len = src.length; if (src_len == 0) return Null_rslt;
int cur_pos = 0; byte cur_byt = src[0];
boolean mode_expr = true; Func_tkn prv_prc = null;
val_stack.Clear(); prc_stack.Clear();
while (true) {
// can't think of a way for this to happen; note that operators will automatically push values/operators off stack that are lower; can't get up to 100
// if (val_stack.Len() > 100 || prc_stack.Len() > 100) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_err__stack_exhausted);
Object o = trie.Match_bgn_w_byte(cur_byt, src, cur_pos, src_len);
int bgn_pos = cur_pos;
if (o == null) { // letter or unknown symbol
while (cur_pos < src_len) {
byte b = src[cur_pos++];
if (Byte_ascii.Is_ltr(b))
continue;
else
break;
synchronized (thread_lock) {
int src_len = src.length; if (src_len == 0) return Null_rslt;
int cur_pos = 0; byte cur_byt = src[0];
boolean mode_expr = true; Func_tkn prv_prc = null;
val_stack.Clear(); prc_stack.Clear();
while (true) {
// can't think of a way for this to happen; note that operators will automatically push values/operators off stack that are lower; can't get up to 100
// if (val_stack.Len() > 100 || prc_stack.Len() > 100) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_err__stack_exhausted);
Object o = trie.Match_bgn_w_byte(cur_byt, src, cur_pos, src_len);
int bgn_pos = cur_pos;
if (o == null) { // letter or unknown symbol
while (cur_pos < src_len) {
byte b = src[cur_pos++];
if (Byte_ascii.Is_ltr(b))
continue;
else
break;
}
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, cur_pos));
}
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, cur_pos));
}
else {
Expr_tkn t = (Expr_tkn)o;
cur_pos = trie.Match_pos();
switch (t.Tid()) {
case Expr_tkn_.Tid_space: break;
case Expr_tkn_.Tid_number:
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
int numBgn = cur_pos - 1;
boolean loop = true;
while (loop) {
if (cur_pos == src_len) break;
switch (src[cur_pos]) {
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.Dot:
++cur_pos;
break;
default: loop = false; break;
}
}
Decimal_adp num = Null_rslt;
try {num = Bry_.To_decimal(src, numBgn, cur_pos);}
catch (Exception exc) {
// NOTE: PATCH.PHP: 65.5.5 can evaluate to 65.5; EX "{{Geological eras|-600|height=2|border=none}}" eventually does "|10-to={{#ifexpr:{{{1|-4567}}}<-65.5|-65.5|{{{1}}}}}.5" which is 65.5.5
Err_.Noop(exc);
int dot_count = 0;
for (int i = numBgn; i < cur_pos; i++) {
if (src[i] == Byte_ascii.Dot) {
switch (dot_count) {
case 0: dot_count = 1; break;
case 1:
try {
num = Bry_.To_decimal(src, numBgn, i);
}
catch (Exception exc_inner) {Err_.Noop(exc_inner);}
break;
}
else {
Expr_tkn t = (Expr_tkn)o;
cur_pos = trie.Match_pos();
switch (t.Tid()) {
case Expr_tkn_.Tid_space: break;
case Expr_tkn_.Tid_number:
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
int numBgn = cur_pos - 1;
boolean loop = true;
while (loop) {
if (cur_pos == src_len) break;
switch (src[cur_pos]) {
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.Dot:
++cur_pos;
break;
default: loop = false; break;
}
}
if (num == null) return Null_rslt;
}
val_stack.Push(num);
mode_expr = false;
break;
case Expr_tkn_.Tid_paren_lhs:
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_operator, Bry_.new_a7("("));
prc_stack.Push((Func_tkn)t);
break;
case Expr_tkn_.Tid_operator:
Func_tkn cur_prc = (Func_tkn)t;
if (Byte_ascii.Is_ltr(cur_byt)) {
int nxt_pos = Bry_find_.Find_fwd_while_letter(src, cur_pos, src_len);
if (nxt_pos > cur_pos)
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, nxt_pos));
}
if (cur_prc.Func_is_const()) { // func is "pi" or "e"; DATE:2014-03-01
if (mode_expr) { // number expected; just call Calc (which will place value on stack)
cur_prc.Calc(ctx, this, val_stack);
Decimal_adp num = Null_rslt;
try {num = Bry_.To_decimal(src, numBgn, cur_pos);}
catch (Exception exc) {
// NOTE: PATCH.PHP: 65.5.5 can evaluate to 65.5; EX "{{Geological eras|-600|height=2|border=none}}" eventually does "|10-to={{#ifexpr:{{{1|-4567}}}<-65.5|-65.5|{{{1}}}}}.5" which is 65.5.5
Err_.Noop(exc);
int dot_count = 0;
for (int i = numBgn; i < cur_pos; i++) {
if (src[i] == Byte_ascii.Dot) {
switch (dot_count) {
case 0: dot_count = 1; break;
case 1:
try {
num = Bry_.To_decimal(src, numBgn, i);
}
catch (Exception exc_inner) {Err_.Noop(exc_inner);}
break;
}
}
}
if (num == null) return Null_rslt;
}
val_stack.Push(num);
mode_expr = false;
break;
case Expr_tkn_.Tid_paren_lhs:
if (!mode_expr) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_operator, Bry_.new_a7("("));
prc_stack.Push((Func_tkn)t);
break;
case Expr_tkn_.Tid_operator:
Func_tkn cur_prc = (Func_tkn)t;
if (Byte_ascii.Is_ltr(cur_byt)) {
int nxt_pos = Bry_find_.Find_fwd_while_letter(src, cur_pos, src_len);
if (nxt_pos > cur_pos)
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unrecognised_word, Bry_.Mid(src, bgn_pos, nxt_pos));
}
if (cur_prc.Func_is_const()) { // func is "pi" or "e"; DATE:2014-03-01
if (mode_expr) { // number expected; just call Calc (which will place value on stack)
cur_prc.Calc(ctx, this, val_stack);
break;
}
else // operator expected; fail b/c pi / e is not an operator;
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
}
if (mode_expr) { // NOTE: all the GetAlts have higher precedence; "break;" need to skip evaluation below else will fail for --1
Func_tkn alt_prc = cur_prc.GetAlt();
prc_stack.Push(alt_prc);
break;
}
else // operator expected; fail b/c pi / e is not an operator;
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_number);
}
if (mode_expr) { // NOTE: all the GetAlts have higher precedence; "break;" need to skip evaluation below else will fail for --1
Func_tkn alt_prc = cur_prc.GetAlt();
prc_stack.Push(alt_prc);
prv_prc = prc_stack.GetLast();
while (prv_prc != null && (cur_prc.Precedence() <= prv_prc.Precedence())) {
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
prc_stack.Pop();
prv_prc = prc_stack.GetLast();
}
prc_stack.Push(cur_prc);
mode_expr = true;
break;
case Expr_tkn_.Tid_paren_rhs: {
prv_prc = prc_stack.GetLast();
while (prv_prc != null && prv_prc.Tid() != Expr_tkn_.Tid_paren_lhs) {
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
prc_stack.Pop();
prv_prc = prc_stack.GetLast();
}
if (prv_prc == Paren_bgn_tkn.Instance)
prc_stack.Pop();
else
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_closing_bracket);
mode_expr = false;
break;
}
prv_prc = prc_stack.GetLast();
while (prv_prc != null && (cur_prc.Precedence() <= prv_prc.Precedence())) {
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
prc_stack.Pop();
prv_prc = prc_stack.GetLast();
}
prc_stack.Push(cur_prc);
mode_expr = true;
break;
case Expr_tkn_.Tid_paren_rhs: {
prv_prc = prc_stack.GetLast();
while (prv_prc != null && prv_prc.Tid() != Expr_tkn_.Tid_paren_lhs) {
if (!prv_prc.Calc(ctx, this, val_stack)) return Null_rslt;
prc_stack.Pop();
prv_prc = prc_stack.GetLast();
}
if (prv_prc == Paren_bgn_tkn.Instance)
prc_stack.Pop();
else
return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unexpected_closing_bracket);
mode_expr = false;
break;
}
}
if (cur_pos == src_len) break;
cur_byt = src[cur_pos];
}
if (cur_pos == src_len) break;
cur_byt = src[cur_pos];
while (prc_stack.Len() > 0) {
Func_tkn cur_prc = prc_stack.Pop();
if (cur_prc.Tid() == Expr_tkn_.Tid_paren_lhs) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unclosed_bracket);
if (!cur_prc.Calc(ctx, this, val_stack)) return Null_rslt;
}
return val_stack.Len() == 0 ? Null_rslt : val_stack.Pop(); // HACK: for [[List of Premiers of South Australia by time in office]] and {{#expr:\n{{age in days
}
while (prc_stack.Len() > 0) {
Func_tkn cur_prc = prc_stack.Pop();
if (cur_prc.Tid() == Expr_tkn_.Tid_paren_lhs) return Err_set(ctx, Xol_msg_itm_.Id_pfunc_expr_unclosed_bracket);
if (!cur_prc.Calc(ctx, this, val_stack)) return Null_rslt;
}
return val_stack.Len() == 0 ? Null_rslt : val_stack.Pop(); // HACK: for [[List of Premiers of South Australia by time in office]] and {{#expr:\n{{age in days
}
private static Btrie_fast_mgr expression_() {
Btrie_fast_mgr rv = Btrie_fast_mgr.ci_a7(); // NOTE:ci.ascii:MW_const.en; math and expressions

View File

@@ -25,7 +25,7 @@ public class Pfunc_ifexist_mgr {
public void Clear() {regy.Clear();}
public boolean Exists(Xowe_wiki wiki, byte[] raw_bry) {
if (Bry_.Len_eq_0(raw_bry)) return false; // return early; NOTE: {{autolink}} can pass in "" (see test)
Xoa_ttl ttl = Xoa_ttl.parse(wiki, raw_bry); if (ttl == null) return false;
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, raw_bry); if (ttl == null) return false;
byte[] ttl_bry = ttl.Page_db(); // NOTE: must use Page_db; EX: {{#ifexist:File:Peter & Paul fortress in SPB 03.jpg|y|n}}
Object exists_obj = regy.Get_by(ttl_bry);
if (exists_obj != null) return ((Pfunc_ifexist_itm)exists_obj).Exists();

View File

@@ -23,60 +23,62 @@ public class Pfunc_switch extends Pf_func_base {
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_switch().Name_(name);}
@Override public boolean Func_require_colon_arg() {return true;}
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {// REF.MW:ParserFunctions_body.php
int self_args_len = self.Args_len(); if (self_args_len == 0) return; // no cases; return; effectively "empty"
byte[] argx = Eval_argx(ctx, src, caller, self);
boolean fall_thru_found = false;
byte[] match = null;
Arg_itm_tkn dflt_val_tkn = null; byte[] dflt_val_bry = null;
Arg_nde_tkn last_keyless_arg = null;
Bry_bfr tmp = ctx.Wiki().Utl__bfr_mkr().Get_b512();
Xol_kwd_mgr kwd_mgr = ctx.Lang().Kwd_mgr();
for (int i = 0; i < self_args_len; i++) {
Arg_nde_tkn arg = self.Args_get_by_idx(i);
if (arg.KeyTkn_exists()) { // = exists; EX: "|a=1|"
last_keyless_arg = null; // set last_keyless_arg to null
byte[] case_key = Get_or_eval(ctx, src, caller, self, bfr, arg.Key_tkn(), tmp);
if ( fall_thru_found // fall-thru found earlier; take cur value; EX: {{#switch:a|a|b=1|c=2}} -> 1
|| Pf_func_.Eq_(case_key, argx) // case_key matches argx; EX: {{#switch:a|a=1}}
) {
match = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
break; // stop iterating; explicit match found;
// synchronized (this) { // LOCK:DELETE; DATE:2016-07-06
int self_args_len = self.Args_len(); if (self_args_len == 0) return; // no cases; return; effectively "empty"
byte[] argx = Eval_argx(ctx, src, caller, self);
boolean fall_thru_found = false;
byte[] match = null;
Arg_itm_tkn dflt_val_tkn = null; byte[] dflt_val_bry = null;
Arg_nde_tkn last_keyless_arg = null;
Bry_bfr tmp = ctx.Wiki().Utl__bfr_mkr().Get_b512();
Xol_kwd_mgr kwd_mgr = ctx.Lang().Kwd_mgr();
for (int i = 0; i < self_args_len; i++) {
Arg_nde_tkn arg = self.Args_get_by_idx(i);
if (arg.KeyTkn_exists()) { // = exists; EX: "|a=1|"
last_keyless_arg = null; // set last_keyless_arg to null
byte[] case_key = Get_or_eval(ctx, src, caller, self, bfr, arg.Key_tkn(), tmp);
if ( fall_thru_found // fall-thru found earlier; take cur value; EX: {{#switch:a|a|b=1|c=2}} -> 1
|| Pf_func_.Eq_(case_key, argx) // case_key matches argx; EX: {{#switch:a|a=1}}
) {
match = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
break; // stop iterating; explicit match found;
}
else if (kwd_mgr.Kwd_default_match(case_key)){ // case_key is #default; EX: {{#switch:a|#default=1}}; note that "#defaultabc" is also allowed;
dflt_val_tkn = arg.Val_tkn(); // set dflt_val_tkn; note that there is no "break" b/c multiple #defaults will use last one; EX: {{#switch:a|#default=1|#default=2}} -> 2
dflt_val_bry = null; // set dflt_val_bry to null; EX:{{#switch:a|#defaultabc|#default=2}} -> 2
}
else {} // case_key != argx; continue
}
else if (kwd_mgr.Kwd_default_match(case_key)){ // case_key is #default; EX: {{#switch:a|#default=1}}; note that "#defaultabc" is also allowed;
dflt_val_tkn = arg.Val_tkn(); // set dflt_val_tkn; note that there is no "break" b/c multiple #defaults will use last one; EX: {{#switch:a|#default=1|#default=2}} -> 2
dflt_val_bry = null; // set dflt_val_bry to null; EX:{{#switch:a|#defaultabc|#default=2}} -> 2
}
else {} // case_key != argx; continue
}
else { // = missing; EX: "|a|", "|#default|"
last_keyless_arg = arg;
byte[] case_val = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
if (Pf_func_.Eq_(case_val, argx)) // argx matches case_val; EX: case_val="|a|" and argx="a"
fall_thru_found = true; // set as fall-thru; note that fall-thrus will have "val" in next keyed arg, so need to continue iterating; EX: {{#switch:a|a|b=1|c=2}} "a" is fall-thru, but "b" is next keyed arg with a val
else if (kwd_mgr.Kwd_default_match(case_val)) { // case_val starts with #default; EX: "|#default|" or "|#defaultabc|"
last_keyless_arg = null; // unflag last keyless arg else |#defaultabc| will be treated as last_keyless_arg and generate "#defaultabc"; DATE:2014-05-29
dflt_val_tkn = null; // unflag dflt_val_tkn; EX: {{#switch:a|b|#default=1|#default}} -> "" x> "1"
int case_val_len = case_val.length;
dflt_val_bry
= case_val_len == Dflt_keyword_len // PERF: check if case_val = "|#default|"
? null // PERF: set to null; don't create Bry_.Empty
: Bry_.Mid(case_val, Dflt_keyword_len, case_val_len) // chop off "#default"; EX: {{#switch:a|b|#defaultabc}} -> "abc"
;
else { // = missing; EX: "|a|", "|#default|"
last_keyless_arg = arg;
byte[] case_val = Get_or_eval(ctx, src, caller, self, bfr, arg.Val_tkn(), tmp);
if (Pf_func_.Eq_(case_val, argx)) // argx matches case_val; EX: case_val="|a|" and argx="a"
fall_thru_found = true; // set as fall-thru; note that fall-thrus will have "val" in next keyed arg, so need to continue iterating; EX: {{#switch:a|a|b=1|c=2}} "a" is fall-thru, but "b" is next keyed arg with a val
else if (kwd_mgr.Kwd_default_match(case_val)) { // case_val starts with #default; EX: "|#default|" or "|#defaultabc|"
last_keyless_arg = null; // unflag last keyless arg else |#defaultabc| will be treated as last_keyless_arg and generate "#defaultabc"; DATE:2014-05-29
dflt_val_tkn = null; // unflag dflt_val_tkn; EX: {{#switch:a|b|#default=1|#default}} -> "" x> "1"
int case_val_len = case_val.length;
dflt_val_bry
= case_val_len == Dflt_keyword_len // PERF: check if case_val = "|#default|"
? null // PERF: set to null; don't create Bry_.Empty
: Bry_.Mid(case_val, Dflt_keyword_len, case_val_len) // chop off "#default"; EX: {{#switch:a|b|#defaultabc}} -> "abc"
;
}
}
}
}
if (match == null) { // no match; will either use last_keyless arg or #default
if (last_keyless_arg != null) // always prefer last_keyless_arg; EX: {{#switch:a|#default=1|2}} -> 2
match = Get_or_eval(ctx, src, caller, self, bfr, last_keyless_arg.Val_tkn(), tmp);
else if (dflt_val_bry != null) // "|#defaultabc|" found; use it
match = dflt_val_bry;
else if (dflt_val_tkn != null) // "|#default=val|" found; use it
match = Get_or_eval(ctx, src, caller, self, bfr, dflt_val_tkn, tmp);
else {} // nothing found; noop; match will remain null
}
if (match != null)
bfr.Add(match);
tmp.Mkr_rls();
if (match == null) { // no match; will either use last_keyless arg or #default
if (last_keyless_arg != null) // always prefer last_keyless_arg; EX: {{#switch:a|#default=1|2}} -> 2
match = Get_or_eval(ctx, src, caller, self, bfr, last_keyless_arg.Val_tkn(), tmp);
else if (dflt_val_bry != null) // "|#defaultabc|" found; use it
match = dflt_val_bry;
else if (dflt_val_tkn != null) // "|#default=val|" found; use it
match = Get_or_eval(ctx, src, caller, self, bfr, dflt_val_tkn, tmp);
else {} // nothing found; noop; match will remain null
}
if (match != null)
bfr.Add(match);
tmp.Mkr_rls();
// }
}
private byte[] Get_or_eval(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bb, Arg_itm_tkn itm, Bry_bfr tmp) {
if (itm.Itm_static() == Bool_.Y_byte)
@@ -86,6 +88,6 @@ public class Pfunc_switch extends Pf_func_base {
return tmp.To_bry_and_clear_and_trim();
}
}
public static final byte[] Dflt_keyword = Bry_.new_a7("#default"); // NOTE: technically should pull from messages, but would need to cache Dflt_keyword on wiki level; checked all Messages files, and no one overrides it; DATE:2014-05-29
public static final byte[] Dflt_keyword = Bry_.new_a7("#default"); // NOTE: technically should pull from messages, but would need to cache Dflt_keyword on wiki level; checked all Messages files, and no one overrides it; DATE:2014-05-29
private static int Dflt_keyword_len = Dflt_keyword.length;
}

View File

@@ -25,7 +25,7 @@ public class Pfunc_displaytitle extends Pf_func_base {
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
byte[] val_dat_ary = Eval_argx(ctx, src, caller, self);
Xowe_wiki wiki = ctx.Wiki(); Xop_parser parser = wiki.Parser_mgr().Main();
Xop_ctx display_ttl_ctx = Xop_ctx.new_sub_(wiki);
Xop_ctx display_ttl_ctx = Xop_ctx.new_sub_(ctx);
Xop_root_tkn display_ttl_root = parser.Parse_text_to_wdom(display_ttl_ctx, val_dat_ary, false);
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512();
boolean restrict = wiki.Cfg_parser().Display_title_restrict();

View File

@@ -17,33 +17,33 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.xtns.pfuncs.pages; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*;
import gplx.xowa.wikis.pages.*; import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*;
import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.dbs.*; import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*;
public class Pfunc_rev_props extends Pf_func_base {
public Pfunc_rev_props(int id) {this.id = id;}
@Override public int Id() {return id;} private final int id;
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_rev_props(id).Name_(name);}
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
byte[] argx = Eval_argx(ctx, src, caller, self);
Xopg_revision_data rev_data = ctx.Page().Revision_data();
Xopg_db_protection rev_data = ctx.Page().Db().Protection();
switch (id) {
case Xol_kwd_grp_.Id_page_id:
case Xol_kwd_grp_.Id_rev_id: bfr.Add_int_variable(ctx.Page().Revision_data().Id()); break; // NOTE: making rev_id and page_id interchangeable; XOWA does not store rev_id
case Xol_kwd_grp_.Id_rev_id: bfr.Add_int_variable(ctx.Page().Db().Page().Id()); break; // NOTE: making rev_id and page_id interchangeable; XOWA does not store rev_id
case Xol_kwd_grp_.Id_rev_user: bfr.Add(rev_data.User()); break;
case Xol_kwd_grp_.Id_rev_protectionlevel: bfr.Add(rev_data.Protection_level()); break;
case Xol_kwd_grp_.Id_rev_protectionexpiry: bfr.Add(rev_data.Protection_expiry()); break;
case Xol_kwd_grp_.Id_rev_revisionsize: // default revsize to pagesize; MW has additional logic for subst which should not apply to XO; https://gerrit.wikimedia.org/r/#/c/82650/
bfr.Add_int_variable(ctx.Page().Data_raw().length);
bfr.Add_int_variable(ctx.Page().Db().Text().Text_bry().length);
break;
case Xol_kwd_grp_.Id_rev_pagesize:
if (argx.length > 0) {
Xoa_ttl argx_ttl = Xoa_ttl.parse(ctx.Wiki(), argx);
Xoa_ttl argx_ttl = Xoa_ttl.Parse(ctx.Wiki(), argx);
if (argx_ttl == null) { // invalid ttl; EX: {{PAGESIZE:{{{bad}}}}}
bfr.Add_byte(Byte_ascii.Num_0);
return;
}
Xoae_page argx_page = ctx.Wiki().Data_mgr().Load_page_by_ttl(argx_ttl);
if (!argx_page.Missing()) {
bfr.Add_int_variable(argx_page.Data_raw().length);
if (argx_page.Db().Page().Exists()) {
bfr.Add_int_variable(argx_page.Db().Text().Text_bry().length);
return;
}
}

View File

@@ -18,17 +18,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.xtns.pfuncs.pages; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*; import gplx.xowa.wikis.ttls.*;
public class Pfunc_rev_props_tst {
private final Xop_fxt fxt = new Xop_fxt();
@Before public void setup() {fxt.Reset(); fxt.Page().Revision_data().User_(Bry_.new_a7("user")).Protection_level_(Bry_.new_a7("normal"));}
@Test public void Revision_id() {fxt.Page().Revision_data().Id_(1); fxt.Test_parse_tmpl_str_test("{{REVISIONID}}" , "{{test}}", "1");}
@Test public void Page_id() {fxt.Page().Revision_data().Id_(1); fxt.Test_parse_tmpl_str_test("{{PAGEID}}" , "{{test}}", "1");}
private final Xop_fxt fxt = new Xop_fxt();
@Before public void setup() {fxt.Reset(); fxt.Page().Db().Protection().User_(Bry_.new_a7("user")).Protection_level_(Bry_.new_a7("normal"));}
@Test public void Revision_id() {fxt.Page().Db().Page().Id_(1); fxt.Test_parse_tmpl_str_test("{{REVISIONID}}" , "{{test}}", "1");}
@Test public void Page_id() {fxt.Page().Db().Page().Id_(1); fxt.Test_parse_tmpl_str_test("{{PAGEID}}" , "{{test}}", "1");}
@Test public void Revision_user() {fxt.Test_parse_tmpl_str_test("{{REVISIONUSER}}" , "{{test}}", "user");}
@Test public void Page_size() {fxt.Test_parse_tmpl_str_test("{{PAGESIZE:Test page}}" , "{{test}}", "0");}
@Test public void Revision_size() {fxt.Test_parse_tmpl_str_test("{{REVISIONSIZE}}" , "{{test}}", "8");}
@Test public void Protection_level() {fxt.Test_parse_tmpl_str_test("{{PROTECTIONLEVEL}}" , "{{test}}", "normal");}
@Test public void Protection_expiry() {fxt.Test_parse_tmpl_str_test("{{PROTECTIONEXPIRY}}" , "{{test}}", "infinite");}
@Test public void PageSize_invalid_ttl() {
fxt.Init_log_(Xop_ttl_log.Invalid_char);
fxt.Test_parse_tmpl_str_test("{{PAGESIZE:{{{100}}}|R}}" , "{{test}}", "0");
}
@Test public void PageSize_invalid_ttl() {fxt.Test_parse_tmpl_str_test("{{PAGESIZE:{{{100}}}|R}}" , "{{test}}", "0");}
}

View File

@@ -164,52 +164,55 @@ public class Pft_fmt_itm_ {
// TODO_OLD: space; "
;
public static Pft_fmt_itm[] Parse(Xop_ctx ctx, byte[] fmt) {
Btrie_fast_mgr trie = Pft_fmt_itm_.Regy;
int i = 0, fmt_len = fmt.length;
fmt_itms.Clear(); int raw_bgn = String_.Pos_neg1; byte raw_byt = Byte_.Zero;
while (i < fmt_len) {
byte b = fmt[i];
Object o = trie.Match_bgn_w_byte(b, fmt, i, fmt_len);
if (o != null) {
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
fmt_itms.Add((Pft_fmt_itm)o);
i = trie.Match_pos();
}
else {
switch (b) {
case Byte_ascii.Backslash:
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
++i; // peek next char
if (i == fmt_len) // trailing backslash; add one; EX: "b\" -> "b\" not "b"
fmt_itms.Add(new Pft_fmt_itm_raw_byt(Byte_ascii.Backslash));
else
fmt_itms.Add(new Pft_fmt_itm_raw_byt(fmt[i]));
++i;
break;
case Byte_ascii.Quote:
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
++i; // skip quote_bgn
raw_bgn = i;
while (i < fmt_len) {
b = fmt[i];
if (b == Byte_ascii.Quote) {
break;
}
synchronized (fmt_itms) { // LOCK:static-obj; DATE:2016-07-06
Btrie_fast_mgr trie = Pft_fmt_itm_.Regy;
Btrie_rv trv = new Btrie_rv();
int i = 0, fmt_len = fmt.length;
fmt_itms.Clear(); int raw_bgn = String_.Pos_neg1; byte raw_byt = Byte_.Zero;
while (i < fmt_len) {
byte b = fmt[i];
Object o = trie.Match_at_w_b0(trv, b, fmt, i, fmt_len);
if (o != null) {
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
fmt_itms.Add((Pft_fmt_itm)o);
i = trv.Pos();
}
else {
switch (b) {
case Byte_ascii.Backslash:
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
++i; // peek next char
if (i == fmt_len) // trailing backslash; add one; EX: "b\" -> "b\" not "b"
fmt_itms.Add(new Pft_fmt_itm_raw_byt(Byte_ascii.Backslash));
else
++i;
}
fmt_itms.Add(i - raw_bgn == 0 ? new Pft_fmt_itm_raw_byt(Byte_ascii.Quote) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i));
raw_bgn = String_.Pos_neg1;
++i; // skip quote_end
break;
default:
if (raw_bgn == String_.Pos_neg1) {raw_bgn = i; raw_byt = b;}
i += gplx.core.intls.Utf8_.Len_of_char_by_1st_byte(b);
break;
fmt_itms.Add(new Pft_fmt_itm_raw_byt(fmt[i]));
++i;
break;
case Byte_ascii.Quote:
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
++i; // skip quote_bgn
raw_bgn = i;
while (i < fmt_len) {
b = fmt[i];
if (b == Byte_ascii.Quote) {
break;
}
else
++i;
}
fmt_itms.Add(i - raw_bgn == 0 ? new Pft_fmt_itm_raw_byt(Byte_ascii.Quote) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i));
raw_bgn = String_.Pos_neg1;
++i; // skip quote_end
break;
default:
if (raw_bgn == String_.Pos_neg1) {raw_bgn = i; raw_byt = b;}
i += gplx.core.intls.Utf8_.Len_of_char_by_1st_byte(b);
break;
}
}
}
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(fmt_len - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(fmt[fmt_len - 1]) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, fmt_len)); raw_bgn = String_.Pos_neg1;}
return (Pft_fmt_itm[])fmt_itms.To_ary(Pft_fmt_itm.class);
}
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(fmt_len - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(fmt[fmt_len - 1]) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, fmt_len)); raw_bgn = String_.Pos_neg1;}
return (Pft_fmt_itm[])fmt_itms.To_ary(Pft_fmt_itm.class);
} private static List_adp fmt_itms = List_adp_.New();
}

View File

@@ -28,7 +28,7 @@ public class Pft_func_date_int extends Pf_func_base {
switch (date_tid) {
case Date_tid_lcl: date = DateAdp_.Now(); break;
case Date_tid_utc: date = DateAdp_.Now().XtoUtc(); break;
case Date_tid_rev: date = ctx.Page().Revision_data().Modified_on(); break;
case Date_tid_rev: date = ctx.Page().Db().Page().Modified_on(); break;
default: throw Err_.new_unhandled(date_tid);
}
switch (id) {
@@ -87,7 +87,7 @@ public class Pft_func_date_int extends Pf_func_base {
}
}
public static final int Date_tid_utc = 0, Date_tid_lcl = 1, Date_tid_rev = 2;
public static final Pft_func_date_int
public static final Pft_func_date_int
Utc = new Pft_func_date_int(-1, Date_tid_utc)
, Lcl = new Pft_func_date_int(-1, Date_tid_lcl)
, Rev = new Pft_func_date_int(-1, Date_tid_rev);

View File

@@ -26,7 +26,7 @@ public class Pft_func_date_name extends Pf_func_base {
switch (date_tid) {
case Pft_func_date_int.Date_tid_lcl: date = DateAdp_.Now(); break;
case Pft_func_date_int.Date_tid_utc: date = DateAdp_.Now().XtoUtc(); break;
case Pft_func_date_int.Date_tid_rev: date = ctx.Page().Revision_data().Modified_on(); break;
case Pft_func_date_int.Date_tid_rev: date = ctx.Page().Db().Page().Modified_on(); break;
default: throw Err_.new_unhandled(date_tid);
}
byte[] val = ctx.Wiki().Msg_mgr().Val_by_id(base_idx + date.Segment(seg_idx));

View File

@@ -18,8 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*;
public class Pft_func_date_rev_tst {
private final Xop_fxt fxt = new Xop_fxt();
@Before public void setup() {fxt.Reset(); fxt.Page().Revision_data().Modified_on_(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));}
private final Xop_fxt fxt = new Xop_fxt();
@Before public void setup() {fxt.Reset(); fxt.Page().Db().Page().Modified_on_(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));}
@After public void teardown() {}
@Test public void Rev_year() {fxt.Test_parse_tmpl_str_test("{{REVISIONYEAR}}" , "{{test}}", "2012");}
@Test public void Rev_month_int() {fxt.Test_parse_tmpl_str_test("{{REVISIONMONTH1}}" , "{{test}}", "1");}

View File

@@ -20,44 +20,48 @@ import gplx.xowa.langs.*;
public class Pft_func_formatdate_bldr {
public int Idx_cur() {return idx_cur;} private int idx_cur;
public Pft_func_formatdate_bldr Idx_nxt_(int v) {idx_nxt = v; return this;} private int idx_nxt;
public Pft_fmt_itm[] Fmt_itms() {return fmt_itms;} Pft_fmt_itm[] fmt_itms;
public Pft_fmt_itm[] Fmt_itms() {return fmt_itms;} private Pft_fmt_itm[] fmt_itms;
public void Format(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang_itm lang, DateAdp date, Pft_fmt_itm fmt_itm) {
fmt_itm.Fmt(bfr, wiki, lang, date, this);
synchronized (this) { // LOCK:static-obj;Pft_func_formatdate.Date_bldr(); DATE:2016-07-07
fmt_itm.Fmt(bfr, wiki, lang, date, this);
}
}
public void Format(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang_itm lang, DateAdp date, Pft_fmt_itm[] fmt_itms) {
this.fmt_itms = fmt_itms;
int len = fmt_itms.length;
idx_cur = 0; idx_nxt = -1;
Pft_fmt_itm chained_fmt = null;
while (idx_cur < len) {
Pft_fmt_itm fmt_itm = fmt_itms[idx_cur];
if (fmt_itm.TypeId() == Pft_fmt_itm_.Tid_hebrew_numeral)
chained_fmt = fmt_itm;
else {
if (chained_fmt != null) {
Bry_bfr tmp_bfr = Xoa_app_.Utl__bfr_mkr().Get_b128();
synchronized (tmp_bfr) {
fmt_itm.Fmt(tmp_bfr, wiki, lang, date, this);
chained_fmt.Fmt(tmp_bfr, wiki, lang, date, this);
bfr.Add(tmp_bfr.To_bry_and_rls());
chained_fmt = null;
synchronized (this) { // LOCK:static-obj;Pft_func_formatdate.Date_bldr(); DATE:2016-07-07
this.fmt_itms = fmt_itms;
int len = fmt_itms.length;
idx_cur = 0; idx_nxt = -1;
Pft_fmt_itm chained_fmt = null;
while (idx_cur < len) {
Pft_fmt_itm fmt_itm = fmt_itms[idx_cur];
if (fmt_itm.TypeId() == Pft_fmt_itm_.Tid_hebrew_numeral)
chained_fmt = fmt_itm;
else {
if (chained_fmt != null) {
Bry_bfr tmp_bfr = Xoa_app_.Utl__bfr_mkr().Get_b128();
synchronized (tmp_bfr) {
fmt_itm.Fmt(tmp_bfr, wiki, lang, date, this);
chained_fmt.Fmt(tmp_bfr, wiki, lang, date, this);
bfr.Add(tmp_bfr.To_bry_and_rls());
chained_fmt = null;
}
}
else
fmt_itm.Fmt(bfr, wiki, lang, date, this);
}
if (idx_nxt == -1)
++idx_cur;
else {
idx_cur = idx_nxt;
idx_nxt = -1;
}
else
fmt_itm.Fmt(bfr, wiki, lang, date, this);
}
if (idx_nxt == -1)
++idx_cur;
else {
idx_cur = idx_nxt;
idx_nxt = -1;
}
}
if (chained_fmt != null) {
int year_int = bfr.To_int_and_clear(-1);
if (year_int != -1) { // handle no format; EX:{{#time:xh}} DATE:2014-07-20
date = DateAdp_.seg_(new int[] {year_int, date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()});
chained_fmt.Fmt(bfr, wiki, lang, date, this);
if (chained_fmt != null) {
int year_int = bfr.To_int_and_clear(-1);
if (year_int != -1) { // handle no format; EX:{{#time:xh}} DATE:2014-07-20
date = DateAdp_.seg_(new int[] {year_int, date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()});
chained_fmt.Fmt(bfr, wiki, lang, date, this);
}
}
}
}

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
import org.junit.*; import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
public class Pft_func_time__basic__tst {
@Before public void init() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));} private final Xop_fxt fxt = new Xop_fxt();
@Before public void init() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));} private final Xop_fxt fxt = new Xop_fxt();
@After public void term() {Tfds.Now_enabled_n_();}
@Test public void Utc_date() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-01-02 03:04:05}}" , "2012-01-02");}
@Test public void Utc_time() {fxt.Test_parse_tmpl_str("{{#time:h:i:s A|2012-01-02 03:04:05}}" , "03:04:05 AM");}

View File

@@ -23,8 +23,8 @@ interface Pxd_itm {
int Seg_idx();
int Eval_idx();
int Data_idx(); void Data_idx_(int v);
void Eval(Pxd_parser state);
void Time_ini(DateAdpBldr bldr);
boolean Eval(Pxd_parser state);
boolean Time_ini(DateAdpBldr bldr);
}
class Pxd_itm_ {
public static final int
@@ -60,6 +60,7 @@ class Pxd_itm_ {
int len = tkns.length;
for (int i = bgn; i < len; i++) {
Pxd_itm itm = tkns[i];
if (itm == null) return null; // PAGE:s.w:Synesthesia EX:"March 2006 [last update]"; DATE:2016-07-06
if (tid == itm.Tkn_tid()) return itm;
}
return null;
@@ -73,8 +74,8 @@ abstract class Pxd_itm_base implements Pxd_itm {
public void Seg_idx_(int v) {seg_idx = v;}
public int Data_idx() {return data_idx;} public void Data_idx_(int v) {data_idx = v;} private int data_idx;
public abstract int Eval_idx();
@gplx.Virtual public void Eval(Pxd_parser state) {}
@gplx.Virtual public void Time_ini(DateAdpBldr bldr) {}
@gplx.Virtual public boolean Eval(Pxd_parser state) {return true;}
@gplx.Virtual public boolean Time_ini(DateAdpBldr bldr) {return true;}
public void Ctor(int ary_idx) {this.ary_idx = ary_idx;}
public static final int Seg_idx_null = -1, Seg_idx_skip = -2;
}
@@ -91,7 +92,7 @@ class DateAdpBldr {
return DateAdp_.Now(); // not dirtied; default to now;
}
public DateAdpBldr Date_(DateAdp v) {date = v; return this;} DateAdp date = null;
public DateAdpBldr Seg_set(int idx, int val) {
public void Seg_set(int idx, int val) {
if (date == null) seg_ary[idx] = val;
else {
seg_ary = date.XtoSegAry();
@@ -99,7 +100,6 @@ class DateAdpBldr {
date = DateAdp_.seg_(seg_ary);
}
dirty = true;
return this;
}
public DateAdp Bld() {
return date == null ? DateAdp_.seg_(seg_ary) : date;
@@ -108,8 +108,8 @@ class DateAdpBldr {
int[] seg_ary = new int[DateAdp_.SegIdx__max]; boolean dirty = false;
}
class Pft_func_time_log {
private static final Gfo_msg_grp owner = Gfo_msg_grp_.new_(Xoa_app_.Nde, "time_parser");
public static final Gfo_msg_itm
private static final Gfo_msg_grp owner = Gfo_msg_grp_.new_(Xoa_app_.Nde, "time_parser");
public static final Gfo_msg_itm
Invalid_day = Gfo_msg_itm_.new_warn_(owner, "Invalid day: ~{0}")
, Invalid_month = Gfo_msg_itm_.new_warn_(owner, "Invalid month: ~{0}")
, Invalid_year = Gfo_msg_itm_.new_warn_(owner, "Invalid year: ~{0}")

View File

@@ -43,16 +43,16 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
public boolean Val_is_adj() {return val_is_adj;} public void Val_is_adj_(boolean v) {val_is_adj = v;} private boolean val_is_adj;
public int Xto_int_or(int or) {return val;}
public int Digits() {return digits;} private int digits;
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Time_ini(DateAdpBldr bldr) {
int seg_idx = this.Seg_idx();
if (seg_idx == Pxd_itm_base.Seg_idx_skip) return;
if (seg_idx == Pxd_itm_base.Seg_idx_skip) return true;
if (val_is_adj) {
if (val == 0) return; // no adjustment to make
if (val == 0) return true; // no adjustment to make
DateAdp date = bldr.Date();
switch (seg_idx) {
case DateAdp_.SegIdx_hour: date = date.Add_hour(val); break;
case DateAdp_.SegIdx_minute: date = date.Add_minute(val); break;
default: return;
default: return true;
}
bldr.Date_(date);
}
@@ -62,22 +62,25 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
switch (seg_idx) {
case DateAdp_.SegIdx_month: date = DateAdp_.seg_(new int[] {date.Year(), 1, date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_month(-1); bldr.Date_(date); break;
case DateAdp_.SegIdx_day: date = DateAdp_.seg_(new int[] {date.Year(), date.Month(), 1, date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_day(-1); bldr.Date_(date); break;
default: return;
default: return true;
}
}
else
else {
if (seg_idx == -1) return false; // PAGE:New_York_City EX: March 14, 2,013; DATE:2016-07-06
bldr.Seg_set(seg_idx, val);
}
}
return true;
}
@Override public void Eval(Pxd_parser tctx) {
@Override public boolean Eval(Pxd_parser tctx) {
int data_idx = this.Data_idx();
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return true; // has seg_idx; already eval'd by something else
switch (digits) {
case 5: // 5 digits
switch (data_idx) {
case 0: Pxd_eval_year.Eval_at_pos_0(tctx, this); break; // year at pos 0; EX: 01234-02-03
case 1: tctx.Err_set(Pft_func_time_log.Invalid_date); return; // year at pos 1; invalid; EX: 01-01234-02
case 2: tctx.Err_set(Pft_func_time_log.Invalid_date); break; // year at pos 2; invalid; EX: 01-02-01234
case 1: tctx.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_bry(tctx.Src())); return false; // year at pos 1; invalid; EX: 01-01234-02
case 2: tctx.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_bry(tctx.Src())); break; // year at pos 2; invalid; EX: 01-02-01234
}
val = 2000 + (val % 10); // NOTE: emulate PHP's incorrect behavior with 5 digit years; EX:ca.w:Nicolau_de_Mira; DATE:2014-04-18
tctx.Seg_idxs_(this, DateAdp_.SegIdx_year);
@@ -85,7 +88,7 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
case 4: // 4 digits; assume year
switch (data_idx) {
case 0: Pxd_eval_year.Eval_at_pos_0(tctx, this); break; // year at pos 0; EX: 2001-02-03
case 1: tctx.Err_set(Pft_func_time_log.Invalid_year_mid); return;// year at pos 1; invalid; EX: 02-2003-03
case 1: tctx.Err_set(Pft_func_time_log.Invalid_year_mid); return false;// year at pos 1; invalid; EX: 02-2003-03
case 2: Pxd_eval_year.Eval_at_pos_2(tctx, this); break; // year at pos 2; EX: 02-03-2001
default: Pxd_eval_year.Eval_at_pos_n(tctx, this); break; // year at pos n; EX: 04:05 02-03-2001
}
@@ -101,7 +104,7 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
&& rhs_itm != null && rhs_itm.Seg_idx() == DateAdp_.SegIdx_year // itm on right is year
&& tctx.Seg_idxs()[DateAdp_.SegIdx_day] == -1 // day not yet set; needed for {{#time:Y|July 28 - August 1, 1975}}
)
if (!Pxd_eval_seg.Eval_as_d(tctx, cur_itm)) return; // cur int should be day; EX:January 1, 2010; PAGE:en.w:Wikipedia:WikiProject_Maine/members; DATE:2014-06-25
if (!Pxd_eval_seg.Eval_as_d(tctx, cur_itm)) return true; // cur int should be day; EX:January 1, 2010; PAGE:en.w:Wikipedia:WikiProject_Maine/members; DATE:2014-06-25
if (val > Month_max) { // value is not a month; assume day; DATE:2013-03-15
switch (data_idx) {
case 0: // > 12 in slot 0
@@ -131,6 +134,7 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
}
break;
}
return true;
}
public static final int Month_max = 12;
private void Eval_unknown_at_pos_3(Pxd_parser tctx) { // int at pos 4
@@ -148,7 +152,8 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
int sym_idx = this.Ary_idx() + (fwd ? 1 : -1);
Pxd_itm[] sym_tkns = tctx.Tkns();
if (sym_idx < 0 || sym_idx > sym_tkns.length) return false; // NOTE: was Data_ary_len; DATE:2013-06-19
return sym_tkns[sym_idx].Tkn_tid() == sym_tid;
Pxd_itm sym_tkn = sym_tkns[sym_idx];
return sym_tkn == null ? false : sym_tkn.Tkn_tid() == sym_tid; // PAGE:s.w:Byzantine_Empire EX:285 DATE:2016-07-06
}
private void Eval_month_at_pos_0(Pxd_parser tctx) {
Pxd_itm[] data_ary = tctx.Data_ary();
@@ -249,6 +254,7 @@ class Pxd_itm_int_ {
}
for (int i = tkn_idx + adj; i != end; i += adj) {
Pxd_itm itm = tkns[i];
if (itm == null) return null; // PAGE:s.w:Leonid_Hurwicz EX:"1944, 2004, [[7 August]] [[2007]]"; DATE:2016-07-06
if (itm.Tkn_tid() == Pxd_itm_.Tid_int) {
Pxd_itm_int itm_int = (Pxd_itm_int)itm;
return itm_int.Seg_idx() == -1 ? itm_int : null;

View File

@@ -20,42 +20,43 @@ import gplx.core.brys.*;
class Pxd_itm_colon extends Pxd_itm_base {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_colon;}
@Override public int Eval_idx() {return 20;}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
int colon_count = ++state.Colon_count;
Pxd_itm[] tkns = state.Tkns();
Pxd_itm_int itm_int = null;
switch (colon_count) {
case 1: // hh:mm
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.N);
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_hour, Bfr_arg_.New_bry("null")); return;}
if (!Pxd_eval_seg.Eval_as_h(state, itm_int)) return;
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_hour, Bfr_arg_.New_bry("null")); return false;}
if (!Pxd_eval_seg.Eval_as_h(state, itm_int)) return true;
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), true);
if (!Pxd_eval_seg.Eval_as_n(state, itm_int)) return;
if (!Pxd_eval_seg.Eval_as_n(state, itm_int)) return true;
break;
case 2: // :ss
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), true);
if (!Pxd_eval_seg.Eval_as_s(state, itm_int)) return;
if (!Pxd_eval_seg.Eval_as_s(state, itm_int)) return true;
break;
case 3: // +hh:mm; DATE:2014-08-26
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.N);
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bfr_arg_.New_bry("null")); return;}
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bfr_arg_.New_bry("null")); return false;}
byte tz_positive_val = Pxd_eval_seg.Eval_as_tz_sym(state, tkns, itm_int);
if (tz_positive_val == Bool_.__byte) return;
if (tz_positive_val == Bool_.__byte) return true;
boolean tz_negative = tz_positive_val == Bool_.N_byte;
if (!Pxd_eval_seg.Eval_as_tz_h(state, itm_int, tz_negative)) return;
if (!Pxd_eval_seg.Eval_as_tz_h(state, itm_int, tz_negative)) return true;
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.Y);
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bfr_arg_.New_bry("null")); return;}
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bfr_arg_.New_bry("null")); return false;}
if (tz_negative) itm_int.Val_(itm_int.Val() * -1);
if (!Pxd_eval_seg.Eval_as_tz_m(state, itm_int, tz_negative)) return;
if (!Pxd_eval_seg.Eval_as_tz_m(state, itm_int, tz_negative)) return true;
break;
}
return true;
}
public Pxd_itm_colon(int ary_idx) {this.Ctor(ary_idx);}
}
class Pxd_itm_null extends Pxd_itm_base {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_null;}
@Override public int Eval_idx() {return 99;}
public static final Pxd_itm_null Instance = new Pxd_itm_null();
public static final Pxd_itm_null Instance = new Pxd_itm_null();
}
class Pxd_itm_dash extends Pxd_itm_base {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_dash;}
@@ -80,7 +81,7 @@ class Pxd_itm_slash extends Pxd_itm_base {
class Pxd_itm_sym extends Pxd_itm_base {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_sym;}
@Override public int Eval_idx() {return 99;}
@Override public void Time_ini(DateAdpBldr bldr) {}
@Override public boolean Time_ini(DateAdpBldr bldr) {return true;}
public byte Sym_byte() {return sym_byte;} private byte sym_byte;
public Pxd_itm_sym(int ary_idx, byte val) {this.Ctor(ary_idx); this.sym_byte = val;}
}
@@ -89,8 +90,8 @@ class Pxd_itm_int_dmy_14 extends Pxd_itm_base implements Pxd_itm_int_interface {
public int Xto_int_or(int or) {return Bry_.To_int_or(src, or);}
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_int_dmy_14;}
@Override public int Eval_idx() {return eval_idx;} private int eval_idx = 20;
@Override public void Time_ini(DateAdpBldr bldr) {
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
@Override public boolean Time_ini(DateAdpBldr bldr) {
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return true; // has seg_idx; already eval'd by something else
bldr.Seg_set(DateAdp_.SegIdx_year , Bry_.To_int_or(src, 0, 4, 0));
bldr.Seg_set(DateAdp_.SegIdx_month , Bry_.To_int_or(src, 4, 6, 0));
if (digits > 6) {
@@ -104,6 +105,7 @@ class Pxd_itm_int_dmy_14 extends Pxd_itm_base implements Pxd_itm_int_interface {
}
}
}
return true;
}
}
class Pxd_itm_int_mhs_6 extends Pxd_itm_base implements Pxd_itm_int_interface {
@@ -111,11 +113,12 @@ class Pxd_itm_int_mhs_6 extends Pxd_itm_base implements Pxd_itm_int_interface {
public int Xto_int_or(int or) {return Bry_.To_int_or(src, or);}
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_int_hms_6;}
@Override public int Eval_idx() {return eval_idx;} private int eval_idx = 20;
@Override public void Time_ini(DateAdpBldr bldr) {
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
@Override public boolean Time_ini(DateAdpBldr bldr) {
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return true; // has seg_idx; already eval'd by something else
bldr.Seg_set(DateAdp_.SegIdx_hour , Bry_.To_int_or(src, 0, 2, 0));
bldr.Seg_set(DateAdp_.SegIdx_minute , Bry_.To_int_or(src, 2, 4, 0));
bldr.Seg_set(DateAdp_.SegIdx_second , Bry_.To_int_or(src, 4, 6, 0));
return true;
}
}
class Pxd_itm_sorter implements gplx.core.lists.ComparerAble {
@@ -124,7 +127,7 @@ class Pxd_itm_sorter implements gplx.core.lists.ComparerAble {
Pxd_itm rhs = (Pxd_itm)rhsObj;
return Int_.Compare(lhs.Eval_idx(), rhs.Eval_idx());
}
public static final Pxd_itm_sorter Instance = new Pxd_itm_sorter();
public static final Pxd_itm_sorter Instance = new Pxd_itm_sorter();
public static Pxd_itm[] XtoAryAndSort(Pxd_itm[] src, int src_len) {
Pxd_itm[] rv = new Pxd_itm[src_len];
for (int i = 0; i < src_len; i++)

View File

@@ -26,7 +26,7 @@ class Pxd_itm_month_name extends Pxd_itm_base implements Pxd_itm_prototype {
Pxd_itm_month_name rv = new Pxd_itm_month_name(ary_idx, name, this.Seg_idx(), seg_val);
return rv;
}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
state.Seg_idxs_(this, this.Seg_idx(), seg_val);
switch (this.Data_idx()) {
case 0: Eval_month_0(state); break;
@@ -36,15 +36,19 @@ class Pxd_itm_month_name extends Pxd_itm_base implements Pxd_itm_prototype {
Pxd_itm[] data_ary = state.Data_ary();
int data_idx = this.Data_idx();
if (data_idx + 1 < data_ary.length) {
Pxd_itm_int itm_rhs = Pxd_itm_int_.CastOrNull(data_ary[data_idx + 1]);
Pxd_itm itm = data_ary[data_idx + 1];
if (itm == null) return false; // PAGE:s.w:Leonid_Hurwicz EX:1944, 2004, [[7 August]] [[2007]] DATE:2016-07-06
Pxd_itm_int itm_rhs = Pxd_itm_int_.CastOrNull(itm);
if (itm_rhs == null) return false; // PAGE:s.w:Leonid_Hurwicz EX:1944, 2004, [[7 August]] [[2007]] DATE:2016-07-06
if (itm_rhs.Digits() == 4) { // handle fmts of 1 January 2010
Eval_month_1(state);
return;
return true;
}
}
Eval_month_2(state);
break;
}
return true;
}
public void Eval_month_0(Pxd_parser state) {
Pxd_itm[] data_ary = state.Data_ary();
@@ -140,8 +144,9 @@ class Pxd_itm_month_name extends Pxd_itm_base implements Pxd_itm_prototype {
}
}
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Time_ini(DateAdpBldr bldr) {
bldr.Seg_set(this.Seg_idx(), seg_val);
return true;
}
}
class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype {
@@ -157,11 +162,12 @@ class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype {
seg_val = v; seg_multiple = 1;
eval_done_by_relative = true;
} private boolean eval_done_by_relative;
@Override public void Eval(Pxd_parser state) {
if (eval_done_by_relative) return;
@Override public boolean Eval(Pxd_parser state) {
if (eval_done_by_relative) return true;
state.Seg_idxs_(this, this.Seg_idx(), seg_val);
Pxd_itm[] tkns = state.Tkns();
Pxd_itm_int itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), false);
if (itm_int == null) return false; // PAGE:s.w:Crich_Tramway_Village EX:Yearly DATE:2016-07-06
state.Seg_idxs_(itm_int, Pxd_itm_base.Seg_idx_skip);
seg_val = itm_int.Val();
for (int i = itm_int.Ary_idx(); i > -1; i--) {
@@ -178,8 +184,9 @@ class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype {
break;
}
}
return true;
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Time_ini(DateAdpBldr bldr) {
DateAdp cur = bldr.Date();
if (cur == null) cur = DateAdp_.Now();
int val = seg_val * seg_multiple;
@@ -193,15 +200,16 @@ class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype {
default: throw Err_.new_unhandled(this.Seg_idx());
}
bldr.Date_(cur);
return true;
}
}
class Pxd_itm_ago extends Pxd_itm_base implements Pxd_itm_prototype {
public Pxd_itm_ago(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
public byte[] Name() {return Name_ago;} public static final byte[] Name_ago = Bry_.new_a7("ago");
public byte[] Name() {return Name_ago;} public static final byte[] Name_ago = Bry_.new_a7("ago");
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_ago;}
@Override public int Eval_idx() {return 5;} // set to high priority so it can evaluate before unit_name
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_ago(ary_idx, this.Seg_idx());}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
Pxd_itm[] tkns = state.Tkns();
int end = this.Ary_idx();
boolean unit_seen = false;
@@ -220,42 +228,43 @@ class Pxd_itm_ago extends Pxd_itm_base implements Pxd_itm_prototype {
default: break;
}
}
return true;
}
@Override public void Time_ini(DateAdpBldr bldr) {
}
@Override public boolean Time_ini(DateAdpBldr bldr) {return true;}
}
class Pxd_itm_day_suffix extends Pxd_itm_base implements Pxd_itm_prototype {
public Pxd_itm_day_suffix(int ary_idx) {Ctor(ary_idx);}
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_day_suffix;}
@Override public int Eval_idx() {return 99;} // set to low priority so it can evaluate after day
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_day_suffix(ary_idx);}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
Pxd_itm[] tkn_ary = state.Tkns();
int tkn_idx = this.Ary_idx();
if (tkn_idx == 0) state.Err_set(Pft_func_time_log.Invalid_day, Bfr_arg_.New_int(Int_.Min_value));
if (tkn_idx == 0) {state.Err_set(Pft_func_time_log.Invalid_day, Bfr_arg_.New_int(Int_.Min_value)); return false;} // PAGE:s.w:Aachen EX: "936" DATE:2016-07-06
Pxd_itm day_itm = tkn_ary[tkn_idx - 1];
if (day_itm.Seg_idx() != DateAdp_.SegIdx_day) {
state.Err_set(Pft_func_time_log.Invalid_day, Bfr_arg_.New_int(Int_.Min_value));
}
return true;
}
public static final Pxd_itm_day_suffix Instance = new Pxd_itm_day_suffix(); Pxd_itm_day_suffix() {}
public static final Pxd_itm_day_suffix Instance = new Pxd_itm_day_suffix(); Pxd_itm_day_suffix() {}
}
class Pxd_itm_day_relative extends Pxd_itm_base implements Pxd_itm_prototype {
public Pxd_itm_day_relative(int adj, int ary_idx) {Ctor(ary_idx); this.adj = adj;}
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_day_relative;}
@Override public int Eval_idx() {return 5;}
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_day_relative(adj, ary_idx);}
@Override public void Eval(Pxd_parser state) {
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Eval(Pxd_parser state) {return true;}
@Override public boolean Time_ini(DateAdpBldr bldr) {
DateAdp date = DateAdp_.Now();
if (adj != 0) date = date.Add_day(adj);
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
bldr.Seg_set(DateAdp_.SegIdx_day , date.Day());
return true;
}
public static final Pxd_itm_day_relative
public static final Pxd_itm_day_relative
Today = new Pxd_itm_day_relative(0)
, Tomorrow = new Pxd_itm_day_relative(1)
, Yesterday = new Pxd_itm_day_relative(-1)
@@ -267,9 +276,8 @@ class Pxd_itm_time_relative extends Pxd_itm_base implements Pxd_itm_prototype {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_time_relative;}
@Override public int Eval_idx() {return 5;}
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_time_relative(ary_idx);}
@Override public void Eval(Pxd_parser state) {
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Eval(Pxd_parser state) {return true;}
@Override public boolean Time_ini(DateAdpBldr bldr) {
DateAdp date = DateAdp_.Now();
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
@@ -278,8 +286,9 @@ class Pxd_itm_time_relative extends Pxd_itm_base implements Pxd_itm_prototype {
bldr.Seg_set(DateAdp_.SegIdx_minute , date.Minute());
bldr.Seg_set(DateAdp_.SegIdx_second , date.Second());
bldr.Seg_set(DateAdp_.SegIdx_frac , date.Frac());
return true;
}
public static final Pxd_itm_time_relative
public static final Pxd_itm_time_relative
Now = new Pxd_itm_time_relative()
;
Pxd_itm_time_relative() {}
@@ -289,15 +298,16 @@ class Pxd_itm_unit_relative extends Pxd_itm_base implements Pxd_itm_prototype {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_unit_relative;}
@Override public int Eval_idx() {return 5;}
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_unit_relative(adj, ary_idx);}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
Pxd_itm itm = Pxd_itm_.Find_fwd_by_tid(state.Tkns(), this.Ary_idx() + 1, Pxd_itm_.Tid_unit);
if (itm == null) state.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_int(adj));
Pxd_itm_unit unit_tkn = (Pxd_itm_unit)itm;
if (unit_tkn == null) {state.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_int(adj)); return false;} // PAGE:s.w:Synesthesia EX:"March 2006 [last update]"; DATE:2016-07-06
unit_tkn.Unit_seg_val_(adj);
return true;
}
@Override public void Time_ini(DateAdpBldr bldr) {
}
public static final Pxd_itm_unit_relative
@Override public boolean Time_ini(DateAdpBldr bldr) {return true;}
public static final Pxd_itm_unit_relative
Next = new Pxd_itm_unit_relative(1)
, Prev = new Pxd_itm_unit_relative(-1)
, This = new Pxd_itm_unit_relative(0)
@@ -307,15 +317,16 @@ class Pxd_itm_unit_relative extends Pxd_itm_base implements Pxd_itm_prototype {
class Pxd_itm_unixtime extends Pxd_itm_base implements Pxd_itm_prototype {
private long unixtime;
public Pxd_itm_unixtime(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("@");
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("@");
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_unixtime;}
@Override public int Eval_idx() {return 5;} // set to high priority so it can evaluate number early
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_unixtime(ary_idx, this.Seg_idx());}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
Pxd_itm[] tkns = state.Tkns();
unixtime = Pxd_itm_int_.Read_nearest_as_int_and_skip(state, tkns, this.Ary_idx(), true, Int_.Min_value);
return true;
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Time_ini(DateAdpBldr bldr) {
DateAdp date = DateAdp_.unixtime_utc_seconds_(unixtime);
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
@@ -324,6 +335,7 @@ class Pxd_itm_unixtime extends Pxd_itm_base implements Pxd_itm_prototype {
bldr.Seg_set(DateAdp_.SegIdx_minute , date.Minute());
bldr.Seg_set(DateAdp_.SegIdx_second , date.Second());
bldr.Seg_set(DateAdp_.SegIdx_frac , date.Frac());
return true;
}
}
class Pxd_itm_dow_name extends Pxd_itm_base implements Pxd_itm_prototype {
@@ -333,31 +345,33 @@ class Pxd_itm_dow_name extends Pxd_itm_base implements Pxd_itm_prototype {
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_dow_name;}
@Override public int Eval_idx() {return 20;}
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_dow_name(ary_idx, dow_name, dow_idx);}
@Override public void Eval(Pxd_parser state) {
}
@Override public void Time_ini(DateAdpBldr bldr) {
@Override public boolean Eval(Pxd_parser state) {return true;}
@Override public boolean Time_ini(DateAdpBldr bldr) {
DateAdp now = DateAdp_.Now();
int adj = dow_idx - now.DayOfWeek(); // adj = requested_dow - current_dow; EX: requesting Friday, and today is Wednesday; adj = 2 (4 - 2); DATE:2014-05-02
if (adj < 0) adj += 7; // requested_down is before current_dow; add 7 to get the next day
bldr.Date_(bldr.Date().Add_day(adj));
return true;
}
}
class Pxd_itm_iso8601_t extends Pxd_itm_base implements Pxd_itm_prototype {
public Pxd_itm_iso8601_t(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("T");
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("T");
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_iso8601_t;}
@Override public int Eval_idx() {return 99;} // evaluate last
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_iso8601_t(ary_idx, this.Seg_idx());}
@Override public void Eval(Pxd_parser state) {
@Override public boolean Eval(Pxd_parser state) {
Pxd_itm hour = Next_non_ws_tkn(state.Tkns(), this.Ary_idx() + 1);
if (hour != null && hour.Seg_idx() == DateAdp_.SegIdx_hour) return; // next item is hour
if (hour != null && hour.Seg_idx() == DateAdp_.SegIdx_hour) return true; // next item is hour
state.Err_set(Pft_func_time_log.Invalid_hour, Bfr_arg_.New_bry("T"));
return true;
}
@Override public void Time_ini(DateAdpBldr bldr) {}
@Override public boolean Time_ini(DateAdpBldr bldr) {return true;}
private static Pxd_itm Next_non_ws_tkn(Pxd_itm[] tkns, int bgn) {
int len = tkns.length;
for (int i = bgn; i < len; i++) {
Pxd_itm itm = tkns[i];
if (itm == null) return null; // PAGE:s.w:Christianity_and_alcohol EX:January 8 to January 14, 2001; DATE:2016-07-06
if (itm.Tkn_tid() != Pxd_itm_.Tid_ws) return itm;
}
return null;

View File

@@ -25,6 +25,7 @@ class Pxd_parser {
public int Data_ary_len() {return data_ary_len;} private int data_ary_len;
public int Colon_count;
public int[] Seg_idxs() {return seg_idxs;} private int[] seg_idxs = new int[DateAdp_.SegIdx__max]; // temp ary for storing current state
public byte[] Src() {return src;}
public boolean Seg_idxs_chk(int... ary) {
int len = ary.length;
for (int i = 0; i < len; i++)
@@ -43,8 +44,10 @@ class Pxd_parser {
fmtr.Bld_bfr(error_bfr, args);
} private Bry_bfr error_bfr = Bry_bfr_.New_w_size(32);
public DateAdp Parse(byte[] src, Bry_bfr error_bfr) {
Tokenize(src); // NOTE: should check if Tokenize failed, but want to be liberal as date parser is not fully implemented; this will always default to 1st day of year; DATE:2014-03-27
return Evaluate(src, error_bfr);
// synchronized (this) { // LOCK:static-obj; DATE:2016-07-06
Tokenize(src); // NOTE: should check if Tokenize failed, but want to be liberal as date parser is not fully implemented; this will always default to 1st day of year; DATE:2014-03-27
return Evaluate(src, error_bfr);
// }
}
private boolean Tokenize(byte[] src) {
this.src = src; src_len = src.length;
@@ -134,7 +137,10 @@ class Pxd_parser {
Pxd_itm[] eval_ary = Pxd_itm_sorter.XtoAryAndSort(tkns, tkns_len);
MakeDataAry();
for (int i = 0; i < tkns_len; i++) {
eval_ary[i].Eval(this);
if (!eval_ary[i].Eval(this)) {
error.Add_bfr_and_clear(error_bfr);
return DateAdp_.MinValue;
}
if (error_bfr.Len() != 0) {
error.Add_bfr_and_clear(error_bfr);
return DateAdp_.MinValue;
@@ -144,7 +150,10 @@ class Pxd_parser {
DateAdpBldr bldr = new DateAdpBldr(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0);
for (int i = 0; i < tkns_len; i++) {
Pxd_itm itm = (Pxd_itm)tkns[i];
itm.Time_ini(bldr);
if (!itm.Time_ini(bldr)) {
error.Add_str_a7("Invalid time");
return null;
}
}
return bldr.Bld();
}

View File

@@ -27,7 +27,7 @@ public class Pfunc_anchorencode extends Pf_func_base { // EX: {{anchorencode:a b
if (anchor_ctx != null) return;// NOTE: called by Scrib_uri
encode_trie.Add(Byte_ascii.Colon, Bfr_arg_.New_byte(Byte_ascii.Colon));
encode_trie.Add(Byte_ascii.Space, Bfr_arg_.New_byte(Byte_ascii.Underline));
anchor_ctx = Xop_ctx.new_sub_(ctx.Wiki());
anchor_ctx = Xop_ctx.new_sub_(ctx);
anchor_ctx.Para().Enabled_n_();
anchor_tkn_mkr = anchor_ctx.Tkn_mkr();
anchor_parser = ctx.Wiki().Parser_mgr().Anchor_encoder();

View File

@@ -30,7 +30,7 @@ public class Pfunc_filepath extends Pf_func_base {
byte[] val_ary = Eval_argx(ctx, src, caller, self); if (val_ary == Bry_.Empty) return;
Xowe_wiki wiki = ctx.Wiki();
Xoa_ttl ttl = wiki.Ttl_parse(Xow_ns_.Tid__file, val_ary); if (ttl == null) return; // text is not valid ttl; exit;
Xoae_page page = Load_page(wiki, ttl); if (page.Missing()) return; // page not found in wiki or commons; exit;
Xoae_page page = Load_page(wiki, ttl); if (page.Db().Page().Exists_n()) return; // page not found in wiki or commons; exit;
byte[] ttl_bry = page.Ttl().Page_url();
// Xof_orig_itm orig_itm = wiki.File_mgr().Orig_mgr().Find_by_ttl_or_null(ttl_bry);
@@ -50,11 +50,13 @@ public class Pfunc_filepath extends Pf_func_base {
private static final Xof_url_bldr url_bldr = new Xof_url_bldr();
private static Xoae_page Load_page(Xowe_wiki wiki, Xoa_ttl ttl) {
Xoae_page page = wiki.Data_mgr().Load_page_by_ttl(ttl);
if (page.Missing()) { // file not found in current wiki; try commons;
if (page.Db().Page().Exists_n()) { // file not found in current wiki; try commons;
Xowe_wiki commons_wiki = (Xowe_wiki)wiki.Appe().Wiki_mgr().Get_by_or_null(wiki.Commons_wiki_key());
if (commons_wiki != null) { // commons_wiki not installed; exit; DATE:2013-06-08
if (!Env_.Mode_testing()) commons_wiki.Init_assert();// must assert load else page_zip never detected; DATE:2013-03-10
page = commons_wiki.Data_mgr().Load_page_by_ttl(ttl);
synchronized (commons_wiki) { // LOCK:app-level; wiki.commons; DATE:2016-07-06
if (!Env_.Mode_testing()) commons_wiki.Init_assert();// must assert load else page_zip never detected; DATE:2013-03-10
page = commons_wiki.Data_mgr().Load_page_by_ttl(ttl);
}
}
}
return page;

View File

@@ -57,7 +57,6 @@ public class Pfunc_filepath_tst {
fxt.Test_parse_tmpl_str_test("{{filepath:B.png}}", "{{test}}", "");
}
@Test public void Invalid() { // PURPOSE: handle invalid ttls; EX:w:Germicidin
fxt.Init_log_(Xop_ttl_log.Invalid_char);
fxt.Test_parse_tmpl_str_test("{{filepath:{{{ImageFile}}}}}", "{{test}}", "");
}
// private static void Init_orig_mgr(Xow_wiki wiki) {

View File

@@ -38,7 +38,7 @@ public class Pfunc_rel2abs extends Pf_func_base {
}
public static boolean Rel2abs_ttl(byte[] ttl, int bgn, int end) {
int last = end - 1;
if (end - bgn > Xoa_ttl.Max_len) return false; // NOTE: some tmpls have long #if statements; quicker to fail here than wait for invalid char below
if (end - bgn > Ttl_max) return false; // NOTE: some tmpls have long #if statements; quicker to fail here than wait for invalid char below
boolean rv = false;
for (int i = bgn; i < end; ++i) {
switch (ttl[i]) {
@@ -165,7 +165,8 @@ public class Pfunc_rel2abs extends Pf_func_base {
}
return tmp_bfr.To_bry_and_clear();
}
private static int[] seg_ary = new int[Xoa_ttl.Max_len];
public static final int Ttl_max = 2048; // ASSUME: max len of 256 * 8 bytes
private static int[] seg_ary = new int[Ttl_max];
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_rel2abs;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_rel2abs().Name_(name);}
public static final int Id_null = 0, Id_slash = 1, Id_dot = 2, Id_dot_slash = 3, Id_dot_dot = 4, Id_dot_dot_slash = 5;

View File

@@ -25,7 +25,7 @@ public class Pfunc_titleparts extends Pf_func_base {
// get argx
int args_len = self.Args_len();
byte[] argx = Eval_argx(ctx, src, caller, self); if (argx == null) return; // no argx; return empty
Xoa_ttl argx_as_ttl = Xoa_ttl.new_(ctx.Wiki(), ctx.App().Msg_log_null(), argx, 0, argx.length); // transform to title in order to upper first, replace _, etc..
Xoa_ttl argx_as_ttl = Xoa_ttl.Parse(ctx.Wiki(), argx, 0, argx.length); // transform to title in order to upper first, replace _, etc..
if (argx_as_ttl == null) {bfr.Add(argx); return;} // NOTE: argx_as_ttl will be null if invalid, such as [[a|b]]; PAGE:en.w:owl and {{taxobox/showtaxon|Dinosauria}}
else argx = argx_as_ttl.Full_txt_w_ttl_case();
// get parts_len
@@ -48,30 +48,32 @@ public class Pfunc_titleparts extends Pf_func_base {
}
private byte[] TitleParts(byte[] src, int parts_len, int parts_bgn) {
// find dlm positions; EX: ab/cde/f/ will have -1,2,6,8
int src_len = src.length; int dlms_ary_len = 1; // 1 b/c dlms_ary[0] will always be -1
for (int i = 0; i < src_len; i++) {
if (src[i] == Byte_ascii.Slash) dlms_ary[dlms_ary_len++] = i;
synchronized (dlms_ary) {// LOCK:static-obj; DATE:2016-07-06
int src_len = src.length; int dlms_ary_len = 1; // 1 b/c dlms_ary[0] will always be -1
for (int i = 0; i < src_len; i++) {
if (src[i] == Byte_ascii.Slash) dlms_ary[dlms_ary_len++] = i;
}
dlms_ary[dlms_ary_len] = src_len; // put src_len into last dlms_ary; makes dlms_ary[] logic easier
// calc bgn_idx; must occur before adjust parts_len
int bgn_idx = parts_bgn > -1 ? parts_bgn : parts_bgn + dlms_ary_len; // negative parts_bgn means calc from end of dlms_ary_len; EX a/b/c|1|-1 means start from 2
if ( bgn_idx < 0 // bgn_idx can be negative when parts_len is negative and greater than array; EX: {{#titleparts:a/b|-1|-2}} results in dlms_ary_len of 1 and parts_bgn of -2 which will be parts_bgn of -1
|| bgn_idx > dlms_ary_len) return Bry_.Empty; // if bgn > len, return ""; EX: {{#titleparts:a/b|1|3}} should return ""
// adjust parts_len for negative/null
if (parts_len == Int_.Min_value) parts_len = dlms_ary_len; // no parts_len; default to dlms_ary_len
else if (parts_len < 0) { // neg parts_len; shorten parts now and default to rest of String; EX: a/b/c|-1 -> makes String a/b/c and get 2 parts
dlms_ary_len += parts_len;
parts_len = dlms_ary_len;
if (parts_len < 1) return Bry_.Empty; // NOTE: if zerod'd b/c of neg length, return empty; contrast with line below; EX: a/b/c|-4
}
if (parts_len == 0) return src; // if no dlms, return orig
// calc idxs for extraction
int bgn_pos = dlms_ary[bgn_idx] + 1; // +1 to start after slash
int end_idx = bgn_idx + parts_len;
int end_pos = end_idx > dlms_ary_len ? dlms_ary[dlms_ary_len] : dlms_ary[end_idx];
if (end_pos < bgn_pos) return Bry_.Empty;
return Bry_.Mid(src, bgn_pos, end_pos);
}
dlms_ary[dlms_ary_len] = src_len; // put src_len into last dlms_ary; makes dlms_ary[] logic easier
// calc bgn_idx; must occur before adjust parts_len
int bgn_idx = parts_bgn > -1 ? parts_bgn : parts_bgn + dlms_ary_len; // negative parts_bgn means calc from end of dlms_ary_len; EX a/b/c|1|-1 means start from 2
if ( bgn_idx < 0 // bgn_idx can be negative when parts_len is negative and greater than array; EX: {{#titleparts:a/b|-1|-2}} results in dlms_ary_len of 1 and parts_bgn of -2 which will be parts_bgn of -1
|| bgn_idx > dlms_ary_len) return Bry_.Empty; // if bgn > len, return ""; EX: {{#titleparts:a/b|1|3}} should return ""
// adjust parts_len for negative/null
if (parts_len == Int_.Min_value) parts_len = dlms_ary_len; // no parts_len; default to dlms_ary_len
else if (parts_len < 0) { // neg parts_len; shorten parts now and default to rest of String; EX: a/b/c|-1 -> makes String a/b/c and get 2 parts
dlms_ary_len += parts_len;
parts_len = dlms_ary_len;
if (parts_len < 1) return Bry_.Empty; // NOTE: if zerod'd b/c of neg length, return empty; contrast with line below; EX: a/b/c|-4
}
if (parts_len == 0) return src; // if no dlms, return orig
// calc idxs for extraction
int bgn_pos = dlms_ary[bgn_idx] + 1; // +1 to start after slash
int end_idx = bgn_idx + parts_len;
int end_pos = end_idx > dlms_ary_len ? dlms_ary[dlms_ary_len] : dlms_ary[end_idx];
if (end_pos < bgn_pos) return Bry_.Empty;
return Bry_.Mid(src, bgn_pos, end_pos);
} static int[] dlms_ary = new Int_ary_bldr(255).Set(0, -1).Xto_int_ary(); // set pos0 to -1; makes +1 logic easier
} private static final int[] dlms_ary = new Int_ary_bldr(255).Set(0, -1).Xto_int_ary(); // set pos0 to -1; makes +1 logic easier
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_titleparts;}
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_titleparts().Name_(name);}
}

View File

@@ -22,7 +22,7 @@ public class Pfunc_ttl extends Pf_func_base {
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
byte[] val_dat_ary = Eval_argx_or_null(ctx, src, caller, self, this.Name());
if (val_dat_ary == Bry_.Empty) return; // if argx is empty, return EX: {{PAGENAME:}}; DATE:2013-02-20
Xoa_ttl ttl = val_dat_ary == null ? ctx.Page().Ttl() : Xoa_ttl.parse(ctx.Wiki(), val_dat_ary);
Xoa_ttl ttl = val_dat_ary == null ? ctx.Page().Ttl() : Xoa_ttl.Parse(ctx.Wiki(), val_dat_ary);
if (ttl == null) return;
switch (id) {
case Xol_kwd_grp_.Id_ttl_page_txt: bfr.Add(ttl.Page_txt()); break;

View File

@@ -28,7 +28,7 @@ public class Pfunc_urlfunc extends Pf_func_base { // EX: {{lc:A}} -> a
}
public static void UrlString(Xop_ctx ctx, byte tid, boolean encode, byte[] src, Bry_bfr trg, byte[] qry_arg) {
Xowe_wiki wiki = ctx.Wiki();
Xoa_ttl ttl = Xoa_ttl.new_(wiki, ctx.Msg_log(), src, 0, src.length);
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, src, 0, src.length);
if (ttl == null) return; // NOTE: guard against null ttl; EX: {{fullurl:{{transclude|{{{1}}}}}|action=edit}} -> {{fullurl:Template:{{{1}}}|action=edit}} -> Template:{{{1}}} will be a null ttl
byte[] ttl_ary = ttl.Full_url();// NOTE: Full_url does encoding; don't encode again
Xow_xwiki_itm xwiki = ttl.Wik_itm();