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