diff --git a/src/css.cc b/src/css.cc index 351bb6f..aeeb224 100644 --- a/src/css.cc +++ b/src/css.cc @@ -15,6 +15,8 @@ #include "html_common.hh" #include "css.hh" +#include + using namespace dw::core::style; void CssProperty::print () { @@ -235,8 +237,6 @@ CssSimpleSelector::CssSimpleSelector () { } CssSimpleSelector::~CssSimpleSelector () { - for (int i = 0; i < klass.size (); i++) - dFree (klass.get (i)); dFree (id); dFree (pseudo); } @@ -244,8 +244,7 @@ CssSimpleSelector::~CssSimpleSelector () { void CssSimpleSelector::setSelect (SelectType t, const char *v) { switch (t) { case SELECT_CLASS: - klass.increase (); - klass.set (klass.size () - 1, dStrdup (v)); + klass.push_back(v); break; case SELECT_PSEUDO_CLASS: if (pseudo == NULL) @@ -275,9 +274,9 @@ bool CssSimpleSelector::match (const DoctreeNode *n) { return false; for (int i = 0; i < klass.size (); i++) { bool found = false; - if (n->klass != NULL) { - for (int j = 0; j < n->klass->size (); j++) { - if (dStrAsciiCasecmp (klass.get(i), n->klass->get(j)) == 0) { + if (n->klass.has_value()) { + for (int j = 0; j < n->klass.value().size (); j++) { + if (dStrAsciiCasecmp (klass.at(i).c_str(), n->klass.value().at(j).c_str()) == 0) { found = true; break; } @@ -314,14 +313,13 @@ void CssSimpleSelector::print () { element, pseudo, id); fprintf (stderr, "class "); for (int i = 0; i < klass.size (); i++) - fprintf (stderr, ".%s", klass.get (i)); + fprintf (stderr, ".%s", klass.at (i).c_str()); } -CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) { +CssRule::CssRule (std::shared_ptr< CssSelector > selector, CssPropertyList *props, int pos) { assert (selector->size () > 0); - this->selector = selector; - this->selector->ref (); + this->selector= selector; this->props = props; this->props->ref (); this->pos = pos; @@ -329,7 +327,6 @@ CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) { } CssRule::~CssRule () { - selector->unref (); props->unref (); } @@ -351,16 +348,13 @@ void CssRule::print () { * will be added behind the others. * This gives later added rules more weight. */ -void CssStyleSheet::RuleList::insert (CssRule *rule) { - increase (); - int i = size () - 1; +void +CssStyleSheet::RuleList::insert( std::shared_ptr< CssRule > rule ) +{ + auto where= std::upper_bound( begin( rules ), end( rules ), rule, + [&]( const auto &l, const auto &r ) { return l->specificity() < r->specificity(); } ); - while (i > 0 && rule->specificity () < get (i - 1)->specificity ()) { - *getRef (i) = get (i - 1); - i--; - } - - *getRef (i) = rule; + rules.insert( where, rule ); } /** @@ -369,42 +363,43 @@ void CssStyleSheet::RuleList::insert (CssRule *rule) { * To improve matching performance the rules are organized into * rule lists based on the topmost simple selector of their selector. */ -void CssStyleSheet::addRule (CssRule *rule) { +void CssStyleSheet::addRule (std::shared_ptr< CssRule > rule) { CssSimpleSelector *top = rule->selector->top (); - RuleList *ruleList = NULL; - lout::object::ConstString *string; + std::shared_ptr< RuleList > ruleList; + std::string string; if (top->getId ()) { - string = new lout::object::ConstString (top->getId ()); - ruleList = idTable.get (string); - if (ruleList == NULL) { - ruleList = new RuleList (); - idTable.put (string, ruleList); + string = top->getId (); + if (not idTable.contains(string)) { + ruleList= std::make_shared< RuleList > (); + idTable.emplace (string, ruleList); } else { - delete string; + ruleList= idTable.at(string); } - } else if (top->getClass () && top->getClass ()->size () > 0) { - string = new lout::object::ConstString (top->getClass ()->get (0)); - ruleList = classTable.get (string); - if (ruleList == NULL) { - ruleList = new RuleList; - classTable.put (string, ruleList); + assert( ruleList ); + } else if (top->getClass ().size () > 0) { + string = top->getClass ().at (0); + if (not classTable.contains(string)) { + ruleList = std::make_shared< RuleList >(); + classTable.emplace (string, ruleList); } else { - delete string; + ruleList= classTable.at(string); } + assert( ruleList ); } else if (top->getElement () >= 0 && top->getElement () < ntags) { - ruleList = &elementTable[top->getElement ()]; + ruleList = elementTable[top->getElement ()]; + assert( ruleList ); } else if (top->getElement () == CssSimpleSelector::ELEMENT_ANY) { - ruleList = &anyTable; + ruleList = anyTable; + assert( ruleList ); } if (ruleList) { - ruleList->insert (rule); + ruleList->insert( rule ); if (rule->selector->getRequiredMatchCache () > requiredMatchCache) requiredMatchCache = rule->selector->getRequiredMatchCache (); } else { assert (top->getElement () == CssSimpleSelector::ELEMENT_NONE); - delete rule; } } @@ -417,13 +412,11 @@ void CssStyleSheet::addRule (CssRule *rule) { void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree, const DoctreeNode *node, MatchCache *matchCache) const { static const int maxLists = 32; - const RuleList *ruleList[maxLists]; + std::array< std::shared_ptr< const RuleList >, maxLists > ruleList; int numLists = 0, index[maxLists] = {0}; if (node->id) { - lout::object::ConstString idString (node->id); - - ruleList[numLists] = idTable.get (&idString); + ruleList[numLists] = idTable.contains( node->id ) ? idTable.at (node->id) : nullptr; if (ruleList[numLists]) numLists++; } @@ -435,19 +428,19 @@ void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree, break; } - lout::object::ConstString classString (node->klass->get (i)); + const std::string classString= node->klass.value().at( i ); - ruleList[numLists] = classTable.get (&classString); + ruleList[numLists] = classTable.contains( classString ) ? classTable.at (classString) : nullptr; if (ruleList[numLists]) numLists++; } } - ruleList[numLists] = &elementTable[node->element]; + ruleList[numLists] = elementTable[node->element]; if (ruleList[numLists]) numLists++; - ruleList[numLists] = &anyTable; + ruleList[numLists] = anyTable; if (ruleList[numLists]) numLists++; @@ -461,21 +454,21 @@ void CssStyleSheet::apply (CssPropertyList *props, Doctree *docTree, int minSpecIndex = -1; for (int i = 0; i < numLists; i++) { - const RuleList *rl = ruleList[i]; + std::shared_ptr< const RuleList > rl = ruleList[i]; if (rl && rl->size () > index[i] && - (rl->get(index[i])->specificity () < minSpec || - (rl->get(index[i])->specificity () == minSpec && - rl->get(index[i])->position () < minPos))) { + (rl->at(index[i])->specificity () < minSpec || + (rl->at(index[i])->specificity () == minSpec && + rl->at(index[i])->position () < minPos))) { - minSpec = rl->get(index[i])->specificity (); - minPos = rl->get(index[i])->position (); + minSpec = rl->at(index[i])->specificity (); + minPos = rl->at(index[i])->position (); minSpecIndex = i; } } if (minSpecIndex >= 0) { - CssRule *rule = ruleList[minSpecIndex]->get (index[minSpecIndex]); + auto &rule = ruleList[minSpecIndex]->at (index[minSpecIndex]); rule->apply(props, docTree, node, matchCache); index[minSpecIndex]++; } else { @@ -526,26 +519,25 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree, sheet[CSS_PRIMARY_USER_IMPORTANT].apply (props, docTree, node, &matchCache); } -void CssContext::addRule (CssSelector *sel, CssPropertyList *props, +void CssContext::addRule (std::shared_ptr< CssSelector > sel, CssPropertyList *props, CssPrimaryOrder order) { if (props->size () > 0) { - CssRule *rule = new CssRule (sel, props, pos++); + auto rule = std::make_unique< CssRule >(sel, props, pos++); if ((order == CSS_PRIMARY_AUTHOR || order == CSS_PRIMARY_AUTHOR_IMPORTANT) && !rule->isSafe ()) { _MSG_WARN ("Ignoring unsafe author style that might reveal browsing history\n"); - delete rule; } else { rule->selector->setMatchCacheOffset(matchCache.size ()); if (rule->selector->getRequiredMatchCache () > matchCache.size ()) matchCache.setSize (rule->selector->getRequiredMatchCache (), -1); if (order == CSS_PRIMARY_USER_AGENT) { - userAgentSheet.addRule (rule); + userAgentSheet.addRule (std::move(rule)); } else { - sheet[order].addRule (rule); + sheet[order].addRule (std::move(rule)); } } } diff --git a/src/css.hh b/src/css.hh index 01c1ca9..418ea92 100644 --- a/src/css.hh +++ b/src/css.hh @@ -13,10 +13,18 @@ #ifndef __CSS_HH__ #define __CSS_HH__ +#include +#include +#include +#include +#include + #include "dw/core.hh" #include "doctree.hh" #include "html.hh" +#include + /* Origin and weight. Used only internally.*/ typedef enum { CSS_PRIMARY_USER_AGENT, @@ -356,7 +364,7 @@ class CssSimpleSelector { private: int element; char *pseudo, *id; - lout::misc::SimpleVector klass; + std::vector< std::string > klass; public: enum { @@ -375,7 +383,7 @@ class CssSimpleSelector { ~CssSimpleSelector (); inline void setElement (int e) { element = e; }; void setSelect (SelectType t, const char *v); - inline lout::misc::SimpleVector *getClass () { return &klass; }; + inline std::vector< std::string > &getClass () { return klass; }; inline const char *getPseudoClass () { return pseudo; }; inline const char *getId () { return id; }; inline int getElement () { return element; }; @@ -438,8 +446,6 @@ class CssSelector { int specificity (); bool checksPseudoClass (); void print (); - inline void ref () { refCount++; } - inline void unref () { if (--refCount == 0) delete this; } }; /** @@ -453,9 +459,9 @@ class CssRule { int spec, pos; public: - CssSelector *selector; + std::shared_ptr< CssSelector > selector; - CssRule (CssSelector *selector, CssPropertyList *props, int pos); + CssRule (std::shared_ptr< CssSelector > selector, CssPropertyList *props, int pos); ~CssRule (); void apply (CssPropertyList *props, Doctree *docTree, @@ -475,20 +481,19 @@ class CssRule { */ class CssStyleSheet { private: - class RuleList : public lout::misc::SimpleVector , - public lout::object::Object { - public: - RuleList () : lout::misc::SimpleVector (1) {}; - ~RuleList () { - for (int i = 0; i < size (); i++) - delete get (i); - }; + class RuleList + { + private: + std::vector< std::shared_ptr< CssRule > > rules; - void insert (CssRule *rule); - inline bool equals (lout::object::Object *other) { - return this == other; - }; - inline int hashValue () { return (intptr_t) this; }; + public: + void insert( std::shared_ptr< CssRule > rule ); + + constexpr std::size_t size() const noexcept { return rules.size(); } + constexpr bool empty() const noexcept { return rules.empty(); } + + template< typename Self > + auto &&at( this Self &&self, const std::size_t index ) { return self.rules.at( index ); } }; class RuleMap : public lout::container::typed::HashTable @@ -500,13 +505,21 @@ class CssStyleSheet { static const int ntags = HTML_NTAGS; - RuleList elementTable[ntags], anyTable; - RuleMap idTable, classTable; + using ElementTable= std::array< std::shared_ptr< RuleList >, ntags >; + ElementTable elementTable= Alepha::Utility::evaluate <=[] + { + ElementTable rv; + std::generate( begin( rv ), end( rv ), &std::make_unique< RuleList > ); + return rv; + }; + std::shared_ptr< RuleList > anyTable= std::make_unique< RuleList >(); + std::map< std::string, std::shared_ptr< RuleList > > idTable; + std::map< std::string, std::shared_ptr< RuleList > > classTable; int requiredMatchCache; public: CssStyleSheet () { requiredMatchCache = 0; } - void addRule (CssRule *rule); + void addRule (std::shared_ptr< CssRule > rule); void apply (CssPropertyList *props, Doctree *docTree, const DoctreeNode *node, MatchCache *matchCache) const; int getRequiredMatchCache () { return requiredMatchCache; } @@ -525,7 +538,7 @@ class CssContext { public: CssContext (); - void addRule (CssSelector *sel, CssPropertyList *props, + void addRule (std::shared_ptr< CssSelector > sel, CssPropertyList *props, CssPrimaryOrder order); void apply (CssPropertyList *props, Doctree *docTree, DoctreeNode *node, diff --git a/src/cssparser.cc b/src/cssparser.cc index e63d85b..465d56b 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1476,14 +1476,13 @@ bool CssParser::parseSimpleSelector(CssSimpleSelector *selector) return true; } -CssSelector *CssParser::parseSelector() +std::unique_ptr< CssSelector > CssParser::parseSelector() { - CssSelector *selector = new CssSelector (); + auto selector = std::make_unique< CssSelector >(); while (true) { if (! parseSimpleSelector (selector->top ())) { - delete selector; - selector = NULL; + selector = nullptr; break; } @@ -1499,8 +1498,7 @@ CssSelector *CssParser::parseSelector() } else if (ttype != CSS_TK_END && spaceSeparated) { selector->addSimpleSelector (CssSelector::COMB_DESCENDANT); } else { - delete selector; - selector = NULL; + selector = nullptr; break; } } @@ -1515,17 +1513,15 @@ CssSelector *CssParser::parseSelector() void CssParser::parseRuleset() { - std::vector < CssSelector * > list; + std::vector < std::shared_ptr< CssSelector > > list; CssPropertyList *props, *importantProps; - CssSelector *selector; while (true) { - selector = parseSelector(); + auto selector= parseSelector(); if (selector) { - selector->ref(); - list.push_back(selector); + list.push_back(std::move( selector )); } // \todo dump whole ruleset in case of parse error as required by CSS 2.1 @@ -1559,7 +1555,7 @@ void CssParser::parseRuleset() } for (std::size_t i = 0; i < list.size(); i++) { - CssSelector *s = list.at(i); + const auto &s = list.at(i); if (origin == CSS_ORIGIN_USER_AGENT) { context->addRule(s, props, CSS_PRIMARY_USER_AGENT); @@ -1570,8 +1566,6 @@ void CssParser::parseRuleset() context->addRule(s, props, CSS_PRIMARY_AUTHOR); context->addRule(s, importantProps, CSS_PRIMARY_AUTHOR_IMPORTANT); } - - s->unref(); } props->unref(); diff --git a/src/cssparser.hh b/src/cssparser.hh index 5f0f21a..3c549e5 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -43,7 +43,7 @@ class CssParser { char *parseUrl(); void parseImport(DilloHtml *html); void parseMedia(); - CssSelector *parseSelector(); + std::unique_ptr< CssSelector > parseSelector(); void parseRuleset(); void ignoreBlock(); void ignoreStatement(); diff --git a/src/doctree.hh b/src/doctree.hh index 52c1c42..bf31d10 100644 --- a/src/doctree.hh +++ b/src/doctree.hh @@ -3,6 +3,9 @@ #include "lout/misc.hh" +#include +#include + class DoctreeNode { public: DoctreeNode *parent; @@ -10,7 +13,7 @@ class DoctreeNode { DoctreeNode *lastChild; int num; // unique ascending id int element; - lout::misc::SimpleVector *klass; + std::optional< std::vector< std::string > > klass; const char *pseudo; const char *id; @@ -18,7 +21,6 @@ class DoctreeNode { parent = NULL; sibling = NULL; lastChild = NULL; - klass = NULL; pseudo = NULL; id = NULL; element = 0; @@ -31,11 +33,6 @@ class DoctreeNode { lastChild = lastChild->sibling; delete n; } - if (klass) { - for (int i = 0; i < klass->size (); i++) - dFree (klass->get(i)); - delete klass; - } } }; diff --git a/src/styleengine.cc b/src/styleengine.cc index 634016a..2a9b02c 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -165,18 +165,16 @@ void StyleEngine::setId (const char *id) { /** * \brief split a string at sep chars and return a SimpleVector of strings */ -static lout::misc::SimpleVector *splitStr (const char *str, char sep) { +static std::vector< std::string > splitStr (const char *str, char sep) { const char *p1 = NULL; - lout::misc::SimpleVector *list = - new lout::misc::SimpleVector (1); + std::vector< std::string > list; for (;; str++) { if (*str != '\0' && *str != sep) { if (!p1) p1 = str; } else if (p1) { - list->increase (); - list->set (list->size () - 1, dStrndup (p1, str - p1)); + list.emplace_back( p1, str - p1 ); p1 = NULL; } @@ -189,7 +187,7 @@ static lout::misc::SimpleVector *splitStr (const char *str, char sep) { void StyleEngine::setClass (const char *klass) { DoctreeNode *dn = doctree->top (); - assert (dn->klass == NULL); + assert (not dn->klass.has_value()); dn->klass = splitStr (klass, ' '); }