public void Parse(string ruleset) { int rlen = ruleset.Length; int lineCount = 0; for (int i = 0; i < ruleset.Length; i++) { if (ruleset[i] == '\n') { lineCount++; } } blackDomainList = new List <SubRange>(lineCount / 2); blackWildcardDomainList = new List <SubRange>(); blackRegexUrlList = new List <Regex>(); blackWildcardUrlList = new List <SubRange>(lineCount / 2); whiteDomainList = new List <SubRange>(); whiteWildcardDomainList = new List <SubRange>(); whiteRegexUrlList = new List <Regex>(); whiteWildcardUrlList = new List <SubRange>(); if (rlen > 1024) { resultCache = new Dictionary <string, bool>(32); resultCacheLock = new ReaderWriterLockSlim(); computingLocks = new Dictionary <string, ManualResetEvent>(); } var bssb = new StringBuilder(ruleset.Length); RulesCount = 0; int cur = 0; int lineNum = 0; while (cur < rlen) { var begin = cur; while (cur < rlen && ruleset[cur++] != '\n') { } var line = new SubString() { str = ruleset, Offset = begin, Length = cur - begin }; lineNum++; line.TrimSelf(); if (line.Length == 0) { continue; } var firstCh = line[0]; if (firstCh == '!' || firstCh == '#' || firstCh == '[') { continue; } RulesCount++; var ch0 = line.CharOrZero(0); var ch1 = line.CharOrZero(1); var ch2 = line.CharOrZero(2); var ch3 = line.CharOrZero(3); if (ch0 == '|') { if (ch1 == '|') // || { const int lineOffset = 2; var offset = bssb.Length; var len = line.Length - 2; if (line.Contains('*', 2)) { // add "*." + value bssb.Append("*."); line.AppendTo(bssb, lineOffset); blackWildcardDomainList.Add(new SubRange(offset, len + 2)); // and value without "*." blackWildcardDomainList.Add(new SubRange(offset + 2, len)); } else { line.AppendTo(bssb, lineOffset); blackDomainList.Add(new SubRange(offset, len)); } } else // | { var offset = bssb.Length; var len = line.Length - 1 + 1; //var wc = line.Substring(1) + "*"; line.AppendTo(bssb, 1); bssb.Append('*'); blackWildcardUrlList.Add(new SubRange(offset, len)); } } else if (ch0 == '@' & ch1 == '@') { if (ch2 == '|') { if (ch3 == '|') // @@|| { const int lineOffset = 4; var offset = bssb.Length; var len = line.Length - 4; if (line.Contains('*', 4)) { // add "*." + value bssb.Append("*."); line.AppendTo(bssb, lineOffset); whiteWildcardDomainList.Add(new SubRange(offset, len + 2)); // and value without "*." whiteWildcardDomainList.Add(new SubRange(offset + 2, len)); } else { line.AppendTo(bssb, lineOffset); whiteDomainList.Add(new SubRange(offset, len)); } } else // @@| { var offset = bssb.Length; var len = line.Length - 3 + 1; //var wc = line.Substring(3) + "*"; line.AppendTo(bssb, 3); bssb.Append('*'); whiteWildcardUrlList.Add(new SubRange(offset, len)); } } else // @@ { if (ch2.IsValidDomainCharacter() || ch2 == '*') { var offset = bssb.Length; var len = line.Length - 2 + 2; //var wc = "*" + line.Substring(2) + "*"; bssb.Append('*'); line.AppendTo(bssb, 2); bssb.Append('*'); whiteWildcardUrlList.Add(new SubRange(offset, len)); } else if (ch2 == '/') { var regex = Regex.Match(line.Get(), "/(.+)/"); if (regex.Success) { whiteRegexUrlList.Add(new Regex(regex.Groups[1].Value, RegexOptions.ECMAScript)); } } } } else if (ch0.IsValidDomainCharacter() || ch0 == '*') { //var wc = "*" + line + "*"; var offset = bssb.Length; var len = line.Length + 2; bssb.Append('*').Append(line).Append('*'); blackWildcardUrlList.Add(new SubRange(offset, len)); } else if (ch0 == '/') { var regex = Regex.Match(line.Get(), "/(.+)/"); if (regex.Success) { blackRegexUrlList.Add(new Regex(regex.Groups[1].Value, RegexOptions.ECMAScript)); } else { goto WRONG; } } else { goto WRONG; } continue; WRONG: RulesCount--; Logg?.warning($"unsupported/wrong ABP filter at line {lineNum}: {line.Get().Quoted()}"); } bigString = bssb.ToString(); blackDomainList.TrimExcess(); blackWildcardDomainList.TrimExcess(); blackRegexUrlList.TrimExcess(); blackWildcardUrlList.TrimExcess(); whiteDomainList.TrimExcess(); whiteWildcardDomainList.TrimExcess(); whiteRegexUrlList.TrimExcess(); whiteWildcardUrlList.TrimExcess(); }