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: Back to manual approach for API Created Jan. 18, 2016, 12:41 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" 2 #include "CSSPropertyFilter.h"
3 #include "ElemHideException.h" 3 #include "StringScanner.h"
4 4
5 namespace 5 namespace
6 { 6 {
7 class Scanner 7 void NormalizeWhitespace(DependentString& text, String::size_type& domainsEnd,
8 String::size_type& selectorStart)
8 { 9 {
9 private: 10 // For element hiding filters we only want to remove spaces preceding the
10 const std::u16string& str; 11 // selector part. The positions we've determined already have to be adjusted
11 size_t pos; 12 // accordingly.
12 size_t end;
13 public:
14 Scanner(const std::u16string& str) : str(str), pos(0), end(str.length()) {}
15 13
16 bool done() 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++)
17 { 20 {
18 return pos >= end; 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];
19 } 29 }
30 selectorStart -= delta;
20 31
21 size_t position() 32 text.reset(text, 0, len - delta);
22 { 33 }
23 return pos - 1;
24 }
25
26 char16_t next()
27 {
28 return done() ? u'\0' : str[pos++];
29 }
30 };
31 } 34 }
32 35
33 ElemHideBase::ElemHideBase(const std::u16string& text, size_t domainsEnd, 36 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideBaseData & data)
34 size_t selectorStart) 37 : ActiveFilter(type, text, false), mData(data)
35 : ActiveFilter(text)
36 { 38 {
39 if (mData.HasDomains())
40 ParseDomains(mData.GetDomainsSource(mText), u',');
37 } 41 }
38 42
39 Filter::Type ElemHideBase::Parse(const std::u16string& text, size_t* domainsEnd, 43 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data)
40 size_t* selectorStart)
41 { 44 {
42 Scanner scanner(text); 45 StringScanner scanner(text);
43 46
44 // Domains part 47 // Domains part
45 loop: 48 bool seenSpaces = false;
46 while (!scanner.done()) 49 while (!scanner.done())
47 { 50 {
48 char16_t next = scanner.next(); 51 String::value_type next = scanner.next();
49 if (next == u'#') 52 if (next == u'#')
50 { 53 {
51 *domainsEnd = scanner.position(); 54 data.mDomainsEnd = scanner.position();
52 break; 55 break;
53 } 56 }
54 57
55 switch (next) 58 switch (next)
56 { 59 {
57 case u'/': 60 case u'/':
58 case u'*': 61 case u'*':
59 case u'|': 62 case u'|':
60 case u'@': 63 case u'@':
61 case u'"': 64 case u'"':
62 case u'!': 65 case u'!':
63 return Type::UNKNOWN; 66 return Type::UNKNOWN;
67 case u' ':
68 seenSpaces = true;
69 break;
64 } 70 }
65 } 71 }
66 72
67 bool exception = false; 73 seenSpaces |= scanner.skip(u' ');
68 char16_t next = scanner.next(); 74 bool exception = scanner.skipOne(u'@');
69 if (next == u'@') 75 if (exception)
70 { 76 seenSpaces |= scanner.skip(u' ');
71 exception = true;
72 next = scanner.next();
73 }
74 77
78 String::value_type next = scanner.next();
75 if (next != u'#') 79 if (next != u'#')
76 return Type::UNKNOWN; 80 return Type::UNKNOWN;
77 81
78 // Selector part 82 // Selector part
79 83
80 // Selector shouldn't be empty 84 // Selector shouldn't be empty
85 seenSpaces |= scanner.skip(u' ');
81 if (scanner.done()) 86 if (scanner.done())
82 return Type::UNKNOWN; 87 return Type::UNKNOWN;
83 88
84 *selectorStart = scanner.position() + 1; 89 data.mSelectorStart = scanner.position() + 1;
85 while (!scanner.done()) 90 while (!scanner.done())
86 { 91 {
87 switch (scanner.next()) 92 switch (scanner.next())
88 { 93 {
89 case u'{': 94 case u'{':
90 case u'}': 95 case u'}':
91 return Type::UNKNOWN; 96 return Type::UNKNOWN;
92 } 97 }
93 } 98 }
94 99
95 return exception ? Type::ELEMHIDEEXCEPTION : Type::ELEMHIDE; 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
105 if (exception)
106 return Type::ELEMHIDEEXCEPTION;
107
108 do
109 {
110 // Is this a CSS property rule maybe?
111 DependentString searchString(u"[-abp-properties="_str);
112 data.mPrefixEnd = text.find(searchString, data.mSelectorStart);
113 if (data.mPrefixEnd == text.npos ||
114 data.mPrefixEnd + searchString.length() + 1 >= text.length())
115 {
116 break;
117 }
118
119 data.mRegexpStart = data.mPrefixEnd + searchString.length() + 1;
120 char16_t quotation = text[data.mRegexpStart - 1];
121 if (quotation != u'\'' && quotation != u'"')
122 break;
123
124 data.mRegexpEnd = text.find(quotation, data.mRegexpStart);
125 if (data.mRegexpEnd == text.npos || data.mRegexpEnd + 1 >= text.length() ||
126 text[data.mRegexpEnd + 1] != u']')
127 {
128 break;
129 }
130
131 data.mSuffixStart = data.mRegexpEnd + 2;
132 return Type::CSSPROPERTY;
133 } while (false);
134
135 return Type::ELEMHIDE;
96 } 136 }
97 137
98 ElemHideBase* ElemHideBase::Create(const std::u16string& text) 138 OwnedString ElemHideBase::GetSelectorDomain() const
99 { 139 {
100 size_t domainsEnd; 140 /* TODO this is inefficient */
101 size_t selectorStart; 141 OwnedString result;
102 Type type = Parse(text, &domainsEnd, &selectorStart); 142 if (mDomains)
103 if (type == Type::UNKNOWN) 143 {
104 return nullptr; 144 for (auto it = mDomains->begin(); it != mDomains->end(); ++it)
105 else if (type == Type::ELEMHIDEEXCEPTION) 145 {
106 return new ElemHideException(text, domainsEnd, selectorStart); 146 if (it->second && !it->first.empty())
107 else 147 {
108 return new ElemHideFilter(text, domainsEnd, selectorStart); 148 if (!result.empty())
149 result.append(u',');
150 result.append(it->first);
151 }
152 }
153 }
154 return result;
109 } 155 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld