Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: compiled/ElemHideBase.cpp

Issue 29333474: Issue 4125 - [emscripten] Convert filter classes to C++ (Closed)
Left Patch Set: How with CSS property filters Created Jan. 20, 2016, 1:12 p.m.
Right Patch Set: Addressed comments from Patch Set 28 Created March 21, 2017, 10:04 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/ElemHideBase.h ('k') | compiled/ElemHideException.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #include "ElemHideBase.h" 1 #include "ElemHideBase.h"
2 #include "ElemHideFilter.h"
3 #include "ElemHideException.h"
4 #include "CSSPropertyFilter.h" 2 #include "CSSPropertyFilter.h"
5 #include "InvalidFilter.h"
6 #include "StringScanner.h" 3 #include "StringScanner.h"
7 4
8 ElemHideBase::ElemHideBase(const std::u16string& text, 5 namespace
9 const std::u16string& domains, const std::u16string& selector)
10 : ActiveFilter(text, false), selector(selector)
11 { 6 {
12 if (!domains.empty()) 7 void NormalizeWhitespace(DependentString& text, String::size_type& domainsEnd,
13 ParseDomains(domains, u','); 8 String::size_type& selectorStart)
9 {
10 // For element hiding filters we only want to remove spaces preceding the
11 // selector part. The positions we've determined already have to be adjusted
12 // accordingly.
13
14 String::size_type delta = 0;
15 String::size_type len = text.length();
16
17 // The first character is guaranteed to be a non-space, the string has been
18 // trimmed earlier.
19 for (String::size_type pos = 1; pos < len; pos++)
20 {
21 if (pos == domainsEnd)
22 domainsEnd -= delta;
23
24 // Only spaces before selectorStart position should be removed.
25 if (pos < selectorStart && text[pos] == ' ')
26 delta++;
27 else
28 text[pos - delta] = text[pos];
29 }
30 selectorStart -= delta;
31
32 text.reset(text, 0, len - delta);
33 }
14 } 34 }
15 35
16 Filter::Type ElemHideBase::Parse(const std::u16string& text, size_t* domainsEnd, 36 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideBaseData & data)
17 size_t* selectorStart, size_t* prefixEnd, size_t* regexpStart, 37 : ActiveFilter(type, text, false), mData(data)
18 size_t* regexpEnd, size_t* suffixStart) 38 {
39 if (mData.HasDomains())
40 ParseDomains(mData.GetDomainsSource(mText), u',');
41 }
42
43 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data)
19 { 44 {
20 StringScanner scanner(text); 45 StringScanner scanner(text);
21 46
22 // Domains part 47 // Domains part
23 loop: 48 bool seenSpaces = false;
24 while (!scanner.done()) 49 while (!scanner.done())
25 { 50 {
26 char16_t next = scanner.next(); 51 String::value_type next = scanner.next();
27 if (next == u'#') 52 if (next == u'#')
28 { 53 {
29 *domainsEnd = scanner.position(); 54 data.mDomainsEnd = scanner.position();
30 break; 55 break;
31 } 56 }
32 57
33 switch (next) 58 switch (next)
34 { 59 {
35 case u'/': 60 case u'/':
36 case u'*': 61 case u'*':
37 case u'|': 62 case u'|':
38 case u'@': 63 case u'@':
39 case u'"': 64 case u'"':
40 case u'!': 65 case u'!':
41 return Type::UNKNOWN; 66 return Type::UNKNOWN;
67 case u' ':
68 seenSpaces = true;
69 break;
42 } 70 }
43 } 71 }
44 72
45 bool exception = false; 73 seenSpaces |= scanner.skip(u' ');
46 char16_t next = scanner.next(); 74 bool exception = scanner.skipOne(u'@');
47 if (next == u'@') 75 if (exception)
48 { 76 seenSpaces |= scanner.skip(u' ');
49 exception = true;
50 next = scanner.next();
51 }
52 77
78 String::value_type next = scanner.next();
53 if (next != u'#') 79 if (next != u'#')
54 return Type::UNKNOWN; 80 return Type::UNKNOWN;
55 81
56 // Selector part 82 // Selector part
57 83
58 // Selector shouldn't be empty 84 // Selector shouldn't be empty
85 seenSpaces |= scanner.skip(u' ');
59 if (scanner.done()) 86 if (scanner.done())
60 return Type::UNKNOWN; 87 return Type::UNKNOWN;
61 88
62 *selectorStart = scanner.position() + 1; 89 data.mSelectorStart = scanner.position() + 1;
63 while (!scanner.done()) 90 while (!scanner.done())
64 { 91 {
65 switch (scanner.next()) 92 switch (scanner.next())
66 { 93 {
67 case u'{': 94 case u'{':
68 case u'}': 95 case u'}':
69 return Type::UNKNOWN; 96 return Type::UNKNOWN;
70 } 97 }
71 } 98 }
72 99
100 // We are done validating, now we can normalize whitespace and the domain part
101 if (seenSpaces)
102 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart);
103 DependentString(text, 0, data.mDomainsEnd).toLower();
104
73 if (exception) 105 if (exception)
74 return Type::ELEMHIDEEXCEPTION; 106 return Type::ELEMHIDEEXCEPTION;
75 107
76 do 108 do
77 { 109 {
78 // Is this a CSS property rule maybe? 110 // Is this a CSS property rule maybe?
79 if (!prefixEnd) 111 DependentString searchString(u"[-abp-properties="_str);
80 { 112 data.mPrefixEnd = text.find(searchString, data.mSelectorStart);
81 // Caller doesn't care 113 if (data.mPrefixEnd == text.npos ||
82 break; 114 data.mPrefixEnd + searchString.length() + 1 >= text.length())
83 }
84
85 const std::u16string searchString(u"[-abp-properties=");
86 *prefixEnd = text.find(searchString, *selectorStart);
87 if (*prefixEnd == text.npos ||
88 *prefixEnd + searchString.length() + 1 >= text.length())
89 { 115 {
90 break; 116 break;
91 } 117 }
92 118
93 *regexpStart = *prefixEnd + searchString.length() + 1; 119 data.mRegexpStart = data.mPrefixEnd + searchString.length() + 1;
94 char16_t quotation = text[*regexpStart - 1]; 120 char16_t quotation = text[data.mRegexpStart - 1];
95 if (quotation != u'\'' && quotation != u'"') 121 if (quotation != u'\'' && quotation != u'"')
96 break; 122 break;
97 123
98 *regexpEnd = text.find(quotation, *regexpStart); 124 data.mRegexpEnd = text.find(quotation, data.mRegexpStart);
99 if (*regexpEnd == text.npos || *regexpEnd + 1 >= text.length() || 125 if (data.mRegexpEnd == text.npos || data.mRegexpEnd + 1 >= text.length() ||
100 text[*regexpEnd + 1] != u']') 126 text[data.mRegexpEnd + 1] != u']')
101 { 127 {
102 break; 128 break;
103 } 129 }
104 130
105 *suffixStart = *regexpEnd + 2; 131 data.mSuffixStart = data.mRegexpEnd + 2;
106 return Type::CSSPROPERTY; 132 return Type::CSSPROPERTY;
107 } while (false); 133 } while (false);
108 134
109 return Type::ELEMHIDE; 135 return Type::ELEMHIDE;
110 } 136 }
111 137
112 Filter* ElemHideBase::Create(const std::u16string& text) 138 OwnedString ElemHideBase::GetSelectorDomain() const
113 { 139 {
114 size_t domainsEnd; 140 /* TODO this is inefficient */
115 size_t selectorStart; 141 OwnedString result;
116 size_t prefixEnd; 142 if (mDomains)
117 size_t regexpStart;
118 size_t regexpEnd;
119 size_t suffixStart;
120 Type type = Parse(text, &domainsEnd, &selectorStart, &prefixEnd, &regexpStart,
121 &regexpEnd, &suffixStart);
122 if (type == Type::UNKNOWN)
123 return nullptr;
124
125 try
126 { 143 {
127 std::u16string domains(text.substr(0, domainsEnd)); 144 for (auto it = mDomains->begin(); it != mDomains->end(); ++it)
128 std::u16string selector(text.substr(selectorStart));
129 if (type == Type::ELEMHIDEEXCEPTION)
130 return new ElemHideException(text, domains, selector);
131 else if (type == Type::CSSPROPERTY)
132 { 145 {
133 std::u16string prefix(text.substr(selectorStart, prefixEnd - selectorStart )); 146 if (it->second && !it->first.empty())
134 std::u16string regexpSource(text.substr(regexpStart, regexpEnd - regexpSta rt)); 147 {
135 std::u16string suffix(text.substr(suffixStart)); 148 if (!result.empty())
136 return new CSSPropertyFilter(text, domains, selector, regexpSource, prefix , 149 result.append(u',');
137 suffix); 150 result.append(it->first);
138 } 151 }
139 else
140 return new ElemHideFilter(text, domains, selector);
141 }
142 catch (const std::u16string& e)
143 {
144 return new InvalidFilter(text, e);
145 }
146 }
147
148 const std::u16string ElemHideBase::GetSelectorDomain() const
149 {
150 std::u16string result;
151 for (auto it = domains.begin(); it != domains.end(); ++it)
152 {
153 if (it->second && !it->first.empty())
154 {
155 if (!result.empty())
156 result.append(u",");
157 result.append(it->first);
158 } 152 }
159 } 153 }
160 return result; 154 return result;
161 } 155 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld