Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
3 * Copyright (C) 2006-present eyeo GmbH | |
4 * | |
5 * Adblock Plus is free software: you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 3 as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | |
16 */ | |
17 | |
18 #include "Parser.h" | |
19 #include "../subscription/DownloadableSubscription.h" | |
20 #include "../subscription/UserDefinedSubscription.h" | |
21 #include "../filter/Filter.h" | |
22 | |
23 namespace | |
24 { | |
25 bool IsSection(const String& value, const String& expectedSectionName) | |
26 { | |
27 auto valueLength = value.length(); | |
28 // fast check whether it's a section and if its length is expected | |
29 if (!(valueLength == expectedSectionName.length() + 2 && value[0] == u'[' && value[valueLength - 1] == u']')) | |
30 return false; | |
31 OwnedString sectionName(DependentString(value, 1, valueLength - 2)); | |
32 sectionName.toLower(); | |
33 return sectionName == expectedSectionName; | |
34 } | |
35 | |
36 bool IsSubscriptionSection(const String& value) | |
37 { | |
38 return IsSection(value, u"subscription"_str); | |
39 } | |
40 | |
41 bool IsSubscriptionFiltersSection(const String& value) | |
42 { | |
43 return ::IsSection(value, u"subscription filters"_str); | |
Wladimir Palant
2017/12/21 10:30:37
Does :: make sense here? You don't use it above.
| |
44 } | |
45 | |
46 Subscription::KeyValue CreateKeyValue(const std::pair<DependentString, Depende ntString>& pair) | |
47 { | |
48 Subscription::KeyValue retValue; | |
49 retValue.first = TrimSpaces(pair.first); | |
50 retValue.second = TrimSpaces(pair.second); | |
51 return retValue; | |
52 } | |
53 | |
54 void DecodeOpeningBracket(DependentString& value) | |
55 { | |
56 String::size_type skippedChars = 0; | |
57 for (String::size_type i = 1; i < value.length(); ++i) | |
58 { | |
59 if (value[i - 1] == u'\\' && value[i] == u'[') | |
60 ++skippedChars; | |
61 value[i - skippedChars] = value[i]; | |
62 } | |
63 if (skippedChars > 0) | |
64 value.reset(value, 0, value.length() - skippedChars); | |
65 } | |
66 } | |
67 | |
68 Parser::Parser() | |
69 : mCurrentState{State::Initial} | |
70 { | |
71 } | |
72 | |
73 void Parser::Process(const String& untrimmedLine) | |
74 { | |
75 auto line = TrimSpaces(untrimmedLine); | |
76 // skip empty lines | |
77 if (line.length() == 0) | |
78 return; | |
79 | |
80 if (IsSubscriptionSection(line)) | |
81 { | |
82 Finalize(); | |
83 mCurrentState = State::SubscriptionSection; | |
84 return; | |
85 } | |
86 | |
87 switch (mCurrentState) | |
88 { | |
89 case State::Initial: | |
90 Initial_processLine(line); | |
91 break; | |
92 case State::SubscriptionSection: | |
93 SubscriptionSection_processLine(line); | |
94 break; | |
95 case State::SubscriptionFiltersSection: | |
96 SubscriptionFiltersSection_processLine(line); | |
97 break; | |
98 default: | |
99 ; | |
100 } | |
101 } | |
102 | |
103 void Parser::Finalize() | |
104 { | |
105 switch (mCurrentState) | |
106 { | |
107 case State::Initial: | |
108 // don't clear file properties because they are also the parser member | |
109 break; | |
110 case State::SubscriptionSection: | |
111 onSubscription(createSubscriptionFromProperties()); | |
112 mSubscriptionProperties.clear(); | |
113 break; | |
114 case State::SubscriptionFiltersSection: | |
115 onSubscription(std::move(mSubscription)); | |
116 break; | |
117 default: | |
118 ; | |
119 } | |
120 } | |
121 | |
122 Parser::Subscriptions::size_type Parser::GetSubscriptionCount() const | |
123 { | |
124 return mSubscriptions.size(); | |
125 } | |
126 | |
127 Subscription* Parser::SubscriptionAt(Subscriptions::size_type index) | |
128 { | |
129 if (index >= mSubscriptions.size()) | |
130 return nullptr; | |
131 return SubscriptionPtr(mSubscriptions[index]).release(); | |
132 } | |
133 | |
134 SubscriptionPtr Parser::createSubscriptionFromProperties() const | |
135 { | |
136 return Subscription::FromProperties(mSubscriptionProperties); | |
137 } | |
138 | |
139 void Parser::Initial_processLine(const String& line) | |
140 { | |
141 // skip # Adblock Plus preferences | |
142 if (line[0] == u'#') | |
143 return; | |
144 | |
145 String::size_type assignSignPos = line.find(u'='); | |
146 if (assignSignPos != String::npos) | |
147 { | |
148 mFileProperties.emplace_back(CreateKeyValue(SplitString(line, assignSignPos) )); | |
149 return; | |
150 } | |
151 onFail("Unexpected line value, it should be either a file property or the [Sub scription] section"); | |
152 } | |
153 | |
154 void Parser::SubscriptionSection_processLine(const String& line) | |
155 { | |
156 String::size_type assignSignPos = line.find(u'='); | |
157 if (assignSignPos != String::npos) | |
158 { | |
159 mSubscriptionProperties.emplace_back(CreateKeyValue(SplitString(line, assign SignPos))); | |
160 return; | |
161 } | |
162 if (IsSubscriptionFiltersSection(line)) | |
163 { | |
164 mSubscription = createSubscriptionFromProperties(); | |
165 mCurrentState = State::SubscriptionFiltersSection; | |
166 return; | |
167 } | |
168 onFail("Unexpected line value, it should be either a subscription property, th e [Subscription filters] section or the [Subscription] section"); | |
169 } | |
170 | |
171 void Parser::SubscriptionFiltersSection_processLine(const String& line) | |
172 { | |
173 OwnedString lineCopy{line}; | |
Wladimir Palant
2017/12/21 10:30:37
I assume that you create a copy so that DecodeOpen
| |
174 DependentString lineForFilter{lineCopy}; | |
175 DecodeOpeningBracket(lineForFilter); | |
Wladimir Palant
2017/12/21 10:30:37
Copying all data around unconditionally seems wast
| |
176 mSubscription->AddFilter(*FilterPtr(Filter::FromText(lineForFilter))); | |
177 // any line is considered as a filter, there can be no error | |
178 } | |
179 | |
180 void Parser::onSubscription(SubscriptionPtr subscription) | |
181 { | |
182 mSubscriptions.emplace_back(std::move(subscription)); | |
183 } | |
OLD | NEW |