forked from LadybirdBrowser/ladybird
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBooleanExpression.cpp
More file actions
136 lines (118 loc) · 4.1 KB
/
Copy pathBooleanExpression.cpp
File metadata and controls
136 lines (118 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/StringBuilder.h>
#include <LibWeb/CSS/BooleanExpression.h>
namespace Web::CSS {
bool BooleanExpression::evaluate_to_boolean(DOM::Document const* document) const
{
return evaluate(document) == MatchResult::True;
}
void BooleanExpression::indent(StringBuilder& builder, int levels)
{
builder.append_repeated(" "sv, levels);
}
void GeneralEnclosed::dump(StringBuilder& builder, int indent_levels) const
{
indent(builder, indent_levels);
builder.appendff("GeneralEnclosed: {}\n", to_string());
}
MatchResult BooleanNotExpression::evaluate(DOM::Document const* document) const
{
// https://drafts.csswg.org/css-values-5/#boolean-logic
// `not test` evaluates to true if its contained test is false, false if it’s true, and unknown if it’s unknown.
switch (m_child->evaluate(document)) {
case MatchResult::False:
return MatchResult::True;
case MatchResult::True:
return MatchResult::False;
case MatchResult::Unknown:
return MatchResult::Unknown;
}
VERIFY_NOT_REACHED();
}
String BooleanNotExpression::to_string() const
{
return MUST(String::formatted("not {}", m_child->to_string()));
}
void BooleanNotExpression::dump(StringBuilder& builder, int indent_levels) const
{
indent(builder, indent_levels);
builder.append("NOT:\n"sv);
m_child->dump(builder, indent_levels + 1);
}
MatchResult BooleanExpressionInParens::evaluate(DOM::Document const* document) const
{
return m_child->evaluate(document);
}
String BooleanExpressionInParens::to_string() const
{
return MUST(String::formatted("({})", m_child->to_string()));
}
void BooleanExpressionInParens::dump(StringBuilder& builder, int indent_levels) const
{
indent(builder, indent_levels);
builder.append("(\n"sv);
m_child->dump(builder, indent_levels + 1);
indent(builder, indent_levels);
builder.append(")\n"sv);
}
MatchResult BooleanAndExpression::evaluate(DOM::Document const* document) const
{
// https://drafts.csswg.org/css-values-5/#boolean-logic
// Multiple tests connected with `and` evaluate to true if all of those tests are true, false if any of them are
// false, and unknown otherwise (i.e. if at least one unknown, but no false).
size_t true_results = 0;
for (auto const& child : m_children) {
auto child_match = child->evaluate(document);
if (child_match == MatchResult::False)
return MatchResult::False;
if (child_match == MatchResult::True)
true_results++;
}
if (true_results == m_children.size())
return MatchResult::True;
return MatchResult::Unknown;
}
String BooleanAndExpression::to_string() const
{
return MUST(String::join(" and "sv, m_children));
}
void BooleanAndExpression::dump(StringBuilder& builder, int indent_levels) const
{
indent(builder, indent_levels);
builder.append("AND:\n"sv);
for (auto const& child : m_children)
child->dump(builder, indent_levels + 1);
}
MatchResult BooleanOrExpression::evaluate(DOM::Document const* document) const
{
// https://drafts.csswg.org/css-values-5/#boolean-logic
// Multiple tests connected with `or` evaluate to true if any of those tests are true, false if all of them are
// false, and unknown otherwise (i.e. at least one unknown, but no true).
size_t false_results = 0;
for (auto const& child : m_children) {
auto child_match = child->evaluate(document);
if (child_match == MatchResult::True)
return MatchResult::True;
if (child_match == MatchResult::False)
false_results++;
}
if (false_results == m_children.size())
return MatchResult::False;
return MatchResult::Unknown;
}
String BooleanOrExpression::to_string() const
{
return MUST(String::join(" or "sv, m_children));
}
void BooleanOrExpression::dump(StringBuilder& builder, int indent_levels) const
{
indent(builder, indent_levels);
builder.append("OR:\n"sv);
for (auto const& child : m_children)
child->dump(builder, indent_levels + 1);
}
}