Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
xpath_ast_node Class Reference

Public Member Functions

 xpath_ast_node (ast_type_t type, xpath_value_type rettype_, const char_t *value)
 xpath_ast_node (ast_type_t type, xpath_value_type rettype_, double value)
 xpath_ast_node (ast_type_t type, xpath_value_type rettype_, xpath_variable *value)
 xpath_ast_node (ast_type_t type, xpath_value_type rettype_, xpath_ast_node *left=0, xpath_ast_node *right=0)
 xpath_ast_node (ast_type_t type, xpath_ast_node *left, axis_t axis, nodetest_t test, const char_t *contents)
 xpath_ast_node (ast_type_t type, xpath_ast_node *left, xpath_ast_node *right, predicate_t test)
void set_next (xpath_ast_node *value)
void set_right (xpath_ast_node *value)
bool eval_boolean (const xpath_context &c, const xpath_stack &stack)
double eval_number (const xpath_context &c, const xpath_stack &stack)
xpath_string eval_string_concat (const xpath_context &c, const xpath_stack &stack)
xpath_string eval_string (const xpath_context &c, const xpath_stack &stack)
xpath_node_set_raw eval_node_set (const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval)
void optimize (xpath_allocator *alloc)
void optimize_self (xpath_allocator *alloc)
bool is_posinv_expr () const
bool is_posinv_step () const
xpath_value_type rettype () const

Detailed Description

Definition at line 9670 of file pugixml.cc.

Constructor & Destructor Documentation

◆ xpath_ast_node() [1/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_value_type rettype_,
const char_t * value )
inline

Definition at line 10421 of file pugixml.cc.

10421 :
10422 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10423 {
10424 assert(type == ast_string_constant);
10425 _data.string = value;
10426 }
@ ast_string_constant
Definition pugixml.cc:9573

◆ xpath_ast_node() [2/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_value_type rettype_,
double value )
inline

Definition at line 10428 of file pugixml.cc.

10428 :
10429 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10430 {
10431 assert(type == ast_number_constant);
10432 _data.number = value;
10433 }
@ ast_number_constant
Definition pugixml.cc:9574

◆ xpath_ast_node() [3/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_value_type rettype_,
xpath_variable * value )
inline

Definition at line 10435 of file pugixml.cc.

10435 :
10436 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
10437 {
10438 assert(type == ast_variable);
10439 _data.variable = value;
10440 }
@ ast_variable
Definition pugixml.cc:9575

◆ xpath_ast_node() [4/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_value_type rettype_,
xpath_ast_node * left = 0,
xpath_ast_node * right = 0 )
inline

Definition at line 10442 of file pugixml.cc.

10442 :
10443 _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0)
10444 {
10445 }

◆ xpath_ast_node() [5/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_ast_node * left,
axis_t axis,
nodetest_t test,
const char_t * contents )
inline

Definition at line 10447 of file pugixml.cc.

10447 :
10448 _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(static_cast<char>(axis)), _test(static_cast<char>(test)), _left(left), _right(0), _next(0)
10449 {
10450 assert(type == ast_step);
10451 _data.nodetest = contents;
10452 }
@ ast_step
Definition pugixml.cc:9611
const axis_t axis_to_type< N >::axis
Definition pugixml.cc:9668

◆ xpath_ast_node() [6/6]

xpath_ast_node::xpath_ast_node ( ast_type_t type,
xpath_ast_node * left,
xpath_ast_node * right,
predicate_t test )
inline

Definition at line 10454 of file pugixml.cc.

10454 :
10455 _type(static_cast<char>(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast<char>(test)), _left(left), _right(right), _next(0)
10456 {
10457 assert(type == ast_filter || type == ast_predicate);
10458 }
@ ast_filter
Definition pugixml.cc:9572
@ ast_predicate
Definition pugixml.cc:9571

Member Function Documentation

◆ eval_boolean()

bool xpath_ast_node::eval_boolean ( const xpath_context & c,
const xpath_stack & stack )
inline

Definition at line 10470 of file pugixml.cc.

10471 {
10472 switch (_type)
10473 {
10474 case ast_op_or:
10475 return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack);
10476
10477 case ast_op_and:
10478 return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack);
10479
10480 case ast_op_equal:
10481 return compare_eq(_left, _right, c, stack, equal_to());
10482
10483 case ast_op_not_equal:
10484 return compare_eq(_left, _right, c, stack, not_equal_to());
10485
10486 case ast_op_less:
10487 return compare_rel(_left, _right, c, stack, less());
10488
10489 case ast_op_greater:
10490 return compare_rel(_right, _left, c, stack, less());
10491
10493 return compare_rel(_left, _right, c, stack, less_equal());
10494
10496 return compare_rel(_right, _left, c, stack, less_equal());
10497
10499 {
10500 xpath_allocator_capture cr(stack.result);
10501
10502 xpath_string lr = _left->eval_string(c, stack);
10503 xpath_string rr = _right->eval_string(c, stack);
10504
10505 return starts_with(lr.c_str(), rr.c_str());
10506 }
10507
10508 case ast_func_contains:
10509 {
10510 xpath_allocator_capture cr(stack.result);
10511
10512 xpath_string lr = _left->eval_string(c, stack);
10513 xpath_string rr = _right->eval_string(c, stack);
10514
10515 return find_substring(lr.c_str(), rr.c_str()) != 0;
10516 }
10517
10518 case ast_func_boolean:
10519 return _left->eval_boolean(c, stack);
10520
10521 case ast_func_not:
10522 return !_left->eval_boolean(c, stack);
10523
10524 case ast_func_true:
10525 return true;
10526
10527 case ast_func_false:
10528 return false;
10529
10530 case ast_func_lang:
10531 {
10532 if (c.n.attribute()) return false;
10533
10534 xpath_allocator_capture cr(stack.result);
10535
10536 xpath_string lang = _left->eval_string(c, stack);
10537
10538 for (xml_node n = c.n.node(); n; n = n.parent())
10539 {
10540 xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang"));
10541
10542 if (a)
10543 {
10544 const char_t* value = a.value();
10545
10546 // strnicmp / strncasecmp is not portable
10547 for (const char_t* lit = lang.c_str(); *lit; ++lit)
10548 {
10549 if (tolower_ascii(*lit) != tolower_ascii(*value)) return false;
10550 ++value;
10551 }
10552
10553 return *value == 0 || *value == '-';
10554 }
10555 }
10556
10557 return false;
10558 }
10559
10561 {
10562 const char_t* value = (_right->_type == ast_string_constant) ? _right->_data.string : _right->_data.variable->get_string();
10563
10564 xml_attribute attr = c.n.node().attribute(_left->_data.nodetest);
10565
10566 return attr && strequal(attr.value(), value) && is_xpath_attribute(attr.name());
10567 }
10568
10569 case ast_variable:
10570 {
10571 assert(_rettype == _data.variable->type());
10572
10573 if (_rettype == xpath_type_boolean)
10574 return _data.variable->get_boolean();
10575
10576 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
10577 break;
10578 }
10579
10580 default:
10581 ;
10582 }
10583
10584 // none of the ast types that return the value directly matched, we need to perform type conversion
10585 switch (_rettype)
10586 {
10587 case xpath_type_number:
10588 return convert_number_to_boolean(eval_number(c, stack));
10589
10590 case xpath_type_string:
10591 {
10592 xpath_allocator_capture cr(stack.result);
10593
10594 return !eval_string(c, stack).empty();
10595 }
10596
10598 {
10599 xpath_allocator_capture cr(stack.result);
10600
10601 return !eval_node_set(c, stack, nodeset_eval_any).empty();
10602 }
10603
10604 default:
10605 assert(false && "Wrong expression for return type boolean"); // unreachable
10606 return false;
10607 }
10608 }
xpath_variable * variable
Definition pugixml.cc:9695
xpath_node_set_raw eval_node_set(const xpath_context &c, const xpath_stack &stack, nodeset_eval_t eval)
Definition pugixml.cc:11033
xpath_string eval_string(const xpath_context &c, const xpath_stack &stack)
Definition pugixml.cc:10790
double eval_number(const xpath_context &c, const xpath_stack &stack)
Definition pugixml.cc:10610
bool empty() const
Definition pugixml.cc:9057
bool empty() const
Definition pugixml.cc:8059
const char_t * c_str() const
Definition pugixml.cc:8031
@ xpath_type_number
Definition pugixml.hpp:1113
@ xpath_type_string
Definition pugixml.hpp:1114
@ xpath_type_node_set
Definition pugixml.hpp:1112
PUGIXML_CHAR char_t
Definition pugixml.hpp:137
@ ast_op_and
Definition pugixml.cc:9557
@ ast_op_equal
Definition pugixml.cc:9558
@ ast_func_not
Definition pugixml.cc:9601
@ ast_opt_compare_attribute
Definition pugixml.cc:9615
@ ast_func_lang
Definition pugixml.cc:9604
@ ast_func_true
Definition pugixml.cc:9602
@ ast_op_not_equal
Definition pugixml.cc:9559
@ ast_func_contains
Definition pugixml.cc:9590
@ ast_op_greater
Definition pugixml.cc:9561
@ ast_func_boolean
Definition pugixml.cc:9600
@ ast_op_less_or_equal
Definition pugixml.cc:9562
@ ast_func_starts_with
Definition pugixml.cc:9589
@ ast_op_or
Definition pugixml.cc:9556
@ ast_op_greater_or_equal
Definition pugixml.cc:9563
@ ast_func_false
Definition pugixml.cc:9603
@ ast_op_less
Definition pugixml.cc:9560
PUGI__FN bool convert_number_to_boolean(double value)
Definition pugixml.cc:8391
@ nodeset_eval_any
Definition pugixml.cc:9659
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN bool starts_with(const char_t *string, const char_t *pattern)
Definition pugixml.cc:8082
bool is_xpath_attribute(const char_t *name)
Definition pugixml.cc:8786
PUGI__FN const char_t * find_substring(const char_t *s, const char_t *p)
Definition pugixml.cc:8102
PUGI__FN bool strequal(const char_t *src, const char_t *dst)
Definition pugixml.cc:226
PUGI__FN char_t tolower_ascii(char_t ch)
Definition pugixml.cc:8113
#define PUGIXML_TEXT(t)
Definition pugixml.hpp:130
xpath_node n
Definition pugixml.cc:9191
xpath_allocator * result
Definition pugixml.cc:7914

Referenced by eval_number(), and eval_string().

◆ eval_node_set()

xpath_node_set_raw xpath_ast_node::eval_node_set ( const xpath_context & c,
const xpath_stack & stack,
nodeset_eval_t eval )
inline

Definition at line 11033 of file pugixml.cc.

11034 {
11035 switch (_type)
11036 {
11037 case ast_op_union:
11038 {
11039 xpath_allocator_capture cr(stack.temp);
11040
11041 xpath_stack swapped_stack = {stack.temp, stack.result};
11042
11043 xpath_node_set_raw ls = _left->eval_node_set(c, stack, eval);
11044 xpath_node_set_raw rs = _right->eval_node_set(c, swapped_stack, eval);
11045
11046 // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother
11047 ls.set_type(xpath_node_set::type_unsorted);
11048
11049 ls.append(rs.begin(), rs.end(), stack.result);
11050 ls.remove_duplicates(stack.temp);
11051
11052 return ls;
11053 }
11054
11055 case ast_filter:
11056 {
11057 xpath_node_set_raw set = _left->eval_node_set(c, stack, _test == predicate_constant_one ? nodeset_eval_first : nodeset_eval_all);
11058
11059 // either expression is a number or it contains position() call; sort by document order
11060 if (_test != predicate_posinv) set.sort_do();
11061
11062 bool once = eval_once(set.type(), eval);
11063
11064 apply_predicate(set, 0, stack, once);
11065
11066 return set;
11067 }
11068
11069 case ast_func_id:
11070 return xpath_node_set_raw();
11071
11072 case ast_step:
11073 {
11074 switch (_axis)
11075 {
11076 case axis_ancestor:
11077 return step_do(c, stack, eval, axis_to_type<axis_ancestor>());
11078
11080 return step_do(c, stack, eval, axis_to_type<axis_ancestor_or_self>());
11081
11082 case axis_attribute:
11083 return step_do(c, stack, eval, axis_to_type<axis_attribute>());
11084
11085 case axis_child:
11086 return step_do(c, stack, eval, axis_to_type<axis_child>());
11087
11088 case axis_descendant:
11089 return step_do(c, stack, eval, axis_to_type<axis_descendant>());
11090
11092 return step_do(c, stack, eval, axis_to_type<axis_descendant_or_self>());
11093
11094 case axis_following:
11095 return step_do(c, stack, eval, axis_to_type<axis_following>());
11096
11098 return step_do(c, stack, eval, axis_to_type<axis_following_sibling>());
11099
11100 case axis_namespace:
11101 // namespaced axis is not supported
11102 return xpath_node_set_raw();
11103
11104 case axis_parent:
11105 return step_do(c, stack, eval, axis_to_type<axis_parent>());
11106
11107 case axis_preceding:
11108 return step_do(c, stack, eval, axis_to_type<axis_preceding>());
11109
11111 return step_do(c, stack, eval, axis_to_type<axis_preceding_sibling>());
11112
11113 case axis_self:
11114 return step_do(c, stack, eval, axis_to_type<axis_self>());
11115
11116 default:
11117 assert(false && "Unknown axis"); // unreachable
11118 return xpath_node_set_raw();
11119 }
11120 }
11121
11122 case ast_step_root:
11123 {
11124 assert(!_right); // root step can't have any predicates
11125
11126 xpath_node_set_raw ns;
11127
11128 ns.set_type(xpath_node_set::type_sorted);
11129
11130 if (c.n.node()) ns.push_back(c.n.node().root(), stack.result);
11131 else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result);
11132
11133 return ns;
11134 }
11135
11136 case ast_variable:
11137 {
11138 assert(_rettype == _data.variable->type());
11139
11140 if (_rettype == xpath_type_node_set)
11141 {
11142 const xpath_node_set& s = _data.variable->get_node_set();
11143
11144 xpath_node_set_raw ns;
11145
11146 ns.set_type(s.type());
11147 ns.append(s.begin(), s.end(), stack.result);
11148
11149 return ns;
11150 }
11151
11152 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
11153 break;
11154 }
11155
11156 default:
11157 ;
11158 }
11159
11160 // none of the ast types that return the value directly matched, but conversions to node set are invalid
11161 assert(false && "Wrong expression for return type node set"); // unreachable
11162 return xpath_node_set_raw();
11163 }
void append(const xpath_node *begin_, const xpath_node *end_, xpath_allocator *alloc)
Definition pugixml.cc:9082
xpath_node_set::type_t type() const
Definition pugixml.cc:9156
xpath_node * end() const
Definition pugixml.cc:9052
void remove_duplicates(xpath_allocator *alloc)
Definition pugixml.cc:9118
xpath_node * begin() const
Definition pugixml.cc:9047
void set_type(xpath_node_set::type_t value)
Definition pugixml.cc:9161
@ ast_op_union
Definition pugixml.cc:9570
@ ast_step_root
Definition pugixml.cc:9612
@ ast_func_id
Definition pugixml.cc:9579
@ predicate_constant_one
Definition pugixml.cc:9653
@ predicate_posinv
Definition pugixml.cc:9651
@ nodeset_eval_first
Definition pugixml.cc:9660
@ nodeset_eval_all
Definition pugixml.cc:9658
@ axis_preceding
Definition pugixml.cc:9630
@ axis_ancestor_or_self
Definition pugixml.cc:9621
@ axis_attribute
Definition pugixml.cc:9622
@ axis_following_sibling
Definition pugixml.cc:9627
@ axis_child
Definition pugixml.cc:9623
@ axis_descendant
Definition pugixml.cc:9624
@ axis_descendant_or_self
Definition pugixml.cc:9625
@ axis_self
Definition pugixml.cc:9632
@ axis_following
Definition pugixml.cc:9626
@ axis_ancestor
Definition pugixml.cc:9620
@ axis_preceding_sibling
Definition pugixml.cc:9631
@ axis_namespace
Definition pugixml.cc:9628
@ axis_parent
Definition pugixml.cc:9629
xpath_allocator * temp
Definition pugixml.cc:7915
#define ns(x)
Definition xmltok.c:1649

Referenced by eval_boolean(), and eval_string().

◆ eval_number()

double xpath_ast_node::eval_number ( const xpath_context & c,
const xpath_stack & stack )
inline

Definition at line 10610 of file pugixml.cc.

10611 {
10612 switch (_type)
10613 {
10614 case ast_op_add:
10615 return _left->eval_number(c, stack) + _right->eval_number(c, stack);
10616
10617 case ast_op_subtract:
10618 return _left->eval_number(c, stack) - _right->eval_number(c, stack);
10619
10620 case ast_op_multiply:
10621 return _left->eval_number(c, stack) * _right->eval_number(c, stack);
10622
10623 case ast_op_divide:
10624 return _left->eval_number(c, stack) / _right->eval_number(c, stack);
10625
10626 case ast_op_mod:
10627 return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack));
10628
10629 case ast_op_negate:
10630 return -_left->eval_number(c, stack);
10631
10633 return _data.number;
10634
10635 case ast_func_last:
10636 return static_cast<double>(c.size);
10637
10638 case ast_func_position:
10639 return static_cast<double>(c.position);
10640
10641 case ast_func_count:
10642 {
10643 xpath_allocator_capture cr(stack.result);
10644
10645 return static_cast<double>(_left->eval_node_set(c, stack, nodeset_eval_all).size());
10646 }
10647
10649 {
10650 xpath_allocator_capture cr(stack.result);
10651
10652 return static_cast<double>(string_value(c.n, stack.result).length());
10653 }
10654
10656 {
10657 xpath_allocator_capture cr(stack.result);
10658
10659 return static_cast<double>(_left->eval_string(c, stack).length());
10660 }
10661
10662 case ast_func_number_0:
10663 {
10664 xpath_allocator_capture cr(stack.result);
10665
10667 }
10668
10669 case ast_func_number_1:
10670 return _left->eval_number(c, stack);
10671
10672 case ast_func_sum:
10673 {
10674 xpath_allocator_capture cr(stack.result);
10675
10676 double r = 0;
10677
10678 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all);
10679
10680 for (const xpath_node* it = ns.begin(); it != ns.end(); ++it)
10681 {
10682 xpath_allocator_capture cri(stack.result);
10683
10685 }
10686
10687 return r;
10688 }
10689
10690 case ast_func_floor:
10691 {
10692 double r = _left->eval_number(c, stack);
10693
10694 return r == r ? floor(r) : r;
10695 }
10696
10697 case ast_func_ceiling:
10698 {
10699 double r = _left->eval_number(c, stack);
10700
10701 return r == r ? ceil(r) : r;
10702 }
10703
10704 case ast_func_round:
10705 return round_nearest_nzero(_left->eval_number(c, stack));
10706
10707 case ast_variable:
10708 {
10709 assert(_rettype == _data.variable->type());
10710
10711 if (_rettype == xpath_type_number)
10712 return _data.variable->get_number();
10713
10714 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
10715 break;
10716 }
10717
10718 default:
10719 ;
10720 }
10721
10722 // none of the ast types that return the value directly matched, we need to perform type conversion
10723 switch (_rettype)
10724 {
10725 case xpath_type_boolean:
10726 return eval_boolean(c, stack) ? 1 : 0;
10727
10728 case xpath_type_string:
10729 {
10730 xpath_allocator_capture cr(stack.result);
10731
10732 return convert_string_to_number(eval_string(c, stack).c_str());
10733 }
10734
10736 {
10737 xpath_allocator_capture cr(stack.result);
10738
10739 return convert_string_to_number(eval_string(c, stack).c_str());
10740 }
10741
10742 default:
10743 assert(false && "Wrong expression for return type number"); // unreachable
10744 return 0;
10745 }
10746 }
bool eval_boolean(const xpath_context &c, const xpath_stack &stack)
Definition pugixml.cc:10470
size_t length() const
Definition pugixml.cc:8036
@ xpath_type_boolean
Definition pugixml.hpp:1115
PUGI__FN double round_nearest_nzero(double value)
Definition pugixml.cc:8587
@ ast_func_sum
Definition pugixml.cc:9607
@ ast_func_floor
Definition pugixml.cc:9608
@ ast_op_divide
Definition pugixml.cc:9567
@ ast_func_number_0
Definition pugixml.cc:9605
@ ast_func_string_length_0
Definition pugixml.cc:9595
@ ast_op_negate
Definition pugixml.cc:9569
@ ast_func_position
Definition pugixml.cc:9577
@ ast_func_ceiling
Definition pugixml.cc:9609
@ ast_op_subtract
Definition pugixml.cc:9565
@ ast_func_last
Definition pugixml.cc:9576
@ ast_op_multiply
Definition pugixml.cc:9566
@ ast_func_count
Definition pugixml.cc:9578
@ ast_func_round
Definition pugixml.cc:9610
@ ast_func_number_1
Definition pugixml.cc:9606
@ ast_func_string_length_1
Definition pugixml.cc:9596
@ ast_op_add
Definition pugixml.cc:9564
@ ast_op_mod
Definition pugixml.cc:9568
PUGI__FN xpath_string string_value(const xpath_node &na, xpath_allocator *alloc)
Definition pugixml.cc:8118
PUGI__FN double convert_string_to_number(const char_t *string)
Definition pugixml.cc:8545
size_t position
Definition pugixml.cc:9192

Referenced by eval_boolean(), and eval_string().

◆ eval_string()

xpath_string xpath_ast_node::eval_string ( const xpath_context & c,
const xpath_stack & stack )
inline

Definition at line 10790 of file pugixml.cc.

10791 {
10792 switch (_type)
10793 {
10795 return xpath_string::from_const(_data.string);
10796
10798 {
10799 xpath_node na = c.n;
10800
10802 }
10803
10805 {
10806 xpath_allocator_capture cr(stack.result);
10807
10808 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10809 xpath_node na = ns.first();
10810
10812 }
10813
10814 case ast_func_name_0:
10815 {
10816 xpath_node na = c.n;
10817
10819 }
10820
10821 case ast_func_name_1:
10822 {
10823 xpath_allocator_capture cr(stack.result);
10824
10825 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10826 xpath_node na = ns.first();
10827
10829 }
10830
10832 {
10833 xpath_node na = c.n;
10834
10836 }
10837
10839 {
10840 xpath_allocator_capture cr(stack.result);
10841
10842 xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first);
10843 xpath_node na = ns.first();
10844
10846 }
10847
10848 case ast_func_string_0:
10849 return string_value(c.n, stack.result);
10850
10851 case ast_func_string_1:
10852 return _left->eval_string(c, stack);
10853
10854 case ast_func_concat:
10855 return eval_string_concat(c, stack);
10856
10858 {
10859 xpath_allocator_capture cr(stack.temp);
10860
10861 xpath_stack swapped_stack = {stack.temp, stack.result};
10862
10863 xpath_string s = _left->eval_string(c, swapped_stack);
10864 xpath_string p = _right->eval_string(c, swapped_stack);
10865
10866 const char_t* pos = find_substring(s.c_str(), p.c_str());
10867
10868 return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string();
10869 }
10870
10872 {
10873 xpath_allocator_capture cr(stack.temp);
10874
10875 xpath_stack swapped_stack = {stack.temp, stack.result};
10876
10877 xpath_string s = _left->eval_string(c, swapped_stack);
10878 xpath_string p = _right->eval_string(c, swapped_stack);
10879
10880 const char_t* pos = find_substring(s.c_str(), p.c_str());
10881 if (!pos) return xpath_string();
10882
10883 const char_t* rbegin = pos + p.length();
10884 const char_t* rend = s.c_str() + s.length();
10885
10886 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);
10887 }
10888
10890 {
10891 xpath_allocator_capture cr(stack.temp);
10892
10893 xpath_stack swapped_stack = {stack.temp, stack.result};
10894
10895 xpath_string s = _left->eval_string(c, swapped_stack);
10896 size_t s_length = s.length();
10897
10898 double first = round_nearest(_right->eval_number(c, stack));
10899
10900 if (is_nan(first)) return xpath_string(); // NaN
10901 else if (first >= static_cast<double>(s_length + 1)) return xpath_string();
10902
10903 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10904 assert(1 <= pos && pos <= s_length + 1);
10905
10906 const char_t* rbegin = s.c_str() + (pos - 1);
10907 const char_t* rend = s.c_str() + s.length();
10908
10909 return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin);
10910 }
10911
10913 {
10914 xpath_allocator_capture cr(stack.temp);
10915
10916 xpath_stack swapped_stack = {stack.temp, stack.result};
10917
10918 xpath_string s = _left->eval_string(c, swapped_stack);
10919 size_t s_length = s.length();
10920
10921 double first = round_nearest(_right->eval_number(c, stack));
10922 double last = first + round_nearest(_right->_next->eval_number(c, stack));
10923
10924 if (is_nan(first) || is_nan(last)) return xpath_string();
10925 else if (first >= static_cast<double>(s_length + 1)) return xpath_string();
10926 else if (first >= last) return xpath_string();
10927 else if (last < 1) return xpath_string();
10928
10929 size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
10930 size_t end = last >= static_cast<double>(s_length + 1) ? s_length + 1 : static_cast<size_t>(last);
10931
10932 assert(1 <= pos && pos <= end && end <= s_length + 1);
10933 const char_t* rbegin = s.c_str() + (pos - 1);
10934 const char_t* rend = s.c_str() + (end - 1);
10935
10936 return (end == s_length + 1 && !s.uses_heap()) ? xpath_string::from_const(rbegin) : xpath_string::from_heap(rbegin, rend, stack.result);
10937 }
10938
10940 {
10941 xpath_string s = string_value(c.n, stack.result);
10942
10943 char_t* begin = s.data(stack.result);
10944 if (!begin) return xpath_string();
10945
10946 char_t* end = normalize_space(begin);
10947
10948 return xpath_string::from_heap_preallocated(begin, end);
10949 }
10950
10952 {
10953 xpath_string s = _left->eval_string(c, stack);
10954
10955 char_t* begin = s.data(stack.result);
10956 if (!begin) return xpath_string();
10957
10958 char_t* end = normalize_space(begin);
10959
10960 return xpath_string::from_heap_preallocated(begin, end);
10961 }
10962
10963 case ast_func_translate:
10964 {
10965 xpath_allocator_capture cr(stack.temp);
10966
10967 xpath_stack swapped_stack = {stack.temp, stack.result};
10968
10969 xpath_string s = _left->eval_string(c, stack);
10970 xpath_string from = _right->eval_string(c, swapped_stack);
10971 xpath_string to = _right->_next->eval_string(c, swapped_stack);
10972
10973 char_t* begin = s.data(stack.result);
10974 if (!begin) return xpath_string();
10975
10976 char_t* end = translate(begin, from.c_str(), to.c_str(), to.length());
10977
10978 return xpath_string::from_heap_preallocated(begin, end);
10979 }
10980
10982 {
10983 xpath_string s = _left->eval_string(c, stack);
10984
10985 char_t* begin = s.data(stack.result);
10986 if (!begin) return xpath_string();
10987
10988 char_t* end = translate_table(begin, _data.table);
10989
10990 return xpath_string::from_heap_preallocated(begin, end);
10991 }
10992
10993 case ast_variable:
10994 {
10995 assert(_rettype == _data.variable->type());
10996
10997 if (_rettype == xpath_type_string)
10998 return xpath_string::from_const(_data.variable->get_string());
10999
11000 // variable needs to be converted to the correct type, this is handled by the fallthrough block below
11001 break;
11002 }
11003
11004 default:
11005 ;
11006 }
11007
11008 // none of the ast types that return the value directly matched, we need to perform type conversion
11009 switch (_rettype)
11010 {
11011 case xpath_type_boolean:
11012 return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
11013
11014 case xpath_type_number:
11015 return convert_number_to_string(eval_number(c, stack), stack.result);
11016
11018 {
11019 xpath_allocator_capture cr(stack.temp);
11020
11021 xpath_stack swapped_stack = {stack.temp, stack.result};
11022
11023 xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first);
11024 return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
11025 }
11026
11027 default:
11028 assert(false && "Wrong expression for return type string"); // unreachable
11029 return xpath_string();
11030 }
11031 }
xpath_string eval_string_concat(const xpath_context &c, const xpath_stack &stack)
Definition pugixml.cc:10748
static xpath_string from_heap_preallocated(const char_t *begin, const char_t *end)
Definition pugixml.cc:7972
bool uses_heap() const
Definition pugixml.cc:8074
static xpath_string from_const(const char_t *str)
Definition pugixml.cc:7967
static xpath_string from_heap(const char_t *begin, const char_t *end, xpath_allocator *alloc)
Definition pugixml.cc:7979
char_t * data(xpath_allocator *alloc)
Definition pugixml.cc:8041
@ ast_func_substring_3
Definition pugixml.cc:9594
@ ast_func_name_1
Definition pugixml.cc:9585
@ ast_opt_translate_table
Definition pugixml.cc:9614
@ ast_func_concat
Definition pugixml.cc:9588
@ ast_func_name_0
Definition pugixml.cc:9584
@ ast_func_string_1
Definition pugixml.cc:9587
@ ast_func_string_0
Definition pugixml.cc:9586
@ ast_func_substring_before
Definition pugixml.cc:9591
@ ast_func_local_name_1
Definition pugixml.cc:9581
@ ast_func_namespace_uri_0
Definition pugixml.cc:9582
@ ast_func_normalize_space_1
Definition pugixml.cc:9598
@ ast_func_substring_2
Definition pugixml.cc:9593
@ ast_func_normalize_space_0
Definition pugixml.cc:9597
@ ast_func_substring_after
Definition pugixml.cc:9592
@ ast_func_namespace_uri_1
Definition pugixml.cc:9583
@ ast_func_translate
Definition pugixml.cc:9599
@ ast_func_local_name_0
Definition pugixml.cc:9580
PUGI__FN const char_t * qualified_name(const xpath_node &node)
Definition pugixml.cc:8594
PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator *alloc)
Definition pugixml.cc:8448
PUGI__FN char_t * normalize_space(char_t *buffer)
Definition pugixml.cc:8674
PUGI__FN const char_t * namespace_uri(xml_node node)
Definition pugixml.cc:8630
PUGI__FN char_t * translate_table(char_t *buffer, const unsigned char *table)
Definition pugixml.cc:8756
PUGI__FN double round_nearest(double value)
Definition pugixml.cc:8582
PUGI__FN char_t * translate(char_t *buffer, const char_t *from, const char_t *to, size_t to_length)
Definition pugixml.cc:8702
PUGI__FN bool is_nan(double value)
Definition pugixml.cc:8346
PUGI__FN const char_t * local_name(const xpath_node &node)
Definition pugixml.cc:8599

Referenced by eval_boolean(), and eval_number().

◆ eval_string_concat()

xpath_string xpath_ast_node::eval_string_concat ( const xpath_context & c,
const xpath_stack & stack )
inline

Definition at line 10748 of file pugixml.cc.

10749 {
10750 assert(_type == ast_func_concat);
10751
10752 xpath_allocator_capture ct(stack.temp);
10753
10754 // count the string number
10755 size_t count = 1;
10756 for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++;
10757
10758 // allocate a buffer for temporary string objects
10759 xpath_string* buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string)));
10760 if (!buffer) return xpath_string();
10761
10762 // evaluate all strings to temporary stack
10763 xpath_stack swapped_stack = {stack.temp, stack.result};
10764
10765 buffer[0] = _left->eval_string(c, swapped_stack);
10766
10767 size_t pos = 1;
10768 for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack);
10769 assert(pos == count);
10770
10771 // get total length
10772 size_t length = 0;
10773 for (size_t i = 0; i < count; ++i) length += buffer[i].length();
10774
10775 // create final string
10776 char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t)));
10777 if (!result) return xpath_string();
10778
10779 char_t* ri = result;
10780
10781 for (size_t j = 0; j < count; ++j)
10782 for (const char_t* bi = buffer[j].c_str(); *bi; ++bi)
10783 *ri++ = *bi;
10784
10785 *ri = 0;
10786
10787 return xpath_string::from_heap_preallocated(result, ri);
10788 }
void * allocate(size_t size)
Definition pugixml.cc:7778

Referenced by eval_string().

◆ is_posinv_expr()

bool xpath_ast_node::is_posinv_expr ( ) const
inline

Definition at line 11245 of file pugixml.cc.

11246 {
11247 switch (_type)
11248 {
11249 case ast_func_position:
11250 case ast_func_last:
11251 return false;
11252
11255 case ast_variable:
11256 return true;
11257
11258 case ast_step:
11259 case ast_step_root:
11260 return true;
11261
11262 case ast_predicate:
11263 case ast_filter:
11264 return true;
11265
11266 default:
11267 if (_left && !_left->is_posinv_expr()) return false;
11268
11269 for (xpath_ast_node* n = _right; n; n = n->_next)
11270 if (!n->is_posinv_expr()) return false;
11271
11272 return true;
11273 }
11274 }

◆ is_posinv_step()

bool xpath_ast_node::is_posinv_step ( ) const
inline

Definition at line 11276 of file pugixml.cc.

11277 {
11278 assert(_type == ast_step);
11279
11280 for (xpath_ast_node* n = _right; n; n = n->_next)
11281 {
11282 assert(n->_type == ast_predicate);
11283
11284 if (n->_test != predicate_posinv)
11285 return false;
11286 }
11287
11288 return true;
11289 }

Referenced by optimize_self().

◆ optimize()

void xpath_ast_node::optimize ( xpath_allocator * alloc)
inline

Definition at line 11165 of file pugixml.cc.

11166 {
11167 if (_left)
11168 _left->optimize(alloc);
11169
11170 if (_right)
11171 _right->optimize(alloc);
11172
11173 if (_next)
11174 _next->optimize(alloc);
11175
11176 // coverity[var_deref_model]
11177 optimize_self(alloc);
11178 }
void optimize_self(xpath_allocator *alloc)
Definition pugixml.cc:11180

◆ optimize_self()

void xpath_ast_node::optimize_self ( xpath_allocator * alloc)
inline

Definition at line 11180 of file pugixml.cc.

11181 {
11182 // Rewrite [position()=expr] with [expr]
11183 // Note that this step has to go before classification to recognize [position()=1]
11184 if ((_type == ast_filter || _type == ast_predicate) &&
11185 _right && // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate)
11186 _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number)
11187 {
11188 _right = _right->_right;
11189 }
11190
11191 // Classify filter/predicate ops to perform various optimizations during evaluation
11192 if ((_type == ast_filter || _type == ast_predicate) && _right) // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate)
11193 {
11194 assert(_test == predicate_default);
11195
11196 if (_right->_type == ast_number_constant && _right->_data.number == 1.0)
11197 _test = predicate_constant_one;
11198 else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last))
11199 _test = predicate_constant;
11200 else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr())
11201 _test = predicate_posinv;
11202 }
11203
11204 // Rewrite descendant-or-self::node()/child::foo with descendant::foo
11205 // The former is a full form of //foo, the latter is much faster since it executes the node test immediately
11206 // Do a similar kind of rewrite for self/descendant/descendant-or-self axes
11207 // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1])
11208 if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) &&
11209 _left && _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right &&
11211 {
11212 if (_axis == axis_child || _axis == axis_descendant)
11213 _axis = axis_descendant;
11214 else
11216
11217 _left = _left->_left;
11218 }
11219
11220 // Use optimized lookup table implementation for translate() with constant arguments
11221 if (_type == ast_func_translate &&
11222 _right && // workaround for clang static analyzer (_right is never null for ast_func_translate)
11223 _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant)
11224 {
11225 unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string);
11226
11227 if (table)
11228 {
11230 _data.table = table;
11231 }
11232 }
11233
11234 // Use optimized path for @attr = 'value' or @attr = $value
11235 if (_type == ast_op_equal &&
11236 _left && _right && // workaround for clang static analyzer and Coverity (_left and _right are never null for ast_op_equal)
11237 // coverity[mixed_enums]
11238 _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right &&
11239 (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string)))
11240 {
11242 }
11243 }
const unsigned char * table
Definition pugixml.cc:9699
bool is_posinv_step() const
Definition pugixml.cc:11276
@ predicate_constant
Definition pugixml.cc:9652
@ predicate_default
Definition pugixml.cc:9650
@ nodetest_name
Definition pugixml.cc:9638
@ nodetest_type_node
Definition pugixml.cc:9639
PUGI__FN unsigned char * translate_table_generate(xpath_allocator *alloc, const char_t *from, const char_t *to)
Definition pugixml.cc:8724

Referenced by optimize().

◆ rettype()

xpath_value_type xpath_ast_node::rettype ( ) const
inline

Definition at line 11291 of file pugixml.cc.

11292 {
11293 return static_cast<xpath_value_type>(_rettype);
11294 }
xpath_value_type
Definition pugixml.hpp:1110

Referenced by evaluate_node_set_prepare(), xpath_parser::parse_expression_rec(), and xpath_parser::parse_step().

◆ set_next()

void xpath_ast_node::set_next ( xpath_ast_node * value)
inline

Definition at line 10460 of file pugixml.cc.

10461 {
10462 _next = value;
10463 }

Referenced by xpath_parser::parse_primary_expression(), and xpath_parser::parse_step().

◆ set_right()

void xpath_ast_node::set_right ( xpath_ast_node * value)
inline

Definition at line 10465 of file pugixml.cc.

10466 {
10467 _right = value;
10468 }

Member Data Documentation

◆ nodetest

const char_t* xpath_ast_node::nodetest

Definition at line 9697 of file pugixml.cc.

◆ number

double xpath_ast_node::number

Definition at line 9693 of file pugixml.cc.

◆ string

const char_t* xpath_ast_node::string

Definition at line 9691 of file pugixml.cc.

◆ table

const unsigned char* xpath_ast_node::table

Definition at line 9699 of file pugixml.cc.

Referenced by optimize_self().

◆ variable

xpath_variable* xpath_ast_node::variable

Definition at line 9695 of file pugixml.cc.


The documentation for this class was generated from the following file: