diff options
-rw-r--r-- | src/core/CSS.cpp | 46 | ||||
-rw-r--r-- | src/core/CSS.hpp | 44 |
2 files changed, 79 insertions, 11 deletions
diff --git a/src/core/CSS.cpp b/src/core/CSS.cpp index 06d062e..c2397d1 100644 --- a/src/core/CSS.cpp +++ b/src/core/CSS.cpp @@ -20,24 +20,19 @@ namespace ousia { -/** - * This returns all children of this SelectorNode that are connected by - * the given operator, have the given className and the given - * PseudoSelector. - */ std::vector<Rooted<SelectorNode>> SelectorNode::getChildren( const SelectionOperator &op, const std::string &className, const PseudoSelector &select) { std::vector<Rooted<SelectorNode>> out; - for(auto& e : edges){ - if(e->getSelectionOperator() != op){ + for (auto &e : edges) { + if (e->getSelectionOperator() != op) { continue; } - if(e->getTarget()->getName() != className){ + if (e->getTarget()->getName() != className) { continue; } - if(e->getTarget()->getPseudoSelector() != select){ + if (e->getTarget()->getPseudoSelector() != select) { continue; } out.push_back(e->getTarget()); @@ -45,5 +40,36 @@ std::vector<Rooted<SelectorNode>> SelectorNode::getChildren( return out; } - +std::vector<Rooted<SelectorNode>> SelectorNode::append( + Rooted<SelectorEdge> edge) +{ + std::vector<Rooted<SelectorNode>> out; + // look if we already have a child in an equivalent edge. + std::vector<Rooted<SelectorNode>> children = + getChildren(edge->getSelectionOperator(), edge->getTarget()->getName(), + edge->getTarget()->getPseudoSelector()); + // note that this can only be one child or no child. + if (children.size() == 0) { + // if there is no child the appending process is trivial: We can just + // add the whole subtree represented by the other node as child here. + edges.push_back(edge); + } else { + // otherwise we start the appending process recursively on the child + // level. + // TODO: RuleSet merging + if (edge->getTarget()->getEdges().size() == 0) { + // if there are no more subsequent edges this is a leafe we could + // not merge, because it is already present in the Tree. + out.push_back(edge->getTarget()); + } else { + // otherwise we go into recursion. + for (auto &e : edge->getTarget()->getEdges()) { + std::vector<Rooted<SelectorNode>> childLeafs = + children[0]->append(e); + out.insert(out.end(), childLeafs.begin(), childLeafs.end()); + } + } + } + return out; +} } diff --git a/src/core/CSS.hpp b/src/core/CSS.hpp index f5d8c1d..c313f25 100644 --- a/src/core/CSS.hpp +++ b/src/core/CSS.hpp @@ -45,7 +45,8 @@ struct Specificity { Specificity(int b, int c, int d) : b(b), c(c), d(d) {} }; -//TODO: Is this correct? I used this to prevent "multiple definition" errors +// TODO: Is this inline usage correct? I used this to prevent "multiple +// definition" errors inline bool operator<(const Specificity &x, const Specificity &y) { return std::tie(x.b, x.c, x.d) < std::tie(y.b, y.c, y.d); @@ -254,6 +255,7 @@ public: : Node(mgr, std::move(name)), pseudoSelector(std::move(pseudoSelector)), edges(this) //, + // TODO: This is temporarily commented out until the TypeSystem works. // ruleSets(acquire(ruleSets)) { } @@ -262,6 +264,7 @@ public: ManagedVector<SelectorEdge> &getEdges() { return edges; } + // TODO: This is temporarily commented out until the TypeSystem works. // const std::vector<Owned<RuleSet>> &getRuleSets() const { return // ruleSets; } @@ -274,6 +277,45 @@ public: const std::string &className, const PseudoSelector &select); + /** + * This appends the given edge and the subsequent SelectorTree to + * this SelectorNode. Note that only those nodes get appended to the + * SelectorTree that are not already contained in this SelectorTree. + * + * Consider the example of the following SelectorTree T: + * + * root + * | \ + * A B + * | + * C + * + * and the following SelectorEdge e with its subsequent Tree T_e + * + * | + * A + * |\ + * C D + * + * If we call root.append(e) the resulting SelectorTree looks like + * this: + * + * root + * | \ + * A B + * |\ + * C D + * + * The method returns all leafs of T that are equivalent to leafs of T_e + * and thus could not be appended to T, because they were already contained + * there. In our example this would be a vector containing just C. + * + * @param edge a Rooted reference to an edge that shall be appended to this + * SelectorNode. + * @return A list of leafs of this SelectorTree that could not be appended, + * because they were already contained. + */ + std::vector<Rooted<SelectorNode>> append(Rooted<SelectorEdge> edge); }; } #endif |