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

Powered by Google App Engine
This is Rietveld