Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
xpath_ast_node Class Reference
Collaboration diagram for xpath_ast_node:
Collaboration graph
[legend]

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)
 
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)
 
bool is_posinv ()
 
xpath_value_type rettype () const
 

Private Member Functions

 xpath_ast_node (const xpath_ast_node &)
 
xpath_ast_nodeoperator= (const xpath_ast_node &)
 
void apply_predicate (xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack)
 
void apply_predicates (xpath_node_set_raw &ns, size_t first, const xpath_stack &stack)
 
void step_push (xpath_node_set_raw &ns, const xml_attribute &a, const xml_node &parent, xpath_allocator *alloc)
 
void step_push (xpath_node_set_raw &ns, const xml_node &n, xpath_allocator *alloc)
 
template<class T >
void step_fill (xpath_node_set_raw &ns, const xml_node &n, xpath_allocator *alloc, T)
 
template<class T >
void step_fill (xpath_node_set_raw &ns, const xml_attribute &a, const xml_node &p, xpath_allocator *alloc, T v)
 
template<class T >
xpath_node_set_raw step_do (const xpath_context &c, const xpath_stack &stack, T v)
 

Static Private Member Functions

template<class Comp >
static bool compare_eq (xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
 
template<class Comp >
static bool compare_rel (xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
 

Private Attributes

char _type
 
char _rettype
 
char _axis
 
char _test
 
xpath_ast_node_left
 
xpath_ast_node_right
 
xpath_ast_node_next
 
union {
   const char_t *   string
 
   double   number
 
   xpath_variable *   variable
 
   const char_t *   nodetest
 
_data
 

Detailed Description

Definition at line 7918 of file pugixml.cpp.

Constructor & Destructor Documentation

◆ xpath_ast_node() [1/6]

xpath_ast_node::xpath_ast_node ( const xpath_ast_node )
private

◆ xpath_ast_node() [2/6]

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

Definition at line 8519 of file pugixml.cpp.

8519  :
8520  _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
8521  {
8522  assert(type == ast_string_constant);
8523  _data.string = value;
8524  }

References _data, and ast_string_constant.

◆ xpath_ast_node() [3/6]

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

Definition at line 8526 of file pugixml.cpp.

8526  :
8527  _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
8528  {
8529  assert(type == ast_number_constant);
8530  _data.number = value;
8531  }

References _data, and ast_number_constant.

◆ xpath_ast_node() [4/6]

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

Definition at line 8533 of file pugixml.cpp.

8533  :
8534  _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0)
8535  {
8536  assert(type == ast_variable);
8537  _data.variable = value;
8538  }

References _data, and ast_variable.

◆ xpath_ast_node() [5/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 8540 of file pugixml.cpp.

8540  :
8541  _type(static_cast<char>(type)), _rettype(static_cast<char>(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0)
8542  {
8543  }

◆ xpath_ast_node() [6/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 8545 of file pugixml.cpp.

8545  :
8546  _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)
8547  {
8548  _data.nodetest = contents;
8549  }

References _data.

Member Function Documentation

◆ apply_predicate()

void xpath_ast_node::apply_predicate ( xpath_node_set_raw ns,
size_t  first,
xpath_ast_node expr,
const xpath_stack stack 
)
inlineprivate

Definition at line 8108 of file pugixml.cpp.

8109  {
8110  assert(ns.size() >= first);
8111 
8112  size_t i = 1;
8113  size_t size = ns.size() - first;
8114 
8115  xpath_node* last = ns.begin() + first;
8116 
8117  // remove_if... or well, sort of
8118  for (xpath_node* it = last; it != ns.end(); ++it, ++i)
8119  {
8120  xpath_context c(*it, i, size);
8121 
8122  if (expr->rettype() == xpath_type_number)
8123  {
8124  if (expr->eval_number(c, stack) == i)
8125  *last++ = *it;
8126  }
8127  else if (expr->eval_boolean(c, stack))
8128  *last++ = *it;
8129  }
8130 
8131  ns.truncate(last);
8132  }

References xpath_node_set_raw::begin(), xpath_node_set_raw::end(), eval_boolean(), eval_number(), rettype(), xpath_node_set_raw::size(), and xpath_node_set_raw::truncate().

Referenced by apply_predicates(), and eval_node_set().

◆ apply_predicates()

void xpath_ast_node::apply_predicates ( xpath_node_set_raw ns,
size_t  first,
const xpath_stack stack 
)
inlineprivate

Definition at line 8134 of file pugixml.cpp.

8135  {
8136  if (ns.size() == first) return;
8137 
8138  for (xpath_ast_node* pred = _right; pred; pred = pred->_next)
8139  {
8140  apply_predicate(ns, first, pred->_left, stack);
8141  }
8142  }

References _next, _right, apply_predicate(), and xpath_node_set_raw::size().

Referenced by step_do().

◆ compare_eq()

template<class Comp >
static bool xpath_ast_node::compare_eq ( xpath_ast_node lhs,
xpath_ast_node rhs,
const xpath_context c,
const xpath_stack stack,
const Comp &  comp 
)
inlinestaticprivate

Definition at line 7949 of file pugixml.cpp.

7950  {
7951  xpath_value_type lt = lhs->rettype(), rt = rhs->rettype();
7952 
7953  if (lt != xpath_type_node_set && rt != xpath_type_node_set)
7954  {
7955  if (lt == xpath_type_boolean || rt == xpath_type_boolean)
7956  return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack));
7957  else if (lt == xpath_type_number || rt == xpath_type_number)
7958  return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack));
7959  else if (lt == xpath_type_string || rt == xpath_type_string)
7960  {
7961  xpath_allocator_capture cr(stack.result);
7962 
7963  xpath_string ls = lhs->eval_string(c, stack);
7964  xpath_string rs = rhs->eval_string(c, stack);
7965 
7966  return comp(ls, rs);
7967  }
7968  }
7969  else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
7970  {
7971  xpath_allocator_capture cr(stack.result);
7972 
7973  xpath_node_set_raw ls = lhs->eval_node_set(c, stack);
7974  xpath_node_set_raw rs = rhs->eval_node_set(c, stack);
7975 
7976  for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
7977  for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
7978  {
7979  xpath_allocator_capture cri(stack.result);
7980 
7981  if (comp(string_value(*li, stack.result), string_value(*ri, stack.result)))
7982  return true;
7983  }
7984 
7985  return false;
7986  }
7987  else
7988  {
7989  if (lt == xpath_type_node_set)
7990  {
7991  swap(lhs, rhs);
7992  swap(lt, rt);
7993  }
7994 
7995  if (lt == xpath_type_boolean)
7996  return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack));
7997  else if (lt == xpath_type_number)
7998  {
7999  xpath_allocator_capture cr(stack.result);
8000 
8001  double l = lhs->eval_number(c, stack);
8002  xpath_node_set_raw rs = rhs->eval_node_set(c, stack);
8003 
8004  for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
8005  {
8006  xpath_allocator_capture cri(stack.result);
8007 
8008  if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
8009  return true;
8010  }
8011 
8012  return false;
8013  }
8014  else if (lt == xpath_type_string)
8015  {
8016  xpath_allocator_capture cr(stack.result);
8017 
8018  xpath_string l = lhs->eval_string(c, stack);
8019  xpath_node_set_raw rs = rhs->eval_node_set(c, stack);
8020 
8021  for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
8022  {
8023  xpath_allocator_capture cri(stack.result);
8024 
8025  if (comp(l, string_value(*ri, stack.result)))
8026  return true;
8027  }
8028 
8029  return false;
8030  }
8031  }
8032 
8033  assert(!"Wrong types");
8034  return false;
8035  }

References xpath_node_set_raw::begin(), xpath_string::c_str(), convert_string_to_number(), xpath_node_set_raw::end(), eval_boolean(), eval_node_set(), eval_number(), eval_string(), xpath_stack::result, rettype(), string_value(), and swap().

Referenced by eval_boolean().

◆ compare_rel()

template<class Comp >
static bool xpath_ast_node::compare_rel ( xpath_ast_node lhs,
xpath_ast_node rhs,
const xpath_context c,
const xpath_stack stack,
const Comp &  comp 
)
inlinestaticprivate

Definition at line 8037 of file pugixml.cpp.

8038  {
8039  xpath_value_type lt = lhs->rettype(), rt = rhs->rettype();
8040 
8041  if (lt != xpath_type_node_set && rt != xpath_type_node_set)
8042  return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack));
8043  else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
8044  {
8045  xpath_allocator_capture cr(stack.result);
8046 
8047  xpath_node_set_raw ls = lhs->eval_node_set(c, stack);
8048  xpath_node_set_raw rs = rhs->eval_node_set(c, stack);
8049 
8050  for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
8051  {
8052  xpath_allocator_capture cri(stack.result);
8053 
8054  double l = convert_string_to_number(string_value(*li, stack.result).c_str());
8055 
8056  for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
8057  {
8058  xpath_allocator_capture crii(stack.result);
8059 
8060  if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
8061  return true;
8062  }
8063  }
8064 
8065  return false;
8066  }
8067  else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
8068  {
8069  xpath_allocator_capture cr(stack.result);
8070 
8071  double l = lhs->eval_number(c, stack);
8072  xpath_node_set_raw rs = rhs->eval_node_set(c, stack);
8073 
8074  for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri)
8075  {
8076  xpath_allocator_capture cri(stack.result);
8077 
8078  if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str())))
8079  return true;
8080  }
8081 
8082  return false;
8083  }
8084  else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
8085  {
8086  xpath_allocator_capture cr(stack.result);
8087 
8088  xpath_node_set_raw ls = lhs->eval_node_set(c, stack);
8089  double r = rhs->eval_number(c, stack);
8090 
8091  for (const xpath_node* li = ls.begin(); li != ls.end(); ++li)
8092  {
8093  xpath_allocator_capture cri(stack.result);
8094 
8095  if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r))
8096  return true;
8097  }
8098 
8099  return false;
8100  }
8101  else
8102  {
8103  assert(!"Wrong types");
8104  return false;
8105  }
8106  }

References xpath_node_set_raw::begin(), xpath_string::c_str(), convert_string_to_number(), xpath_node_set_raw::end(), eval_node_set(), eval_number(), xpath_stack::result, rettype(), and string_value().

Referenced by eval_boolean().

◆ eval_boolean()

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

Definition at line 8561 of file pugixml.cpp.

8562  {
8563  switch (_type)
8564  {
8565  case ast_op_or:
8566  return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack);
8567 
8568  case ast_op_and:
8569  return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack);
8570 
8571  case ast_op_equal:
8572  return compare_eq(_left, _right, c, stack, equal_to());
8573 
8574  case ast_op_not_equal:
8575  return compare_eq(_left, _right, c, stack, not_equal_to());
8576 
8577  case ast_op_less:
8578  return compare_rel(_left, _right, c, stack, less());
8579 
8580  case ast_op_greater:
8581  return compare_rel(_right, _left, c, stack, less());
8582 
8583  case ast_op_less_or_equal:
8584  return compare_rel(_left, _right, c, stack, less_equal());
8585 
8587  return compare_rel(_right, _left, c, stack, less_equal());
8588 
8589  case ast_func_starts_with:
8590  {
8591  xpath_allocator_capture cr(stack.result);
8592 
8593  xpath_string lr = _left->eval_string(c, stack);
8594  xpath_string rr = _right->eval_string(c, stack);
8595 
8596  return starts_with(lr.c_str(), rr.c_str());
8597  }
8598 
8599  case ast_func_contains:
8600  {
8601  xpath_allocator_capture cr(stack.result);
8602 
8603  xpath_string lr = _left->eval_string(c, stack);
8604  xpath_string rr = _right->eval_string(c, stack);
8605 
8606  return find_substring(lr.c_str(), rr.c_str()) != 0;
8607  }
8608 
8609  case ast_func_boolean:
8610  return _left->eval_boolean(c, stack);
8611 
8612  case ast_func_not:
8613  return !_left->eval_boolean(c, stack);
8614 
8615  case ast_func_true:
8616  return true;
8617 
8618  case ast_func_false:
8619  return false;
8620 
8621  case ast_func_lang:
8622  {
8623  if (c.n.attribute()) return false;
8624 
8625  xpath_allocator_capture cr(stack.result);
8626 
8627  xpath_string lang = _left->eval_string(c, stack);
8628 
8629  for (xml_node n = c.n.node(); n; n = n.parent())
8630  {
8631  xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang"));
8632 
8633  if (a)
8634  {
8635  const char_t* value = a.value();
8636 
8637  // strnicmp / strncasecmp is not portable
8638  for (const char_t* lit = lang.c_str(); *lit; ++lit)
8639  {
8640  if (tolower_ascii(*lit) != tolower_ascii(*value)) return false;
8641  ++value;
8642  }
8643 
8644  return *value == 0 || *value == '-';
8645  }
8646  }
8647 
8648  return false;
8649  }
8650 
8651  case ast_variable:
8652  {
8653  assert(_rettype == _data.variable->type());
8654 
8655  if (_rettype == xpath_type_boolean)
8656  return _data.variable->get_boolean();
8657 
8658  // fallthrough to type conversion
8659  }
8660 
8661  default:
8662  {
8663  switch (_rettype)
8664  {
8665  case xpath_type_number:
8666  return convert_number_to_boolean(eval_number(c, stack));
8667 
8668  case xpath_type_string:
8669  {
8670  xpath_allocator_capture cr(stack.result);
8671 
8672  return !eval_string(c, stack).empty();
8673  }
8674 
8675  case xpath_type_node_set:
8676  {
8677  xpath_allocator_capture cr(stack.result);
8678 
8679  return !eval_node_set(c, stack).empty();
8680  }
8681 
8682  default:
8683  assert(!"Wrong expression for return type boolean");
8684  return false;
8685  }
8686  }
8687  }
8688  }

References _data, _left, _rettype, _right, _type, ast_func_boolean, ast_func_contains, ast_func_false, ast_func_lang, ast_func_not, ast_func_starts_with, ast_func_true, ast_op_and, ast_op_equal, ast_op_greater, ast_op_greater_or_equal, ast_op_less, ast_op_less_or_equal, ast_op_not_equal, ast_op_or, ast_variable, xpath_string::c_str(), compare_eq(), compare_rel(), convert_number_to_boolean(), xpath_string::empty(), xpath_node_set_raw::empty(), eval_boolean(), eval_node_set(), eval_number(), eval_string(), find_substring(), xpath_context::n, xpath_stack::result, starts_with(), and tolower_ascii().

Referenced by apply_predicate(), compare_eq(), eval_boolean(), 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 
)
inline

Definition at line 9094 of file pugixml.cpp.

9095  {
9096  switch (_type)
9097  {
9098  case ast_op_union:
9099  {
9100  xpath_allocator_capture cr(stack.temp);
9101 
9102  xpath_stack swapped_stack = {stack.temp, stack.result};
9103 
9104  xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack);
9105  xpath_node_set_raw rs = _right->eval_node_set(c, stack);
9106 
9107  // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother
9108  rs.set_type(xpath_node_set::type_unsorted);
9109 
9110  rs.append(ls.begin(), ls.end(), stack.result);
9111  rs.remove_duplicates();
9112 
9113  return rs;
9114  }
9115 
9116  case ast_filter:
9117  case ast_filter_posinv:
9118  {
9119  xpath_node_set_raw set = _left->eval_node_set(c, stack);
9120 
9121  // either expression is a number or it contains position() call; sort by document order
9122  if (_type == ast_filter) set.sort_do();
9123 
9124  apply_predicate(set, 0, _right, stack);
9125 
9126  return set;
9127  }
9128 
9129  case ast_func_id:
9130  return xpath_node_set_raw();
9131 
9132  case ast_step:
9133  {
9134  switch (_axis)
9135  {
9136  case axis_ancestor:
9137  return step_do(c, stack, axis_to_type<axis_ancestor>());
9138 
9139  case axis_ancestor_or_self:
9140  return step_do(c, stack, axis_to_type<axis_ancestor_or_self>());
9141 
9142  case axis_attribute:
9143  return step_do(c, stack, axis_to_type<axis_attribute>());
9144 
9145  case axis_child:
9146  return step_do(c, stack, axis_to_type<axis_child>());
9147 
9148  case axis_descendant:
9149  return step_do(c, stack, axis_to_type<axis_descendant>());
9150 
9152  return step_do(c, stack, axis_to_type<axis_descendant_or_self>());
9153 
9154  case axis_following:
9155  return step_do(c, stack, axis_to_type<axis_following>());
9156 
9158  return step_do(c, stack, axis_to_type<axis_following_sibling>());
9159 
9160  case axis_namespace:
9161  // namespaced axis is not supported
9162  return xpath_node_set_raw();
9163 
9164  case axis_parent:
9165  return step_do(c, stack, axis_to_type<axis_parent>());
9166 
9167  case axis_preceding:
9168  return step_do(c, stack, axis_to_type<axis_preceding>());
9169 
9171  return step_do(c, stack, axis_to_type<axis_preceding_sibling>());
9172 
9173  case axis_self:
9174  return step_do(c, stack, axis_to_type<axis_self>());
9175 
9176  default:
9177  assert(!"Unknown axis");
9178  return xpath_node_set_raw();
9179  }
9180  }
9181 
9182  case ast_step_root:
9183  {
9184  assert(!_right); // root step can't have any predicates
9185 
9186  xpath_node_set_raw ns;
9187 
9188  ns.set_type(xpath_node_set::type_sorted);
9189 
9190  if (c.n.node()) ns.push_back(c.n.node().root(), stack.result);
9191  else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result);
9192 
9193  return ns;
9194  }
9195 
9196  case ast_variable:
9197  {
9198  assert(_rettype == _data.variable->type());
9199 
9200  if (_rettype == xpath_type_node_set)
9201  {
9202  const xpath_node_set& s = _data.variable->get_node_set();
9203 
9204  xpath_node_set_raw ns;
9205 
9206  ns.set_type(s.type());
9207  ns.append(s.begin(), s.end(), stack.result);
9208 
9209  return ns;
9210  }
9211 
9212  // fallthrough to type conversion
9213  }
9214 
9215  default:
9216  assert(!"Wrong expression for return type node set");
9217  return xpath_node_set_raw();
9218  }
9219  }

References _axis, _data, _left, _rettype, _right, _type, xpath_node_set_raw::append(), apply_predicate(), ast_filter, ast_filter_posinv, ast_func_id, ast_op_union, ast_step, ast_step_root, ast_variable, axis_ancestor, axis_ancestor_or_self, axis_attribute, axis_child, axis_descendant, axis_descendant_or_self, axis_following, axis_following_sibling, axis_namespace, axis_parent, axis_preceding, axis_preceding_sibling, axis_self, xpath_node_set_raw::begin(), xpath_node_set_raw::end(), eval_node_set(), xpath_context::n, xpath_node_set_raw::push_back(), xpath_node_set_raw::remove_duplicates(), xpath_stack::result, xpath_node_set_raw::set_type(), xpath_node_set_raw::sort_do(), step_do(), and xpath_stack::temp.

Referenced by compare_eq(), compare_rel(), eval_boolean(), eval_node_set(), eval_number(), eval_string(), and step_do().

◆ eval_number()

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

Definition at line 8690 of file pugixml.cpp.

8691  {
8692  switch (_type)
8693  {
8694  case ast_op_add:
8695  return _left->eval_number(c, stack) + _right->eval_number(c, stack);
8696 
8697  case ast_op_subtract:
8698  return _left->eval_number(c, stack) - _right->eval_number(c, stack);
8699 
8700  case ast_op_multiply:
8701  return _left->eval_number(c, stack) * _right->eval_number(c, stack);
8702 
8703  case ast_op_divide:
8704  return _left->eval_number(c, stack) / _right->eval_number(c, stack);
8705 
8706  case ast_op_mod:
8707  return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack));
8708 
8709  case ast_op_negate:
8710  return -_left->eval_number(c, stack);
8711 
8712  case ast_number_constant:
8713  return _data.number;
8714 
8715  case ast_func_last:
8716  return static_cast<double>(c.size);
8717 
8718  case ast_func_position:
8719  return static_cast<double>(c.position);
8720 
8721  case ast_func_count:
8722  {
8723  xpath_allocator_capture cr(stack.result);
8724 
8725  return static_cast<double>(_left->eval_node_set(c, stack).size());
8726  }
8727 
8729  {
8730  xpath_allocator_capture cr(stack.result);
8731 
8732  return static_cast<double>(string_value(c.n, stack.result).length());
8733  }
8734 
8736  {
8737  xpath_allocator_capture cr(stack.result);
8738 
8739  return static_cast<double>(_left->eval_string(c, stack).length());
8740  }
8741 
8742  case ast_func_number_0:
8743  {
8744  xpath_allocator_capture cr(stack.result);
8745 
8746  return convert_string_to_number(string_value(c.n, stack.result).c_str());
8747  }
8748 
8749  case ast_func_number_1:
8750  return _left->eval_number(c, stack);
8751 
8752  case ast_func_sum:
8753  {
8754  xpath_allocator_capture cr(stack.result);
8755 
8756  double r = 0;
8757 
8758  xpath_node_set_raw ns = _left->eval_node_set(c, stack);
8759 
8760  for (const xpath_node* it = ns.begin(); it != ns.end(); ++it)
8761  {
8762  xpath_allocator_capture cri(stack.result);
8763 
8764  r += convert_string_to_number(string_value(*it, stack.result).c_str());
8765  }
8766 
8767  return r;
8768  }
8769 
8770  case ast_func_floor:
8771  {
8772  double r = _left->eval_number(c, stack);
8773 
8774  return r == r ? floor(r) : r;
8775  }
8776 
8777  case ast_func_ceiling:
8778  {
8779  double r = _left->eval_number(c, stack);
8780 
8781  return r == r ? ceil(r) : r;
8782  }
8783 
8784  case ast_func_round:
8785  return round_nearest_nzero(_left->eval_number(c, stack));
8786 
8787  case ast_variable:
8788  {
8789  assert(_rettype == _data.variable->type());
8790 
8791  if (_rettype == xpath_type_number)
8792  return _data.variable->get_number();
8793 
8794  // fallthrough to type conversion
8795  }
8796 
8797  default:
8798  {
8799  switch (_rettype)
8800  {
8801  case xpath_type_boolean:
8802  return eval_boolean(c, stack) ? 1 : 0;
8803 
8804  case xpath_type_string:
8805  {
8806  xpath_allocator_capture cr(stack.result);
8807 
8808  return convert_string_to_number(eval_string(c, stack).c_str());
8809  }
8810 
8811  case xpath_type_node_set:
8812  {
8813  xpath_allocator_capture cr(stack.result);
8814 
8815  return convert_string_to_number(eval_string(c, stack).c_str());
8816  }
8817 
8818  default:
8819  assert(!"Wrong expression for return type number");
8820  return 0;
8821  }
8822 
8823  }
8824  }
8825  }

References _data, _left, _rettype, _right, _type, ast_func_ceiling, ast_func_count, ast_func_floor, ast_func_last, ast_func_number_0, ast_func_number_1, ast_func_position, ast_func_round, ast_func_string_length_0, ast_func_string_length_1, ast_func_sum, ast_number_constant, ast_op_add, ast_op_divide, ast_op_mod, ast_op_multiply, ast_op_negate, ast_op_subtract, ast_variable, xpath_node_set_raw::begin(), xpath_string::c_str(), convert_string_to_number(), xpath_node_set_raw::end(), eval_boolean(), eval_node_set(), eval_number(), eval_string(), xpath_string::length(), xpath_context::n, xpath_context::position, xpath_stack::result, round_nearest_nzero(), xpath_node_set_raw::size(), xpath_context::size, and string_value().

Referenced by apply_predicate(), compare_eq(), compare_rel(), eval_boolean(), eval_number(), and eval_string().

◆ eval_string()

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

Definition at line 8876 of file pugixml.cpp.

8877  {
8878  switch (_type)
8879  {
8880  case ast_string_constant:
8881  return xpath_string_const(_data.string);
8882 
8883  case ast_func_local_name_0:
8884  {
8885  xpath_node na = c.n;
8886 
8887  return xpath_string_const(local_name(na));
8888  }
8889 
8890  case ast_func_local_name_1:
8891  {
8892  xpath_allocator_capture cr(stack.result);
8893 
8894  xpath_node_set_raw ns = _left->eval_node_set(c, stack);
8895  xpath_node na = ns.first();
8896 
8897  return xpath_string_const(local_name(na));
8898  }
8899 
8900  case ast_func_name_0:
8901  {
8902  xpath_node na = c.n;
8903 
8904  return xpath_string_const(qualified_name(na));
8905  }
8906 
8907  case ast_func_name_1:
8908  {
8909  xpath_allocator_capture cr(stack.result);
8910 
8911  xpath_node_set_raw ns = _left->eval_node_set(c, stack);
8912  xpath_node na = ns.first();
8913 
8914  return xpath_string_const(qualified_name(na));
8915  }
8916 
8918  {
8919  xpath_node na = c.n;
8920 
8921  return xpath_string_const(namespace_uri(na));
8922  }
8923 
8925  {
8926  xpath_allocator_capture cr(stack.result);
8927 
8928  xpath_node_set_raw ns = _left->eval_node_set(c, stack);
8929  xpath_node na = ns.first();
8930 
8931  return xpath_string_const(namespace_uri(na));
8932  }
8933 
8934  case ast_func_string_0:
8935  return string_value(c.n, stack.result);
8936 
8937  case ast_func_string_1:
8938  return _left->eval_string(c, stack);
8939 
8940  case ast_func_concat:
8941  return eval_string_concat(c, stack);
8942 
8944  {
8945  xpath_allocator_capture cr(stack.temp);
8946 
8947  xpath_stack swapped_stack = {stack.temp, stack.result};
8948 
8949  xpath_string s = _left->eval_string(c, swapped_stack);
8950  xpath_string p = _right->eval_string(c, swapped_stack);
8951 
8952  const char_t* pos = find_substring(s.c_str(), p.c_str());
8953 
8954  return pos ? xpath_string(s.c_str(), pos, stack.result) : xpath_string();
8955  }
8956 
8958  {
8959  xpath_allocator_capture cr(stack.temp);
8960 
8961  xpath_stack swapped_stack = {stack.temp, stack.result};
8962 
8963  xpath_string s = _left->eval_string(c, swapped_stack);
8964  xpath_string p = _right->eval_string(c, swapped_stack);
8965 
8966  const char_t* pos = find_substring(s.c_str(), p.c_str());
8967  if (!pos) return xpath_string();
8968 
8969  const char_t* result = pos + p.length();
8970 
8971  return s.uses_heap() ? xpath_string(result, stack.result) : xpath_string_const(result);
8972  }
8973 
8974  case ast_func_substring_2:
8975  {
8976  xpath_allocator_capture cr(stack.temp);
8977 
8978  xpath_stack swapped_stack = {stack.temp, stack.result};
8979 
8980  xpath_string s = _left->eval_string(c, swapped_stack);
8981  size_t s_length = s.length();
8982 
8983  double first = round_nearest(_right->eval_number(c, stack));
8984 
8985  if (is_nan(first)) return xpath_string(); // NaN
8986  else if (first >= s_length + 1) return xpath_string();
8987 
8988  size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
8989  assert(1 <= pos && pos <= s_length + 1);
8990 
8991  const char_t* rbegin = s.c_str() + (pos - 1);
8992 
8993  return s.uses_heap() ? xpath_string(rbegin, stack.result) : xpath_string_const(rbegin);
8994  }
8995 
8996  case ast_func_substring_3:
8997  {
8998  xpath_allocator_capture cr(stack.temp);
8999 
9000  xpath_stack swapped_stack = {stack.temp, stack.result};
9001 
9002  xpath_string s = _left->eval_string(c, swapped_stack);
9003  size_t s_length = s.length();
9004 
9005  double first = round_nearest(_right->eval_number(c, stack));
9006  double last = first + round_nearest(_right->_next->eval_number(c, stack));
9007 
9008  if (is_nan(first) || is_nan(last)) return xpath_string();
9009  else if (first >= s_length + 1) return xpath_string();
9010  else if (first >= last) return xpath_string();
9011  else if (last < 1) return xpath_string();
9012 
9013  size_t pos = first < 1 ? 1 : static_cast<size_t>(first);
9014  size_t end = last >= s_length + 1 ? s_length + 1 : static_cast<size_t>(last);
9015 
9016  assert(1 <= pos && pos <= end && end <= s_length + 1);
9017  const char_t* rbegin = s.c_str() + (pos - 1);
9018  const char_t* rend = s.c_str() + (end - 1);
9019 
9020  return (end == s_length + 1 && !s.uses_heap()) ? xpath_string_const(rbegin) : xpath_string(rbegin, rend, stack.result);
9021  }
9022 
9024  {
9025  xpath_string s = string_value(c.n, stack.result);
9026 
9027  normalize_space(s.data(stack.result));
9028 
9029  return s;
9030  }
9031 
9033  {
9034  xpath_string s = _left->eval_string(c, stack);
9035 
9036  normalize_space(s.data(stack.result));
9037 
9038  return s;
9039  }
9040 
9041  case ast_func_translate:
9042  {
9043  xpath_allocator_capture cr(stack.temp);
9044 
9045  xpath_stack swapped_stack = {stack.temp, stack.result};
9046 
9047  xpath_string s = _left->eval_string(c, stack);
9048  xpath_string from = _right->eval_string(c, swapped_stack);
9049  xpath_string to = _right->_next->eval_string(c, swapped_stack);
9050 
9051  translate(s.data(stack.result), from.c_str(), to.c_str());
9052 
9053  return s;
9054  }
9055 
9056  case ast_variable:
9057  {
9058  assert(_rettype == _data.variable->type());
9059 
9060  if (_rettype == xpath_type_string)
9061  return xpath_string_const(_data.variable->get_string());
9062 
9063  // fallthrough to type conversion
9064  }
9065 
9066  default:
9067  {
9068  switch (_rettype)
9069  {
9070  case xpath_type_boolean:
9071  return xpath_string_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
9072 
9073  case xpath_type_number:
9074  return convert_number_to_string(eval_number(c, stack), stack.result);
9075 
9076  case xpath_type_node_set:
9077  {
9078  xpath_allocator_capture cr(stack.temp);
9079 
9080  xpath_stack swapped_stack = {stack.temp, stack.result};
9081 
9082  xpath_node_set_raw ns = eval_node_set(c, swapped_stack);
9083  return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
9084  }
9085 
9086  default:
9087  assert(!"Wrong expression for return type string");
9088  return xpath_string();
9089  }
9090  }
9091  }
9092  }

References _data, _left, _next, _rettype, _right, _type, ast_func_concat, ast_func_local_name_0, ast_func_local_name_1, ast_func_name_0, ast_func_name_1, ast_func_namespace_uri_0, ast_func_namespace_uri_1, ast_func_normalize_space_0, ast_func_normalize_space_1, ast_func_string_0, ast_func_string_1, ast_func_substring_2, ast_func_substring_3, ast_func_substring_after, ast_func_substring_before, ast_func_translate, ast_string_constant, ast_variable, xpath_string::c_str(), convert_number_to_string(), xpath_string::data(), xpath_node_set_raw::empty(), eval_boolean(), eval_node_set(), eval_number(), eval_string(), eval_string_concat(), find_substring(), xpath_node_set_raw::first(), is_nan(), xpath_string::length(), local_name(), xpath_context::n, namespace_uri(), normalize_space(), qualified_name(), xpath_stack::result, round_nearest(), string_value(), xpath_stack::temp, translate(), xpath_string::uses_heap(), and xpath_string_const().

Referenced by compare_eq(), eval_boolean(), eval_number(), eval_string(), eval_string_concat(), and evaluate_string_impl().

◆ eval_string_concat()

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

Definition at line 8827 of file pugixml.cpp.

8828  {
8829  assert(_type == ast_func_concat);
8830 
8831  xpath_allocator_capture ct(stack.temp);
8832 
8833  // count the string number
8834  size_t count = 1;
8835  for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++;
8836 
8837  // gather all strings
8838  xpath_string static_buffer[4];
8839  xpath_string* buffer = static_buffer;
8840 
8841  // allocate on-heap for large concats
8842  if (count > sizeof(static_buffer) / sizeof(static_buffer[0]))
8843  {
8844  buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string)));
8845  assert(buffer);
8846  }
8847 
8848  // evaluate all strings to temporary stack
8849  xpath_stack swapped_stack = {stack.temp, stack.result};
8850 
8851  buffer[0] = _left->eval_string(c, swapped_stack);
8852 
8853  size_t pos = 1;
8854  for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack);
8855  assert(pos == count);
8856 
8857  // get total length
8858  size_t length = 0;
8859  for (size_t i = 0; i < count; ++i) length += buffer[i].length();
8860 
8861  // create final string
8862  char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t)));
8863  assert(result);
8864 
8865  char_t* ri = result;
8866 
8867  for (size_t j = 0; j < count; ++j)
8868  for (const char_t* bi = buffer[j].c_str(); *bi; ++bi)
8869  *ri++ = *bi;
8870 
8871  *ri = 0;
8872 
8873  return xpath_string(result, true);
8874  }

References _left, _next, _right, _type, xpath_allocator::allocate(), ast_func_concat, eval_string(), xpath_stack::result, and xpath_stack::temp.

Referenced by eval_string().

◆ is_posinv()

bool xpath_ast_node::is_posinv ( )
inline

Definition at line 9221 of file pugixml.cpp.

9222  {
9223  switch (_type)
9224  {
9225  case ast_func_position:
9226  return false;
9227 
9228  case ast_string_constant:
9229  case ast_number_constant:
9230  case ast_variable:
9231  return true;
9232 
9233  case ast_step:
9234  case ast_step_root:
9235  return true;
9236 
9237  case ast_predicate:
9238  case ast_filter:
9239  case ast_filter_posinv:
9240  return true;
9241 
9242  default:
9243  if (_left && !_left->is_posinv()) return false;
9244 
9245  for (xpath_ast_node* n = _right; n; n = n->_next)
9246  if (!n->is_posinv()) return false;
9247 
9248  return true;
9249  }
9250  }

References _left, _next, _right, _type, ast_filter, ast_filter_posinv, ast_func_position, ast_number_constant, ast_predicate, ast_step, ast_step_root, ast_string_constant, ast_variable, and is_posinv().

Referenced by is_posinv(), and xpath_parser::parse_filter_expression().

◆ operator=()

xpath_ast_node& xpath_ast_node::operator= ( const xpath_ast_node )
private

◆ rettype()

xpath_value_type xpath_ast_node::rettype ( ) const
inline

◆ set_next()

void xpath_ast_node::set_next ( xpath_ast_node value)
inline

Definition at line 8551 of file pugixml.cpp.

8552  {
8553  _next = value;
8554  }

References _next.

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 8556 of file pugixml.cpp.

8557  {
8558  _right = value;
8559  }

References _right.

Referenced by xpath_parser::parse_step().

◆ step_do()

template<class T >
xpath_node_set_raw xpath_ast_node::step_do ( const xpath_context c,
const xpath_stack stack,
v 
)
inlineprivate

Definition at line 8470 of file pugixml.cpp.

8471  {
8472  const axis_t axis = T::axis;
8473  bool attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self);
8474 
8475  xpath_node_set_raw ns;
8476  ns.set_type((axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling) ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted);
8477 
8478  if (_left)
8479  {
8480  xpath_node_set_raw s = _left->eval_node_set(c, stack);
8481 
8482  // self axis preserves the original order
8483  if (axis == axis_self) ns.set_type(s.type());
8484 
8485  for (const xpath_node* it = s.begin(); it != s.end(); ++it)
8486  {
8487  size_t size = ns.size();
8488 
8489  // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes
8490  if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted);
8491 
8492  if (it->node())
8493  step_fill(ns, it->node(), stack.result, v);
8494  else if (attributes)
8495  step_fill(ns, it->attribute(), it->parent(), stack.result, v);
8496 
8497  apply_predicates(ns, size, stack);
8498  }
8499  }
8500  else
8501  {
8502  if (c.n.node())
8503  step_fill(ns, c.n.node(), stack.result, v);
8504  else if (attributes)
8505  step_fill(ns, c.n.attribute(), c.n.parent(), stack.result, v);
8506 
8507  apply_predicates(ns, 0, stack);
8508  }
8509 
8510  // child, attribute and self axes always generate unique set of nodes
8511  // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice
8512  if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted)
8513  ns.remove_duplicates();
8514 
8515  return ns;
8516  }

References _left, apply_predicates(), axis_ancestor, axis_ancestor_or_self, axis_attribute, axis_child, axis_descendant_or_self, axis_following, axis_parent, axis_preceding, axis_preceding_sibling, axis_self, xpath_node_set_raw::begin(), xpath_node_set_raw::end(), eval_node_set(), xpath_context::n, xpath_node_set_raw::remove_duplicates(), xpath_stack::result, xpath_node_set_raw::set_type(), xpath_node_set_raw::size(), step_fill(), and xpath_node_set_raw::type().

Referenced by eval_node_set().

◆ step_fill() [1/2]

template<class T >
void xpath_ast_node::step_fill ( xpath_node_set_raw ns,
const xml_attribute &  a,
const xml_node &  p,
xpath_allocator alloc,
v 
)
inlineprivate

Definition at line 8394 of file pugixml.cpp.

8395  {
8396  const axis_t axis = T::axis;
8397 
8398  switch (axis)
8399  {
8400  case axis_ancestor:
8401  case axis_ancestor_or_self:
8402  {
8403  if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test
8404  step_push(ns, a, p, alloc);
8405 
8406  xml_node cur = p;
8407 
8408  while (cur)
8409  {
8410  step_push(ns, cur, alloc);
8411 
8412  cur = cur.parent();
8413  }
8414 
8415  break;
8416  }
8417 
8419  case axis_self:
8420  {
8421  if (_test == nodetest_type_node) // reject attributes based on principal node type test
8422  step_push(ns, a, p, alloc);
8423 
8424  break;
8425  }
8426 
8427  case axis_following:
8428  {
8429  xml_node cur = p;
8430 
8431  for (;;)
8432  {
8433  if (cur.first_child())
8434  cur = cur.first_child();
8435  else if (cur.next_sibling())
8436  cur = cur.next_sibling();
8437  else
8438  {
8439  while (cur && !cur.next_sibling()) cur = cur.parent();
8440  cur = cur.next_sibling();
8441 
8442  if (!cur) break;
8443  }
8444 
8445  step_push(ns, cur, alloc);
8446  }
8447 
8448  break;
8449  }
8450 
8451  case axis_parent:
8452  {
8453  step_push(ns, p, alloc);
8454 
8455  break;
8456  }
8457 
8458  case axis_preceding:
8459  {
8460  // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding
8461  step_fill(ns, p, alloc, v);
8462  break;
8463  }
8464 
8465  default:
8466  assert(!"Unimplemented axis");
8467  }
8468  }

References _test, axis_ancestor, axis_ancestor_or_self, axis_descendant_or_self, axis_following, axis_parent, axis_preceding, axis_self, nodetest_type_node, step_fill(), and step_push().

◆ step_fill() [2/2]

template<class T >
void xpath_ast_node::step_fill ( xpath_node_set_raw ns,
const xml_node &  n,
xpath_allocator alloc,
 
)
inlineprivate

Definition at line 8224 of file pugixml.cpp.

8225  {
8226  const axis_t axis = T::axis;
8227 
8228  switch (axis)
8229  {
8230  case axis_attribute:
8231  {
8232  for (xml_attribute a = n.first_attribute(); a; a = a.next_attribute())
8233  step_push(ns, a, n, alloc);
8234 
8235  break;
8236  }
8237 
8238  case axis_child:
8239  {
8240  for (xml_node c = n.first_child(); c; c = c.next_sibling())
8241  step_push(ns, c, alloc);
8242 
8243  break;
8244  }
8245 
8246  case axis_descendant:
8248  {
8249  if (axis == axis_descendant_or_self)
8250  step_push(ns, n, alloc);
8251 
8252  xml_node cur = n.first_child();
8253 
8254  while (cur && cur != n)
8255  {
8256  step_push(ns, cur, alloc);
8257 
8258  if (cur.first_child())
8259  cur = cur.first_child();
8260  else if (cur.next_sibling())
8261  cur = cur.next_sibling();
8262  else
8263  {
8264  while (!cur.next_sibling() && cur != n)
8265  cur = cur.parent();
8266 
8267  if (cur != n) cur = cur.next_sibling();
8268  }
8269  }
8270 
8271  break;
8272  }
8273 
8275  {
8276  for (xml_node c = n.next_sibling(); c; c = c.next_sibling())
8277  step_push(ns, c, alloc);
8278 
8279  break;
8280  }
8281 
8283  {
8284  for (xml_node c = n.previous_sibling(); c; c = c.previous_sibling())
8285  step_push(ns, c, alloc);
8286 
8287  break;
8288  }
8289 
8290  case axis_following:
8291  {
8292  xml_node cur = n;
8293 
8294  // exit from this node so that we don't include descendants
8295  while (cur && !cur.next_sibling()) cur = cur.parent();
8296  cur = cur.next_sibling();
8297 
8298  for (;;)
8299  {
8300  step_push(ns, cur, alloc);
8301 
8302  if (cur.first_child())
8303  cur = cur.first_child();
8304  else if (cur.next_sibling())
8305  cur = cur.next_sibling();
8306  else
8307  {
8308  while (cur && !cur.next_sibling()) cur = cur.parent();
8309  cur = cur.next_sibling();
8310 
8311  if (!cur) break;
8312  }
8313  }
8314 
8315  break;
8316  }
8317 
8318  case axis_preceding:
8319  {
8320  xml_node cur = n;
8321 
8322  while (cur && !cur.previous_sibling()) cur = cur.parent();
8323  cur = cur.previous_sibling();
8324 
8325  for (;;)
8326  {
8327  if (cur.last_child())
8328  cur = cur.last_child();
8329  else
8330  {
8331  // leaf node, can't be ancestor
8332  step_push(ns, cur, alloc);
8333 
8334  if (cur.previous_sibling())
8335  cur = cur.previous_sibling();
8336  else
8337  {
8338  do
8339  {
8340  cur = cur.parent();
8341  if (!cur) break;
8342 
8343  if (!node_is_ancestor(cur, n)) step_push(ns, cur, alloc);
8344  }
8345  while (!cur.previous_sibling());
8346 
8347  cur = cur.previous_sibling();
8348 
8349  if (!cur) break;
8350  }
8351  }
8352  }
8353 
8354  break;
8355  }
8356 
8357  case axis_ancestor:
8358  case axis_ancestor_or_self:
8359  {
8360  if (axis == axis_ancestor_or_self)
8361  step_push(ns, n, alloc);
8362 
8363  xml_node cur = n.parent();
8364 
8365  while (cur)
8366  {
8367  step_push(ns, cur, alloc);
8368 
8369  cur = cur.parent();
8370  }
8371 
8372  break;
8373  }
8374 
8375  case axis_self:
8376  {
8377  step_push(ns, n, alloc);
8378 
8379  break;
8380  }
8381 
8382  case axis_parent:
8383  {
8384  if (n.parent()) step_push(ns, n.parent(), alloc);
8385 
8386  break;
8387  }
8388 
8389  default:
8390  assert(!"Unimplemented axis");
8391  }
8392  }

References axis_ancestor, axis_ancestor_or_self, axis_attribute, axis_child, axis_descendant, axis_descendant_or_self, axis_following, axis_following_sibling, axis_parent, axis_preceding, axis_preceding_sibling, axis_self, node_is_ancestor(), and step_push().

Referenced by step_do(), and step_fill().

◆ step_push() [1/2]

void xpath_ast_node::step_push ( xpath_node_set_raw ns,
const xml_attribute &  a,
const xml_node &  parent,
xpath_allocator alloc 
)
inlineprivate

Definition at line 8144 of file pugixml.cpp.

8145  {
8146  if (!a) return;
8147 
8148  const char_t* name = a.name();
8149 
8150  // There are no attribute nodes corresponding to attributes that declare namespaces
8151  // That is, "xmlns:..." or "xmlns"
8152  if (starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')) return;
8153 
8154  switch (_test)
8155  {
8156  case nodetest_name:
8157  if (strequal(name, _data.nodetest)) ns.push_back(xpath_node(a, parent), alloc);
8158  break;
8159 
8160  case nodetest_type_node:
8161  case nodetest_all:
8162  ns.push_back(xpath_node(a, parent), alloc);
8163  break;
8164 
8166  if (starts_with(name, _data.nodetest))
8167  ns.push_back(xpath_node(a, parent), alloc);
8168  break;
8169 
8170  default:
8171  ;
8172  }
8173  }

References _data, _test, nodetest_all, nodetest_all_in_namespace, nodetest_name, nodetest_type_node, xpath_node_set_raw::push_back(), starts_with(), and strequal().

Referenced by step_fill().

◆ step_push() [2/2]

void xpath_ast_node::step_push ( xpath_node_set_raw ns,
const xml_node &  n,
xpath_allocator alloc 
)
inlineprivate

Definition at line 8175 of file pugixml.cpp.

8176  {
8177  if (!n) return;
8178 
8179  switch (_test)
8180  {
8181  case nodetest_name:
8182  if (n.type() == node_element && strequal(n.name(), _data.nodetest)) ns.push_back(n, alloc);
8183  break;
8184 
8185  case nodetest_type_node:
8186  ns.push_back(n, alloc);
8187  break;
8188 
8189  case nodetest_type_comment:
8190  if (n.type() == node_comment)
8191  ns.push_back(n, alloc);
8192  break;
8193 
8194  case nodetest_type_text:
8195  if (n.type() == node_pcdata || n.type() == node_cdata)
8196  ns.push_back(n, alloc);
8197  break;
8198 
8199  case nodetest_type_pi:
8200  if (n.type() == node_pi)
8201  ns.push_back(n, alloc);
8202  break;
8203 
8204  case nodetest_pi:
8205  if (n.type() == node_pi && strequal(n.name(), _data.nodetest))
8206  ns.push_back(n, alloc);
8207  break;
8208 
8209  case nodetest_all:
8210  if (n.type() == node_element)
8211  ns.push_back(n, alloc);
8212  break;
8213 
8215  if (n.type() == node_element && starts_with(n.name(), _data.nodetest))
8216  ns.push_back(n, alloc);
8217  break;
8218 
8219  default:
8220  assert(!"Unknown axis");
8221  }
8222  }

References _data, _test, nodetest_all, nodetest_all_in_namespace, nodetest_name, nodetest_pi, nodetest_type_comment, nodetest_type_node, nodetest_type_pi, nodetest_type_text, xpath_node_set_raw::push_back(), starts_with(), and strequal().

Member Data Documentation

◆ _axis

char xpath_ast_node::_axis
private

Definition at line 7926 of file pugixml.cpp.

Referenced by eval_node_set().

◆ _data

union { ... } xpath_ast_node::_data

◆ _left

xpath_ast_node* xpath_ast_node::_left
private

◆ _next

xpath_ast_node* xpath_ast_node::_next
private

Definition at line 7932 of file pugixml.cpp.

Referenced by apply_predicates(), eval_string(), eval_string_concat(), is_posinv(), and set_next().

◆ _rettype

char xpath_ast_node::_rettype
private

Definition at line 7923 of file pugixml.cpp.

Referenced by eval_boolean(), eval_node_set(), eval_number(), eval_string(), and rettype().

◆ _right

xpath_ast_node* xpath_ast_node::_right
private

◆ _test

char xpath_ast_node::_test
private

Definition at line 7927 of file pugixml.cpp.

Referenced by step_fill(), and step_push().

◆ _type

char xpath_ast_node::_type
private

◆ nodetest

const char_t* xpath_ast_node::nodetest

Definition at line 7943 of file pugixml.cpp.

◆ number

double xpath_ast_node::number

Definition at line 7939 of file pugixml.cpp.

◆ string

const char_t* xpath_ast_node::string

Definition at line 7937 of file pugixml.cpp.

◆ variable

xpath_variable* xpath_ast_node::variable

Definition at line 7941 of file pugixml.cpp.


The documentation for this class was generated from the following file:
xpath_context
Definition: pugixml.cpp:7454
namespace_uri
const PUGI__FN char_t * namespace_uri(const xml_node &node)
Definition: pugixml.cpp:7053
xpath_ast_node::apply_predicates
void apply_predicates(xpath_node_set_raw &ns, size_t first, const xpath_stack &stack)
Definition: pugixml.cpp:8134
axis_descendant
@ axis_descendant
Definition: pugixml.cpp:7887
axis_ancestor_or_self
@ axis_ancestor_or_self
Definition: pugixml.cpp:7884
xpath_node_set_raw::end
xpath_node * end() const
Definition: pugixml.cpp:7357
local_name
const PUGI__FN char_t * local_name(const xpath_node &node)
Definition: pugixml.cpp:7022
ast_func_translate
@ ast_func_translate
Definition: pugixml.cpp:7865
ast_func_last
@ ast_func_last
Definition: pugixml.cpp:7842
xpath_node_set_raw::sort_do
void sort_do()
Definition: pugixml.cpp:7421
xpath_ast_node::step_do
xpath_node_set_raw step_do(const xpath_context &c, const xpath_stack &stack, T v)
Definition: pugixml.cpp:8470
ast_func_starts_with
@ ast_func_starts_with
Definition: pugixml.cpp:7855
round_nearest_nzero
PUGI__FN double round_nearest_nzero(double value)
Definition: pugixml.cpp:7010
ast_number_constant
@ ast_number_constant
Definition: pugixml.cpp:7840
ast_op_add
@ ast_op_add
Definition: pugixml.cpp:7829
xpath_node_set_raw::push_back
void push_back(const xpath_node &node, xpath_allocator *alloc)
Definition: pugixml.cpp:7377
ast_op_divide
@ ast_op_divide
Definition: pugixml.cpp:7832
xpath_context::position
size_t position
Definition: pugixml.cpp:7457
ast_op_equal
@ ast_op_equal
Definition: pugixml.cpp:7823
ast_func_name_0
@ ast_func_name_0
Definition: pugixml.cpp:7850
equal_to
Definition: pugixml.cpp:5959
not_equal_to
Definition: pugixml.cpp:5967
xpath_node_set_raw::truncate
void truncate(xpath_node *pos)
Definition: pugixml.cpp:7426
xpath_node_set_raw::set_type
void set_type(xpath_node_set::type_t value)
Definition: pugixml.cpp:7446
xpath_node_set_raw::first
xpath_node first() const
Definition: pugixml.cpp:7372
xpath_node_set_raw::empty
bool empty() const
Definition: pugixml.cpp:7362
xpath_ast_node::step_push
void step_push(xpath_node_set_raw &ns, const xml_attribute &a, const xml_node &parent, xpath_allocator *alloc)
Definition: pugixml.cpp:8144
ast_func_local_name_1
@ ast_func_local_name_1
Definition: pugixml.cpp:7847
xpath_ast_node::_right
xpath_ast_node * _right
Definition: pugixml.cpp:7931
ast_func_id
@ ast_func_id
Definition: pugixml.cpp:7845
ast_filter_posinv
@ ast_filter_posinv
Definition: pugixml.cpp:7838
ast_op_less
@ ast_op_less
Definition: pugixml.cpp:7825
xpath_ast_node
Definition: pugixml.cpp:7918
ast_op_union
@ ast_op_union
Definition: pugixml.cpp:7835
ast_op_not_equal
@ ast_op_not_equal
Definition: pugixml.cpp:7824
ast_func_substring_after
@ ast_func_substring_after
Definition: pugixml.cpp:7858
xpath_ast_node::rettype
xpath_value_type rettype() const
Definition: pugixml.cpp:9252
qualified_name
const PUGI__FN char_t * qualified_name(const xpath_node &node)
Definition: pugixml.cpp:7017
swap
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:5991
ast_func_namespace_uri_1
@ ast_func_namespace_uri_1
Definition: pugixml.cpp:7849
ast_func_position
@ ast_func_position
Definition: pugixml.cpp:7843
xpath_stack
Definition: pugixml.cpp:6362
axis_ancestor
@ axis_ancestor
Definition: pugixml.cpp:7883
convert_string_to_number
PUGI__FN double convert_string_to_number(const char_t *string)
Definition: pugixml.cpp:6968
axis_preceding
@ axis_preceding
Definition: pugixml.cpp:7893
xpath_ast_node::eval_string
xpath_string eval_string(const xpath_context &c, const xpath_stack &stack)
Definition: pugixml.cpp:8876
ast_op_negate
@ ast_op_negate
Definition: pugixml.cpp:7834
xpath_node_set_raw::append
void append(const xpath_node *begin_, const xpath_node *end_, xpath_allocator *alloc)
Definition: pugixml.cpp:7399
ast_func_local_name_0
@ ast_func_local_name_0
Definition: pugixml.cpp:7846
xpath_context::size
size_t size
Definition: pugixml.cpp:7457
starts_with
PUGI__NS_END PUGI__NS_BEGIN PUGI__FN bool starts_with(const char_t *string, const char_t *pattern)
Definition: pugixml.cpp:6534
ast_func_string_1
@ ast_func_string_1
Definition: pugixml.cpp:7853
xpath_ast_node::eval_boolean
bool eval_boolean(const xpath_context &c, const xpath_stack &stack)
Definition: pugixml.cpp:8561
xpath_ast_node::_test
char _test
Definition: pugixml.cpp:7927
axis_namespace
@ axis_namespace
Definition: pugixml.cpp:7891
nodetest_all
@ nodetest_all
Definition: pugixml.cpp:7907
ast_func_number_1
@ ast_func_number_1
Definition: pugixml.cpp:7872
nodetest_type_comment
@ nodetest_type_comment
Definition: pugixml.cpp:7903
ast_func_boolean
@ ast_func_boolean
Definition: pugixml.cpp:7866
xpath_ast_node::_axis
char _axis
Definition: pugixml.cpp:7926
ast_func_concat
@ ast_func_concat
Definition: pugixml.cpp:7854
xpath_ast_node::eval_node_set
xpath_node_set_raw eval_node_set(const xpath_context &c, const xpath_stack &stack)
Definition: pugixml.cpp:9094
axis_following_sibling
@ axis_following_sibling
Definition: pugixml.cpp:7890
ast_func_number_0
@ ast_func_number_0
Definition: pugixml.cpp:7871
nodetest_type_node
@ nodetest_type_node
Definition: pugixml.cpp:7902
xpath_ast_node::_type
char _type
Definition: pugixml.cpp:7922
ast_func_substring_3
@ ast_func_substring_3
Definition: pugixml.cpp:7860
ast_op_greater
@ ast_op_greater
Definition: pugixml.cpp:7826
ast_step
@ ast_step
Definition: pugixml.cpp:7877
ast_func_contains
@ ast_func_contains
Definition: pugixml.cpp:7856
xpath_string::data
char_t * data(xpath_allocator *alloc)
Definition: pugixml.cpp:6494
nodetest_name
@ nodetest_name
Definition: pugixml.cpp:7901
xpath_ast_node::apply_predicate
void apply_predicate(xpath_node_set_raw &ns, size_t first, xpath_ast_node *expr, const xpath_stack &stack)
Definition: pugixml.cpp:8108
ast_op_greater_or_equal
@ ast_op_greater_or_equal
Definition: pugixml.cpp:7828
ast_variable
@ ast_variable
Definition: pugixml.cpp:7841
ast_filter
@ ast_filter
Definition: pugixml.cpp:7837
xpath_ast_node::eval_number
double eval_number(const xpath_context &c, const xpath_stack &stack)
Definition: pugixml.cpp:8690
xpath_allocator_capture
Definition: pugixml.cpp:6347
ast_op_multiply
@ ast_op_multiply
Definition: pugixml.cpp:7831
axis_following
@ axis_following
Definition: pugixml.cpp:7889
normalize_space
PUGI__FN void normalize_space(char_t *buffer)
Definition: pugixml.cpp:7097
ast_func_lang
@ ast_func_lang
Definition: pugixml.cpp:7870
nodetest_type_text
@ nodetest_type_text
Definition: pugixml.cpp:7905
ast_func_true
@ ast_func_true
Definition: pugixml.cpp:7868
round_nearest
PUGI__FN double round_nearest(double value)
Definition: pugixml.cpp:7005
xpath_ast_node::_rettype
char _rettype
Definition: pugixml.cpp:7923
nodetest_type_pi
@ nodetest_type_pi
Definition: pugixml.cpp:7904
xpath_ast_node::_data
union xpath_ast_node::@7 _data
ast_op_less_or_equal
@ ast_op_less_or_equal
Definition: pugixml.cpp:7827
ast_func_substring_2
@ ast_func_substring_2
Definition: pugixml.cpp:7859
ast_func_substring_before
@ ast_func_substring_before
Definition: pugixml.cpp:7857
xpath_ast_node::_left
xpath_ast_node * _left
Definition: pugixml.cpp:7930
xpath_ast_node::compare_eq
static bool compare_eq(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
Definition: pugixml.cpp:7949
string_value
PUGI__FN xpath_string string_value(const xpath_node &na, xpath_allocator *alloc)
Definition: pugixml.cpp:6570
ast_func_normalize_space_0
@ ast_func_normalize_space_0
Definition: pugixml.cpp:7863
axis_preceding_sibling
@ axis_preceding_sibling
Definition: pugixml.cpp:7894
xpath_stack::result
xpath_allocator * result
Definition: pugixml.cpp:6364
less_equal
Definition: pugixml.cpp:5983
xpath_ast_node::compare_rel
static bool compare_rel(xpath_ast_node *lhs, xpath_ast_node *rhs, const xpath_context &c, const xpath_stack &stack, const Comp &comp)
Definition: pugixml.cpp:8037
convert_number_to_string
PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator *alloc)
Definition: pugixml.cpp:6871
axis_parent
@ axis_parent
Definition: pugixml.cpp:7892
ast_func_normalize_space_1
@ ast_func_normalize_space_1
Definition: pugixml.cpp:7864
strequal
PUGI__FN bool strequal(const char_t *src, const char_t *dst)
Definition: pugixml.cpp:188
ast_func_not
@ ast_func_not
Definition: pugixml.cpp:7867
convert_number_to_boolean
PUGI__FN bool convert_number_to_boolean(double value)
Definition: pugixml.cpp:6812
nodetest_pi
@ nodetest_pi
Definition: pugixml.cpp:7906
ast_func_count
@ ast_func_count
Definition: pugixml.cpp:7844
xpath_string::length
size_t length() const
Definition: pugixml.cpp:6489
tolower_ascii
PUGI__FN char_t tolower_ascii(char_t ch)
Definition: pugixml.cpp:6565
axis_to_type
Definition: pugixml.cpp:7911
node_is_ancestor
PUGI__FN bool node_is_ancestor(xml_node parent, xml_node node)
Definition: pugixml.cpp:6660
ast_func_floor
@ ast_func_floor
Definition: pugixml.cpp:7874
xpath_node_set_raw::remove_duplicates
void remove_duplicates()
Definition: pugixml.cpp:7433
ast_func_namespace_uri_0
@ ast_func_namespace_uri_0
Definition: pugixml.cpp:7848
xpath_context::n
xpath_node n
Definition: pugixml.cpp:7456
less
Definition: pugixml.cpp:5975
xpath_node_set_raw
Definition: pugixml.cpp:7339
xpath_ast_node::step_fill
void step_fill(xpath_node_set_raw &ns, const xml_node &n, xpath_allocator *alloc, T)
Definition: pugixml.cpp:8224
xpath_string_const
PUGI__FN xpath_string xpath_string_const(const char_t *str)
Definition: pugixml.cpp:6527
ast_func_false
@ ast_func_false
Definition: pugixml.cpp:7869
xpath_node_set_raw::begin
xpath_node * begin() const
Definition: pugixml.cpp:7352
xpath_ast_node::is_posinv
bool is_posinv()
Definition: pugixml.cpp:9221
axis_t
axis_t
Definition: pugixml.cpp:7881
find_substring
const PUGI__FN char_t * find_substring(const char_t *s, const char_t *p)
Definition: pugixml.cpp:6554
nodetest_all_in_namespace
@ nodetest_all_in_namespace
Definition: pugixml.cpp:7908
xpath_allocator::allocate
void * allocate(size_t size)
Definition: pugixml.cpp:6250
ast_func_name_1
@ ast_func_name_1
Definition: pugixml.cpp:7851
xpath_string::empty
bool empty() const
Definition: pugixml.cpp:6506
ast_func_string_0
@ ast_func_string_0
Definition: pugixml.cpp:7852
ast_func_string_length_0
@ ast_func_string_length_0
Definition: pugixml.cpp:7861
ast_func_ceiling
@ ast_func_ceiling
Definition: pugixml.cpp:7875
ast_func_round
@ ast_func_round
Definition: pugixml.cpp:7876
axis_attribute
@ axis_attribute
Definition: pugixml.cpp:7885
ast_step_root
@ ast_step_root
Definition: pugixml.cpp:7878
ast_op_and
@ ast_op_and
Definition: pugixml.cpp:7822
xpath_node_set_raw::size
size_t size() const
Definition: pugixml.cpp:7367
ast_func_sum
@ ast_func_sum
Definition: pugixml.cpp:7873
xpath_ast_node::_next
xpath_ast_node * _next
Definition: pugixml.cpp:7932
axis_descendant_or_self
@ axis_descendant_or_self
Definition: pugixml.cpp:7888
ast_string_constant
@ ast_string_constant
Definition: pugixml.cpp:7839
ast_op_subtract
@ ast_op_subtract
Definition: pugixml.cpp:7830
ast_op_mod
@ ast_op_mod
Definition: pugixml.cpp:7833
translate
PUGI__FN void translate(char_t *buffer, const char_t *from, const char_t *to)
Definition: pugixml.cpp:7123
xpath_string
Definition: pugixml.cpp:6402
ast_func_string_length_1
@ ast_func_string_length_1
Definition: pugixml.cpp:7862
xpath_string::c_str
const char_t * c_str() const
Definition: pugixml.cpp:6484
ast_op_or
@ ast_op_or
Definition: pugixml.cpp:7821
xpath_ast_node::eval_string_concat
xpath_string eval_string_concat(const xpath_context &c, const xpath_stack &stack)
Definition: pugixml.cpp:8827
axis_self
@ axis_self
Definition: pugixml.cpp:7895
is_nan
PUGI__FN bool is_nan(double value)
Definition: pugixml.cpp:6767
xpath_string::uses_heap
bool uses_heap() const
Definition: pugixml.cpp:6521
ast_predicate
@ ast_predicate
Definition: pugixml.cpp:7836
axis_child
@ axis_child
Definition: pugixml.cpp:7886
xpath_stack::temp
xpath_allocator * temp
Definition: pugixml.cpp:6365
xpath_node_set_raw::type
xpath_node_set::type_t type() const
Definition: pugixml.cpp:7441

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001