blob: 2c461b8d6b190b7ad474116adacc3500de87e256 [file] [log] [blame]
/*
* Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/core/css/css_selector_list.h"
#include <memory>
#include "third_party/blink/renderer/core/css/css_selector.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
CSSSelectorList* CSSSelectorList::Empty() {
CSSSelectorList* list =
MakeGarbageCollected<CSSSelectorList>(base::PassKey<CSSSelectorList>());
new (list->first_selector_) CSSSelector();
list->first_selector_[0].SetMatch(CSSSelector::kInvalidList);
DCHECK(!list->IsValid());
return list;
}
CSSSelectorList* CSSSelectorList::Copy() const {
if (!IsValid()) {
return CSSSelectorList::Empty();
}
unsigned length = ComputeLength();
DCHECK(length);
CSSSelectorList* list = MakeGarbageCollected<CSSSelectorList>(
AdditionalBytes(sizeof(CSSSelector) * (length - 1)),
base::PassKey<CSSSelectorList>());
for (unsigned i = 0; i < length; ++i) {
new (&list->first_selector_[i]) CSSSelector(first_selector_[i]);
}
return list;
}
void CSSSelectorList::AdoptSelectorVector(
base::span<CSSSelector> selector_vector,
CSSSelector* selector_array) {
std::uninitialized_move(selector_vector.begin(), selector_vector.end(),
selector_array);
selector_array[selector_vector.size() - 1].SetLastInSelectorList(true);
}
CSSSelectorList* CSSSelectorList::AdoptSelectorVector(
base::span<CSSSelector> selector_vector) {
if (selector_vector.empty()) {
return CSSSelectorList::Empty();
}
CSSSelectorList* list = MakeGarbageCollected<CSSSelectorList>(
AdditionalBytes(sizeof(CSSSelector) * (selector_vector.size() - 1)),
base::PassKey<CSSSelectorList>());
AdoptSelectorVector(selector_vector, list->first_selector_);
return list;
}
unsigned CSSSelectorList::ComputeLength() const {
if (!IsValid()) {
return 0;
}
const CSSSelector* current = First();
while (!current->IsLastInSelectorList()) {
++current;
}
return SelectorIndex(*current) + 1;
}
unsigned CSSSelectorList::MaximumSpecificity() const {
unsigned specificity = 0;
for (const CSSSelector* s = First(); s; s = Next(*s)) {
specificity = std::max(specificity, s->Specificity());
}
return specificity;
}
void CSSSelectorList::Reparent(CSSSelector* selector_list,
StyleRule* old_parent,
StyleRule* new_parent) {
DCHECK(selector_list);
CSSSelector* current = selector_list;
do {
current->Reparent(old_parent, new_parent);
} while (!(current++)->IsLastInSelectorList());
}
String CSSSelectorList::SelectorsText(const CSSSelector* first) {
StringBuilder result;
for (const CSSSelector* s = first; s; s = Next(*s)) {
if (s != first) {
result.Append(", ");
}
result.Append(s->SelectorText());
}
return result.ReleaseString();
}
void CSSSelectorList::Trace(Visitor* visitor) const {
if (!IsValid()) {
return;
}
for (int i = 0;; ++i) {
visitor->Trace(first_selector_[i]);
if (first_selector_[i].IsLastInSelectorList()) {
break;
}
}
}
} // namespace blink