#include "scope.h" #include "parse.h" #include #include namespace scope { scope_t wildcard("x-any"); // ========= // = Scope = // ========= scope_t::scope_t () { ; } scope_t::scope_t (char const* scope) { setup(scope); } scope_t::scope_t (std::string const& scope) { setup(scope); } void scope_t::setup (std::string const& scope) { path.reset(new scope::types::path_t); scope::parse::path(scope.data(), scope.data() + scope.size(), *path); } bool scope_t::has_prefix (scope_t const& rhs) const { std::vector const& lhsScopes = path ? path->scopes : std::vector(); std::vector const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector(); size_t i = 0; for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i) { if(lhsScopes[i] != rhsScopes[i]) break; } return i == rhsScopes.size(); } scope_t scope_t::append (std::string const& atom) const { scope_t res; res.path.reset(new types::path_t(path ? *path : types::path_t())); types::scope_t scope; parse::scope(atom.data(), atom.data() + atom.size(), scope); res.path->scopes.push_back(scope); return res; } scope_t scope_t::parent () const { scope_t res; if(path && !path->scopes.empty()) { res.path.reset(new types::path_t(*path)); res.path->scopes.pop_back(); } return res; } bool scope_t::operator== (scope_t const& rhs) const { return (!path && !rhs.path) || (path && rhs.path && *path == *rhs.path); } bool scope_t::operator!= (scope_t const& rhs) const { return !(*this == rhs); } bool scope_t::operator< (scope_t const& rhs) const { return (!path && rhs.path) || (path && rhs.path && *path < *rhs.path); } scope_t::operator bool () const { return path; } scope_t shared_prefix (scope_t const& lhs, scope_t const& rhs) { std::vector const& lhsScopes = lhs.path ? lhs.path->scopes : std::vector(); std::vector const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector(); size_t i = 0; for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i) { if(lhsScopes[i] != rhsScopes[i]) break; } scope_t res; res.path.reset(new types::path_t); res.path->scopes.insert(res.path->scopes.end(), lhsScopes.begin(), lhsScopes.begin() + i); return res; } std::string xml_difference (scope_t const& lhs, scope_t const& rhs, std::string const& open, std::string const& close) { std::vector const& lhsScopes = lhs.path ? lhs.path->scopes : std::vector(); std::vector const& rhsScopes = rhs.path ? rhs.path->scopes : std::vector(); size_t i = 0; for(; i < std::min(lhsScopes.size(), rhsScopes.size()); ++i) { if(lhsScopes[i] != rhsScopes[i]) break; } std::string res = ""; for(size_t j = lhsScopes.size(); j > i; --j) res += open + "/" + to_s(lhsScopes[j-1]) + close; for(size_t j = i; j < rhsScopes.size(); ++j) res += open + to_s(rhsScopes[j]) + close; return res; } std::string to_s (scope_t const& s) { return s.path ? to_s(*s.path) : ""; } std::string to_s (context_t const& c) { return c.left == c.right ? text::format("(l/r ‘%s’)", to_s(c.left).c_str()) : text::format("(left ‘%s’, right ‘%s’)", to_s(c.left).c_str(), to_s(c.right).c_str()); } // ============ // = Selector = // ============ selector_t::selector_t () { ; } selector_t::selector_t (char const* str) { setup(str); } selector_t::selector_t (std::string const& str) { setup(str); } void selector_t::setup (std::string const& str) { selector.reset(new scope::types::selector_t); scope::parse::selector(str.data(), str.data() + str.size(), *selector); } std::string to_s (selector_t const& s) { return s.selector ? to_s(*s.selector) : ""; } // ============ // = Matching = // ============ bool selector_t::does_match (context_t const& scope, double* rank) const { if(!selector) { if(rank) *rank = 0; return true; } if(!scope.left.path || !scope.right.path) return false; return scope.left == wildcard || scope.right == wildcard || selector->does_match(*scope.left.path, *scope.right.path, rank); } }