diff options
| -rw-r--r-- | src/pugixpath.cpp | 239 | 
1 files changed, 106 insertions, 133 deletions
diff --git a/src/pugixpath.cpp b/src/pugixpath.cpp index 60f65b8..bc51b4d 100644 --- a/src/pugixpath.cpp +++ b/src/pugixpath.cpp @@ -503,33 +503,33 @@ namespace  		return PUGIXML_TEXT("");
  	}
 -	template <class T> struct equal_to
 +	struct equal_to
  	{
 -		bool operator()(const T& lhs, const T& rhs) const
 +		template <typename T> bool operator()(const T& lhs, const T& rhs) const
  		{
  			return lhs == rhs;
  		}
  	};
 -	template <class T> struct not_equal_to
 +	struct not_equal_to
  	{
 -		bool operator()(const T& lhs, const T& rhs) const
 +		template <typename T> bool operator()(const T& lhs, const T& rhs) const
  		{
  			return lhs != rhs;
  		}
  	};
 -	template <class T> struct less
 +	struct less
  	{
 -		bool operator()(const T& lhs, const T& rhs) const
 +		template <typename T> bool operator()(const T& lhs, const T& rhs) const
  		{
  			return lhs < rhs;
  		}
  	};
 -	template <class T> struct less_equal
 +	struct less_equal
  	{
 -		bool operator()(const T& lhs, const T& rhs) const
 +		template <typename T> bool operator()(const T& lhs, const T& rhs) const
  		{
  			return lhs <= rhs;
  		}
 @@ -1296,158 +1296,131 @@ namespace pugi  		xpath_ast_node(const xpath_ast_node&);
  		xpath_ast_node& operator=(const xpath_ast_node&);
 -		template <class Cbool, class Cdouble, class Cstring> struct compare_eq
 +		template <class Comp> static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const Comp& comp = Comp())
  		{
 -			static bool run(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c)
 +			xpath_type_t lt = lhs->rettype(), rt = rhs->rettype();
 +
 +			if (lt != xpath_type_node_set && rt != xpath_type_node_set)
  			{
 -				if (lhs->rettype() != xpath_type_node_set && rhs->rettype() != xpath_type_node_set)
 -				{
 -					if (lhs->rettype() == xpath_type_boolean || rhs->rettype() == xpath_type_boolean)
 -						return Cbool()(lhs->eval_boolean(c), rhs->eval_boolean(c));
 -					else if (lhs->rettype() == xpath_type_number || rhs->rettype() == xpath_type_number)
 -						return Cdouble()(lhs->eval_number(c), rhs->eval_number(c));
 -					else if (lhs->rettype() == xpath_type_string || rhs->rettype() == xpath_type_string)
 -						return Cstring()(lhs->eval_string(c), rhs->eval_string(c));
 -				}
 -				else if (lhs->rettype() == xpath_type_node_set && rhs->rettype() == xpath_type_node_set)
 -				{
 -					xpath_node_set ls = lhs->eval_node_set(c);
 -					xpath_node_set rs = rhs->eval_node_set(c);
 -					
 -					for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 +				if (lt == xpath_type_boolean || rt == xpath_type_boolean)
 +					return comp(lhs->eval_boolean(c), rhs->eval_boolean(c));
 +				else if (lt == xpath_type_number || rt == xpath_type_number)
 +					return comp(lhs->eval_number(c), rhs->eval_number(c));
 +				else if (lt == xpath_type_string || rt == xpath_type_string)
 +					return comp(lhs->eval_string(c), rhs->eval_string(c));
 +			}
 +			else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
 +			{
 +				xpath_node_set ls = lhs->eval_node_set(c);
 +				xpath_node_set rs = rhs->eval_node_set(c);
 +
 +				for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
  					for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
  					{
 -						if (Cstring()(string_value(*li), string_value(*ri)))
 +						if (comp(string_value(*li), string_value(*ri)))
  							return true;
  					}
 -					
 -					return false;
 -				}
 -				else if (lhs->rettype() != xpath_type_node_set && rhs->rettype() == xpath_type_node_set)
 -				{
 -					if (lhs->rettype() == xpath_type_boolean)
 -						return Cbool()(lhs->eval_boolean(c), rhs->eval_boolean(c));
 -					else if (lhs->rettype() == xpath_type_number)
 -					{
 -						double l = lhs->eval_number(c);
 -						xpath_node_set rs = rhs->eval_node_set(c);
 -						
 -						for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
 -						{
 -							if (Cdouble()(l, convert_string_to_number(string_value(*ri).c_str())) == true)
 -								return true;
 -						}
 -						
 -						return false;
 -					}
 -					else if (lhs->rettype() == xpath_type_string)
 -					{
 -						string_t l = lhs->eval_string(c);
 -						xpath_node_set rs = rhs->eval_node_set(c);
 -
 -						for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
 -						{
 -							if (Cstring()(l, string_value(*ri)) == true)
 -								return true;
 -						}
 -						
 -						return false;
 -					}
 -				}
 -				else if (lhs->rettype() == xpath_type_node_set && rhs->rettype() != xpath_type_node_set)
 -				{
 -					if (rhs->rettype() == xpath_type_boolean)
 -						return Cbool()(lhs->eval_boolean(c), rhs->eval_boolean(c));
 -					else if (rhs->rettype() == xpath_type_number)
 -					{
 -						xpath_node_set ls = lhs->eval_node_set(c);
 -						double r = rhs->eval_number(c);
 -
 -						for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 -						{
 -							if (Cdouble()(convert_string_to_number(string_value(*li).c_str()), r) == true)
 -								return true;
 -						}
 -						
 -						return false;
 -					}
 -					else if (rhs->rettype() == xpath_type_string)
 -					{
 -						xpath_node_set ls = lhs->eval_node_set(c);
 -						string_t r = rhs->eval_string(c);
 -
 -						for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 -						{
 -							if (Cstring()(string_value(*li), r) == true)
 -								return true;
 -						}
 -						
 -						return false;
 -					}
 -				}
 -  		        assert(!"Wrong types");
  				return false;
  			}
 -		};
 -
 -		template <class Cdouble> struct compare_rel
 -		{
 -			static bool run(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c)
 +			else
  			{
 -				if (lhs->rettype() != xpath_type_node_set && rhs->rettype() != xpath_type_node_set)
 -					return Cdouble()(lhs->eval_number(c), rhs->eval_number(c));
 -				else if (lhs->rettype() == xpath_type_node_set && rhs->rettype() == xpath_type_node_set)
 +				if (lt == xpath_type_node_set)
 +				{
 +					std::swap(lhs, rhs);
 +					std::swap(lt, rt);
 +				}
 +
 +				if (lt == xpath_type_boolean)
 +					return comp(lhs->eval_boolean(c), rhs->eval_boolean(c));
 +				else if (lt == xpath_type_number)
  				{
 -					xpath_node_set ls = lhs->eval_node_set(c);
 +					double l = lhs->eval_number(c);
  					xpath_node_set rs = rhs->eval_node_set(c);
 -					
 -					for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 +
 +					for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
  					{
 -						double l = convert_string_to_number(string_value(*li).c_str());
 -						
 -						for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
 -						{
 -							if (Cdouble()(l, convert_string_to_number(string_value(*ri).c_str())) == true)
 -								return true;
 -						}
 +						if (comp(l, convert_string_to_number(string_value(*ri).c_str())))
 +							return true;
  					}
 -					
 +
  					return false;
  				}
 -				else if (lhs->rettype() != xpath_type_node_set && rhs->rettype() == xpath_type_node_set)
 +				else if (lt == xpath_type_string)
  				{
 -					double l = lhs->eval_number(c);
 +					string_t l = lhs->eval_string(c);
  					xpath_node_set rs = rhs->eval_node_set(c);
 -						
 +
  					for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
  					{
 -						if (Cdouble()(l, convert_string_to_number(string_value(*ri).c_str())) == true)
 +						if (comp(l, string_value(*ri)))
  							return true;
  					}
 -					
 +
  					return false;
  				}
 -				else if (lhs->rettype() == xpath_type_node_set && rhs->rettype() != xpath_type_node_set)
 +			}
 +
 +			assert(!"Wrong types");
 +			return false;
 +		}
 +
 +		template <class Comp> static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const Comp& comp = Comp())
 +		{
 +			xpath_type_t lt = lhs->rettype(), rt = rhs->rettype();
 +
 +			if (lt != xpath_type_node_set && rt != xpath_type_node_set)
 +				return comp(lhs->eval_number(c), rhs->eval_number(c));
 +			else if (lt == xpath_type_node_set && rt == xpath_type_node_set)
 +			{
 +				xpath_node_set ls = lhs->eval_node_set(c);
 +				xpath_node_set rs = rhs->eval_node_set(c);
 +
 +				for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
  				{
 -					xpath_node_set ls = lhs->eval_node_set(c);
 -					double r = rhs->eval_number(c);
 +					double l = convert_string_to_number(string_value(*li).c_str());
 -					for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 +					for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
  					{
 -						if (Cdouble()(convert_string_to_number(string_value(*li).c_str()), r) == true)
 +						if (comp(l, convert_string_to_number(string_value(*ri).c_str())))
  							return true;
  					}
 -					
 -					return false;
  				}
 -				else
 +
 +				return false;
 +			}
 +			else if (lt != xpath_type_node_set && rt == xpath_type_node_set)
 +			{
 +				double l = lhs->eval_number(c);
 +				xpath_node_set rs = rhs->eval_node_set(c);
 +
 +				for (xpath_node_set::const_iterator ri = rs.begin(); ri != rs.end(); ++ri)
  				{
 -					assert(!"Wrong types");
 -					return false;
 +					if (comp(l, convert_string_to_number(string_value(*ri).c_str())))
 +						return true;
  				}
 +
 +				return false;
  			}
 -		};
 +			else if (lt == xpath_type_node_set && rt != xpath_type_node_set)
 +			{
 +				xpath_node_set ls = lhs->eval_node_set(c);
 +				double r = rhs->eval_number(c);
 +
 +				for (xpath_node_set::const_iterator li = ls.begin(); li != ls.end(); ++li)
 +				{
 +					if (comp(convert_string_to_number(string_value(*li).c_str()), r))
 +						return true;
 +				}
 +
 +				return false;
 +			}
 +			else
 +			{
 +				assert(!"Wrong types");
 +				return false;
 +			}
 +		}
  		void apply_predicate(xpath_node_set& ns, size_t first, xpath_ast_node* expr, const xpath_context& context)
  		{
 @@ -1974,22 +1947,22 @@ namespace pugi  				else return m_right->eval_boolean(c);
  			case ast_op_equal:
 -				return compare_eq<equal_to<bool>, equal_to<double>, equal_to<string_t> >::run(m_left, m_right, c);
 +				return compare_eq(m_left, m_right, c, equal_to());
  			case ast_op_not_equal:
 -				return compare_eq<not_equal_to<bool>, not_equal_to<double>, not_equal_to<string_t> >::run(m_left, m_right, c);
 +				return compare_eq(m_left, m_right, c, not_equal_to());
  			case ast_op_less:
 -				return compare_rel<less<double> >::run(m_left, m_right, c);
 +				return compare_rel(m_left, m_right, c, less());
  			case ast_op_greater:
 -				return compare_rel<less<double> >::run(m_right, m_left, c);
 +				return compare_rel(m_right, m_left, c, less());
  			case ast_op_less_or_equal:
 -				return compare_rel<less_equal<double> >::run(m_left, m_right, c);
 +				return compare_rel(m_left, m_right, c, less_equal());
  			case ast_op_greater_or_equal:
 -				return compare_rel<less_equal<double> >::run(m_right, m_left, c);
 +				return compare_rel(m_right, m_left, c, less_equal());
  			case ast_func_starts_with:
  				return starts_with(m_left->eval_string(c).c_str(), m_right->eval_string(c).c_str());
  | 
