lUInt32 LVCssSelector::getHash() { lUInt32 hash = 0; lUInt32 nextHash = 0; if (_next) nextHash = _next->getHash(); for (LVCssSelectorRule * p = _rules; p; p = p->getNext()) { lUInt32 ruleHash = p->getHash(); hash = hash * 31 + ruleHash; } hash = hash * 31 + nextHash; if (!_decl.isNull()) hash = hash * 31 + _decl->getHash(); return hash; }
bool LVCssSelector::check( const ldomNode * node ) const { // check main Id if (_id!=0 && node->getNodeId() != _id) return false; if (!_rules) return true; // check additional rules const ldomNode * n = node; LVCssSelectorRule * rule = _rules; do { if ( !rule->check(n) ) return false; rule = rule->getNext(); } while (rule!=NULL); return true; }
bool LVCssSelector::parse( const char * &str, lxmlDocBase * doc ) { if (!str || !*str) return false; for (;;) { skip_spaces( str ); if ( *str == '*' ) // universal selector { str++; skip_spaces( str ); _id = 0; } else if ( *str == '.' ) // classname follows { _id = 0; } else if ( css_is_alpha( *str ) ) { // ident char ident[64]; if (!parse_ident( str, ident )) return false; _id = doc->getElementNameIndex( lString16(ident).c_str() ); skip_spaces( str ); } else { return false; } if ( *str == ',' || *str == '{' ) return true; // one or more attribute rules bool attr_rule = false; while ( *str == '[' || *str=='.' || *str=='#' ) { LVCssSelectorRule * rule = parse_attr( str, doc ); if (!rule) return false; insertRuleStart( rule ); //insertRuleAfterStart //insertRuleAfterStart( rule ); //insertRuleAfterStart /* if ( _id!=0 ) { LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_parent); rule->setId(_id); insertRuleStart( rule ); _id=0; } */ skip_spaces( str ); attr_rule = true; //continue; } // element relation if (*str == '>') { str++; LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_parent); rule->setId(_id); insertRuleStart( rule ); _id=0; continue; } else if (*str == '+') { str++; LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_predecessor); rule->setId(_id); insertRuleStart( rule ); _id=0; continue; } else if (css_is_alpha( *str )) { LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_ancessor); rule->setId(_id); insertRuleStart( rule ); _id=0; continue; } if ( !attr_rule ) return false; else if ( *str == ',' || *str == '{' ) return true; } }
LVCssSelectorRule * parse_attr( const char * &str, lxmlDocBase * doc ) { char attrname[512]; char attrvalue[512]; LVCssSelectorRuleType st = cssrt_universal; if (*str=='.') { // E.class str++; skip_spaces( str ); if (!parse_ident( str, attrvalue )) return NULL; skip_spaces( str ); LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_class); lString16 s( attrvalue ); s.lowercase(); rule->setAttr(attr_class, s); return rule; } else if ( *str=='#' ) { // E#id str++; skip_spaces( str ); if (!parse_ident( str, attrvalue )) return NULL; skip_spaces( str ); LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_id); lString16 s( attrvalue ); rule->setAttr(attr_id, s); return rule; } else if (*str != '[') return NULL; str++; skip_spaces( str ); if (!parse_ident( str, attrname )) return NULL; skip_spaces( str ); attrvalue[0] = 0; if (*str==']') { st = cssrt_attrset; str++; } else if (*str=='=') { str++; if (!parse_attr_value( str, attrvalue)) return NULL; st = cssrt_attreq; } else if (*str=='~' && str[1]=='=') { str+=2; if (!parse_attr_value( str, attrvalue)) return NULL; st = cssrt_attrhas; } else if (*str=='|' && str[1]=='=') { str+=2; if (!parse_attr_value( str, attrvalue)) return NULL; st = cssrt_attrstarts; } else { return NULL; } LVCssSelectorRule * rule = new LVCssSelectorRule(st); lString16 s( attrvalue ); lUInt16 id = doc->getAttrNameIndex( lString16(attrname).c_str() ); rule->setAttr(id, s); return rule; }