| Index: compiled/ElemHideBase.cpp |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/compiled/ElemHideBase.cpp |
| @@ -0,0 +1,164 @@ |
| +#include "ElemHideBase.h" |
| +#include "ElemHideFilter.h" |
| +#include "ElemHideException.h" |
| +#include "CSSPropertyFilter.h" |
| +#include "InvalidFilter.h" |
| +#include "StringScanner.h" |
| + |
| +ElemHideBase::ElemHideBase(const String& text, |
| + String::size_type domainsEnd, String::size_type selectorStart) |
| + : ActiveFilter(text, false), |
| + mSelector(String(mText, selectorStart)) |
| +{ |
| + if (domainsEnd) |
| + ParseDomains(mText, 0, domainsEnd, u','); |
| +} |
| + |
| +Filter::Type ElemHideBase::Parse(const String& text, |
| + String::size_type* domainsEnd, |
| + String::size_type* selectorStart, |
| + String::size_type* prefixEnd, |
| + String::size_type* regexpStart, |
| + String::size_type* regexpEnd, |
| + String::size_type* suffixStart) |
| +{ |
| + StringScanner scanner(text); |
| + |
| + // Domains part |
| + while (!scanner.done()) |
| + { |
| + String::value_type next = scanner.next(); |
| + if (next == u'#') |
| + { |
| + *domainsEnd = scanner.position(); |
| + break; |
| + } |
| + |
| + switch (next) |
| + { |
| + case u'/': |
| + case u'*': |
| + case u'|': |
| + case u'@': |
| + case u'"': |
| + case u'!': |
| + return Type::UNKNOWN; |
| + } |
| + } |
| + |
| + bool exception = false; |
| + String::value_type next = scanner.next(); |
| + if (next == u'@') |
| + { |
| + exception = true; |
| + next = scanner.next(); |
| + } |
| + |
| + if (next != u'#') |
| + return Type::UNKNOWN; |
| + |
| + // Selector part |
| + |
| + // Selector shouldn't be empty |
| + if (scanner.done()) |
| + return Type::UNKNOWN; |
| + |
| + *selectorStart = scanner.position() + 1; |
| + while (!scanner.done()) |
| + { |
| + switch (scanner.next()) |
| + { |
| + case u'{': |
| + case u'}': |
| + return Type::UNKNOWN; |
| + } |
| + } |
| + |
| + if (exception) |
| + return Type::ELEMHIDEEXCEPTION; |
| + |
| + do |
| + { |
| + // Is this a CSS property rule maybe? |
| + if (!prefixEnd) |
| + { |
| + // Caller doesn't care |
| + break; |
| + } |
| + |
| + String searchString(u"[-abp-properties="_str); |
| + *prefixEnd = text.find(searchString, *selectorStart); |
| + if (*prefixEnd == text.npos || |
| + *prefixEnd + searchString.length() + 1 >= text.length()) |
| + { |
| + break; |
| + } |
| + |
| + *regexpStart = *prefixEnd + searchString.length() + 1; |
| + char16_t quotation = text[*regexpStart - 1]; |
| + if (quotation != u'\'' && quotation != u'"') |
| + break; |
| + |
| + *regexpEnd = text.find(quotation, *regexpStart); |
| + if (*regexpEnd == text.npos || *regexpEnd + 1 >= text.length() || |
| + text[*regexpEnd + 1] != u']') |
| + { |
| + break; |
| + } |
| + |
| + *suffixStart = *regexpEnd + 2; |
| + return Type::CSSPROPERTY; |
| + } while (false); |
| + |
| + return Type::ELEMHIDE; |
| +} |
| + |
| +Filter* ElemHideBase::Create(const String& text) |
| +{ |
| + size_t domainsEnd; |
| + size_t selectorStart; |
| + size_t prefixEnd; |
| + size_t regexpStart; |
| + size_t regexpEnd; |
| + size_t suffixStart; |
| + Type type = Parse(text, &domainsEnd, &selectorStart, &prefixEnd, ®expStart, |
| + ®expEnd, &suffixStart); |
| + if (type == Type::UNKNOWN) |
| + return nullptr; |
| + |
| + try |
| + { |
| + if (type == Type::ELEMHIDEEXCEPTION) |
| + return new ElemHideException(text, domainsEnd, selectorStart); |
| + else if (type == Type::CSSPROPERTY) |
| + { |
| + return new CSSPropertyFilter(text, domainsEnd, selectorStart, prefixEnd, |
| + regexpStart, regexpEnd, suffixStart); |
| + } |
| + else |
| + return new ElemHideFilter(text, domainsEnd, selectorStart); |
| + } |
| + catch (const String& e) |
| + { |
| + return new InvalidFilter(text, e); |
| + } |
| +} |
| + |
| +String ElemHideBase::GetSelectorDomain() const |
| +{ |
| + /* TODO this is inefficient */ |
| + String result; |
| + if (mDomains) |
| + { |
| + for (auto it = mDomains->begin(); it != mDomains->end(); ++it) |
| + { |
| + if (it->second && !it->first.empty()) |
| + { |
| + if (!result.empty()) |
| + result.append(u','); |
| + result.append(it->first); |
| + } |
| + } |
| + } |
| + return std::move(result.ensure_own_buffer()); |
| +} |