| Index: compiled/ElemHideBase.cpp | 
| =================================================================== | 
| new file mode 100644 | 
| --- /dev/null | 
| +++ b/compiled/ElemHideBase.cpp | 
| @@ -0,0 +1,109 @@ | 
| +#include "ElemHideBase.h" | 
| +#include "ElemHideFilter.h" | 
| +#include "ElemHideException.h" | 
| + | 
| +namespace | 
| +{ | 
| +  class Scanner | 
| +  { | 
| +  private: | 
| +    const std::u16string& str; | 
| +    size_t pos; | 
| +    size_t end; | 
| +  public: | 
| +    Scanner(const std::u16string& str) : str(str), pos(0), end(str.length()) {} | 
| + | 
| +    bool done() | 
| +    { | 
| +      return pos >= end; | 
| +    } | 
| + | 
| +    size_t position() | 
| +    { | 
| +      return pos - 1; | 
| +    } | 
| + | 
| +    char16_t next() | 
| +    { | 
| +      return done() ? u'\0' : str[pos++]; | 
| +    } | 
| +  }; | 
| +} | 
| + | 
| +ElemHideBase::ElemHideBase(const std::u16string& text, size_t domainsEnd, | 
| +    size_t selectorStart) | 
| +    : ActiveFilter(text) | 
| +{ | 
| +} | 
| + | 
| +Filter::Type ElemHideBase::Parse(const std::u16string& text, size_t* domainsEnd, | 
| +    size_t* selectorStart) | 
| +{ | 
| +  Scanner scanner(text); | 
| + | 
| +  // Domains part | 
| +  loop: | 
| +  while (!scanner.done()) | 
| +  { | 
| +    char16_t 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; | 
| +  char16_t 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; | 
| +    } | 
| +  } | 
| + | 
| +  return exception ? Type::ELEMHIDEEXCEPTION : Type::ELEMHIDE; | 
| +} | 
| + | 
| +ElemHideBase* ElemHideBase::Create(const std::u16string& text) | 
| +{ | 
| +  size_t domainsEnd; | 
| +  size_t selectorStart; | 
| +  Type type = Parse(text, &domainsEnd, &selectorStart); | 
| +  if (type == Type::UNKNOWN) | 
| +    return nullptr; | 
| +  else if (type == Type::ELEMHIDEEXCEPTION) | 
| +    return new ElemHideException(text, domainsEnd, selectorStart); | 
| +  else | 
| +    return new ElemHideFilter(text, domainsEnd, selectorStart); | 
| +} | 
|  |