blob: 52bf86ddf10137b4720a31a0451148ef22c21211 [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_CSSOM_COMPOUND_SELECTOR_H_
#define COBALT_CSSOM_COMPOUND_SELECTOR_H_
#include <string>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "cobalt/cssom/selector.h"
#include "cobalt/cssom/simple_selector.h"
#include "cobalt/cssom/specificity.h"
namespace cobalt {
namespace cssom {
class Combinator;
class PseudoElement;
class SelectorVisitor;
// A compound selector is a chain of simple selectors that are not separated by
// a combinator.
// https://www.w3.org/TR/selectors4/#compound
class CompoundSelector : public Selector {
public:
typedef ScopedVector<SimpleSelector> SimpleSelectors;
CompoundSelector();
~CompoundSelector() OVERRIDE;
// From Selector.
void Accept(SelectorVisitor* visitor) OVERRIDE;
CompoundSelector* AsCompoundSelector() OVERRIDE { return this; }
Specificity GetSpecificity() const OVERRIDE { return specificity_; }
// Rest of public methods.
void AppendSelector(scoped_ptr<SimpleSelector> selector);
const SimpleSelectors& simple_selectors() { return simple_selectors_; }
PseudoElement* pseudo_element() {
if (has_pseudo_element_) {
for (SimpleSelectors::iterator iter = simple_selectors_.begin();
iter != simple_selectors_.end(); ++iter) {
if ((*iter)->AsPseudoElement()) {
return (*iter)->AsPseudoElement();
}
}
}
return NULL;
}
Combinator* left_combinator() { return left_combinator_; }
void set_left_combinator(Combinator* combinator) {
left_combinator_ = combinator;
}
Combinator* right_combinator() { return right_combinator_.get(); }
void set_right_combinator(scoped_ptr<Combinator> combinator);
bool requires_rule_matching_verification_visit() const {
return requires_rule_matching_verification_visit_;
}
bool operator<(const CompoundSelector& that) const {
if (simple_selectors_.size() < that.simple_selectors_.size()) {
return true;
}
if (simple_selectors_.size() > that.simple_selectors_.size()) {
return false;
}
for (size_t i = 0; i < simple_selectors_.size(); ++i) {
if (simple_selectors_[i]->type() < that.simple_selectors_[i]->type()) {
return true;
}
if (simple_selectors_[i]->type() > that.simple_selectors_[i]->type()) {
return false;
}
if (simple_selectors_[i]->prefix() <
that.simple_selectors_[i]->prefix()) {
return true;
}
if (simple_selectors_[i]->prefix() >
that.simple_selectors_[i]->prefix()) {
return false;
}
if (simple_selectors_[i]->text() < that.simple_selectors_[i]->text()) {
return true;
}
if (simple_selectors_[i]->text() > that.simple_selectors_[i]->text()) {
return false;
}
}
return false;
}
private:
Combinator* left_combinator_;
scoped_ptr<Combinator> right_combinator_;
SimpleSelectors simple_selectors_;
Specificity specificity_;
bool has_pseudo_element_;
// This flag tracks whether or not during rule matching, after the initial
// candidate gathering phase, the simple selectors require additional checks
// during the verification phase to determine a match; otherwise, the act of
// being gathered itself proves the match.
// There are two cases where the selectors require a visit:
// 1. There are multiple selectors. Gathering only tests against the first
// selector and the later selectors must also be verified to match.
// 2. The single selector's AlwaysRequiresRuleMatchingVerificationVisit() call
// returns true. This indicates that being gathered as a candidate is not
// sufficient to prove a match and that additional verification checks are
// required.
bool requires_rule_matching_verification_visit_;
DISALLOW_COPY_AND_ASSIGN(CompoundSelector);
};
} // namespace cssom
} // namespace cobalt
#endif // COBALT_CSSOM_COMPOUND_SELECTOR_H_