1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ShadowParts.h"
8 #include "nsContentUtils.h"
13 static bool IsSpace(char16_t aChar
) {
14 return nsContentUtils::IsHTMLWhitespace(aChar
);
17 using SingleMapping
= std::pair
<RefPtr
<nsAtom
>, RefPtr
<nsAtom
>>;
19 // https://drafts.csswg.org/css-shadow-parts/#parsing-mapping
21 // Returns null on both tokens to signal an error.
22 static SingleMapping
ParseSingleMapping(const nsAString
& aString
) {
23 const char16_t
* c
= aString
.BeginReading();
24 const char16_t
* end
= aString
.EndReading();
26 const auto CollectASequenceOfSpaces
= [&c
, end
]() {
27 while (c
!= end
&& IsSpace(*c
)) {
32 const auto CollectToken
= [&c
, end
]() -> RefPtr
<nsAtom
> {
33 const char16_t
* t
= c
;
34 while (c
!= end
&& !IsSpace(*c
) && *c
!= ':') {
40 return NS_AtomizeMainThread(Substring(t
, c
));
43 // Steps 1 and 2 are variable declarations.
45 // 3. Collect a sequence of code points that are space characters.
46 CollectASequenceOfSpaces();
48 // 4. Collect a sequence of code points that are not space characters or
49 // U+003A COLON characters, and call the result first token.
50 RefPtr
<nsAtom
> firstToken
= CollectToken();
52 // 5. If first token is empty then return error.
54 return {nullptr, nullptr};
57 // 6. Collect a sequence of code points that are space characters.
58 CollectASequenceOfSpaces();
60 // 7. If the end of the input has been reached, return the pair first
63 return {firstToken
, firstToken
};
66 // 8. If character at position is not a U+003A COLON character, return error.
68 return {nullptr, nullptr};
71 // 9. Consume the U+003A COLON character.
74 // 10. Collect a sequence of code points that are space characters.
75 CollectASequenceOfSpaces();
77 // 11. Collect a sequence of code points that are not space characters or
78 // U+003A COLON characters. and let second token be the result.
79 RefPtr
<nsAtom
> secondToken
= CollectToken();
81 // 12. If second token is empty then return error.
83 return {nullptr, nullptr};
86 // 13. Collect a sequence of code points that are space characters.
87 CollectASequenceOfSpaces();
89 // 14. If position is not past the end of input then return error.
91 return {nullptr, nullptr};
94 // 15. Return the pair first token/second token.
95 return {std::move(firstToken
), std::move(secondToken
)};
98 // https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
99 ShadowParts
ShadowParts::Parse(const nsAString
& aString
) {
102 for (const auto& substring
: aString
.Split(',')) {
103 auto mapping
= ParseSingleMapping(substring
);
104 if (!mapping
.first
) {
105 MOZ_ASSERT(!mapping
.second
);
108 nsAtom
* second
= mapping
.second
.get();
109 parts
.mMappings
.LookupForAdd(mapping
.first
)
110 .OrInsert([] { return new PartList(); })
111 ->AppendElement(std::move(mapping
.second
));
112 parts
.mReverseMappings
.GetOrInsert(second
) = std::move(mapping
.first
);
119 void ShadowParts::Dump() const {
120 if (mMappings
.IsEmpty()) {
121 printf(" (empty)\n");
124 for (auto& entry
: mMappings
) {
126 entry
.GetKey()->ToUTF8String(key
);
127 printf(" %s: ", key
.get());
130 for (nsAtom
* part
: *entry
.GetData()) {
136 part
->ToUTF8String(value
);
137 printf("%s", value
.get());
143 } // namespace mozilla