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:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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");}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");}
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user