Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/plugin/TokenSequence.h

Issue 29331055: Issue #1234 - Remove 'CString' from PluginFilter.* (Closed)
Patch Set: rebase Created Jan. 5, 2016, 4:07 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 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 template<class T> class TokenSequenceConstIterator; // forward declaration
19
20 /**
21 * A sequence of delimited tokens contained within a given string.
22 */
23 template<class T>
24 class TokenSequence
25 {
26 typedef TokenSequenceConstIterator<T> ConstIterator;
sergei 2016/01/25 14:13:52 I would like to have it as a public member and nam
Eric 2016/01/26 15:54:19 When our style guide at https://adblockplus.org/en
sergei 2016/01/26 22:34:58 I thought that it's natural to adhere to common it
27 friend class ConstIterator;
28 const T delimiters;
29 const T value;
30
31 /**
32 * Default constructor is deleted
33 */
34 TokenSequence(); // = delete
35
36 public:
37 TokenSequence(const T& value, const T& delimiters)
38 : value(value), delimiters(delimiters)
39 {
40 if (delimiters.empty())
41 {
42 // If we don't have delimiter characters, the 'first_first_*' functions wi ll have undefined behavior.
43 throw std::runtime_error("Must have at least one delimiter character");
44 }
45 }
46
47 ConstIterator cbegin() const
48 {
49 return ConstIterator(*this, ConstIterator::BeginMarker());
50 }
51
52 ConstIterator cend() const
53 {
54 return ConstIterator(*this, ConstIterator::EndMarker());
55 }
56 };
57
58 /**
59 * Iterator class for TokenSequence<T>
60 *
61 * All constructors are private, only available to TokenSequence<T> through a fr iend declaration.
62 *
63 * Invariant
64 * if posFirstCharInToken == npos
65 * iterator is "end()"
66 * else
67 * 0 <= posFirstCharInToken < posFirstCharNotInToken <= length of underlying container string
68 * first token position = posFirstCharInToken
69 * token length = posFirstCharNotInToken - posFirstCharInToken
70 */
71 template<class T>
72 class TokenSequenceConstIterator
73 {
74 typedef TokenSequence<T> Container;
75 friend class Container;
76 const Container& sequence;
sergei 2016/01/25 14:13:54 I'm pretty sure it generates a warning something l
Eric 2016/01/26 15:54:20 I am completely sure it does not generate a warnin
sergei 2016/01/26 22:34:57 OK, our warning level does not generate a warning
77 size_t posFirstCharInToken;
sergei 2016/01/25 14:13:54 Wouldn't it better to name it as `tokenFirstCharPo
Eric 2016/01/26 15:54:20 It's "position of the first character in the token
sergei 2016/01/26 22:34:57 Let's say there is a string "aaa bbb ccc", after t
78 size_t posFirstCharNotInToken;
sergei 2016/01/25 14:13:53 And this one is a position of the next delimiter,
Eric 2016/01/26 15:54:21 Your suggested name is not as precise as the curre
sergei 2016/01/26 22:34:58 That's clear that it's a right-open interval, BTW,
79
80 class BeginMarker {};
81 class EndMarker {};
82
83 /**
84 * Default constructor is deleted
85 */
86 TokenSequenceConstIterator(); // = delete
87
88 /**
89 * Constructor for cbegin()
90 */
91 TokenSequenceConstIterator(const TokenSequence<T>& sequence, BeginMarker)
92 : sequence(sequence)
93 {
94 Advance(0);
95 }
96
97 /**
98 * Constructor for cend()
99 */
100 TokenSequenceConstIterator(const TokenSequence<T>& sequence, EndMarker)
101 : sequence(sequence), posFirstCharInToken(T::npos)
sergei 2016/01/25 14:13:54 I feel myself uncomfortable when not all members w
Eric 2016/01/26 15:54:20 If you would like a comment about why 'posFirstCha
sergei 2016/01/26 22:34:57 Don't forget about readability and maintainability
102 {
103 }
104
105 /**
106 * Find the next token beginning at or after the given position
107 */
108 void Advance(size_t posStart)
sergei 2016/01/25 14:13:54 Wouldn't it be better to rename it to something li
Eric 2016/01/26 15:54:19 It's better to name functions "what they do" than
sergei 2016/01/26 22:34:57 "advance to the next token" actually means `find n
109 {
110 posFirstCharInToken = sequence.value.find_first_not_of(sequence.delimiters, posStart);
sergei 2016/01/25 14:13:53 That line "eats" all delimiters and skips empty to
Eric 2016/01/26 15:54:19 From my point of view, it's completely conventiona
sergei 2016/01/26 22:34:57 Why not to use it with comma as a delimiter and ho
111 if (posFirstCharInToken == T::npos)
112 {
113 // If we've become an "end()" iterator, we're done.
114 return;
115 }
116 posFirstCharNotInToken = sequence.value.find_first_of(sequence.delimiters, p osFirstCharInToken + 1);
117 if (posFirstCharNotInToken == T::npos)
118 {
119 posFirstCharNotInToken = sequence.value.length();
120 }
121 }
122
123 public:
124 bool operator==(const TokenSequenceConstIterator& other) const
125 {
126 if (&sequence != &other.sequence)
127 {
128 return false; // iterators to different sequences cannot be equal
129 }
130 // Iterators with the same initial token position will also have the same fi nal final position
131 // "end()" iterators use "npos" as their position
132 return posFirstCharInToken == other.posFirstCharInToken;
133 }
134
135 bool operator!=(const TokenSequenceConstIterator& other) const
136 {
137 return !operator==(other);
138 }
139
140 void operator++()
sergei 2016/01/25 14:13:53 It seems we are not using it, but it can be very c
Eric 2016/01/26 15:54:20 Right. We're not using it. So no need for a return
141 {
142 if (posFirstCharInToken == T::npos)
143 {
144 return; // Incrementing "end()" yields "end()"
sergei 2016/01/25 14:13:52 Should we throw an exception here instead?
Eric 2016/01/26 15:54:20 In fact, the way that this code is used in 'for' l
sergei 2016/01/26 22:34:58 It defensive but it protects silently, if we are t
145 }
146 if (posFirstCharNotInToken >= sequence.value.length())
147 {
148 // We are already at the end of the sequence. No need to search more.
149 posFirstCharInToken = T::npos;
sergei 2016/01/25 14:13:53 I'm not sure that we actually need to make an assi
Eric 2016/01/26 15:54:19 The very simple answer is that we're incrementing
sergei 2016/01/26 22:34:58 Sorry, I have overlooked it, I have wrongly read `
150 return;
sergei 2016/01/25 14:13:54 Should we rather throw an exception?
Eric 2016/01/26 15:54:20 Never. Incrementing to "end()" is not an error.
151 }
152 Advance(posFirstCharNotInToken + 1);
153 }
154
155 T operator*() const
156 {
157 if (posFirstCharInToken == T::npos)
158 {
159 throw std::runtime_error("Cannot dereference end() iterator");
160 }
161 return sequence.value.substr(posFirstCharInToken, posFirstCharNotInToken - p osFirstCharInToken);
162 }
163 };
OLDNEW

Powered by Google App Engine
This is Rietveld