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

Unified Diff: src/plugin/TokenSequence.h

Issue 29331055: Issue #1234 - Remove 'CString' from PluginFilter.* (Closed)
Patch Set: address comments Created Nov. 30, 2015, 3:51 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/plugin/TokenSequence.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/plugin/TokenSequence.h
@@ -0,0 +1,163 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-2015 Eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+template<class T> class TokenSequenceConstIterator; // forward declaration
+
+/**
+ * A sequence of delimited tokens contained within a given string.
+ */
+template<class T>
+class TokenSequence
+{
+ typedef TokenSequenceConstIterator<T> ConstIterator;
+ friend class ConstIterator;
+ const T delimiters;
+ const T value;
+
+ /**
+ * Default constructor is deleted
+ */
+ TokenSequence(); // = delete
+
+public:
+ TokenSequence(const T& value, const T& delimiters)
+ : value(value), delimiters(delimiters)
+ {
+ if (delimiters.empty())
+ {
+ // If we don't have delimiter characters, the 'first_first_*' functions will have undefined behavior.
+ throw std::runtime_error("Must have at least one delimiter character");
+ }
+ }
+
+ ConstIterator cbegin() const
+ {
+ return ConstIterator(*this, ConstIterator::BeginMarker());
+ }
+
+ ConstIterator cend() const
+ {
+ return ConstIterator(*this, ConstIterator::EndMarker());
+ }
+};
+
+/**
+ * Iterator class for TokenSequence<T>
+ *
+ * All constructors are private, only available to TokenSequence<T> through a friend declaration.
+ *
+ * Invariant
+ * if posFirstCharInToken == npos
+ * iterator is "end()"
+ * else
+ * 0 <= posFirstCharInToken < posFirstCharNotInToken <= length of underlying container string
+ * first token position = posFirstCharInToken
+ * token length = posFirstCharNotInToken - posFirstCharInToken
+ */
+template<class T>
+class TokenSequenceConstIterator
+{
+ typedef TokenSequence<T> Container;
+ friend class Container;
+ const Container& sequence;
+ size_t posFirstCharInToken;
+ size_t posFirstCharNotInToken;
+
+ class BeginMarker {};
+ class EndMarker {};
+
+ /**
+ * Default constructor is deleted
+ */
+ TokenSequenceConstIterator(); // = delete
+
+ /**
+ * Constructor for cbegin()
+ */
+ TokenSequenceConstIterator(const TokenSequence<T>& sequence, BeginMarker)
+ : sequence(sequence)
+ {
+ Advance(0);
+ }
+
+ /**
+ * Constructor for cend()
+ */
+ TokenSequenceConstIterator(const TokenSequence<T>& sequence, EndMarker)
+ : sequence(sequence), posFirstCharInToken(T::npos)
+ {
+ }
+
+ /**
+ * Find the next token beginning at or after the given position
+ */
+ void Advance(size_t posStart)
+ {
+ posFirstCharInToken = sequence.value.find_first_not_of(sequence.delimiters, posStart);
+ if (posFirstCharInToken == T::npos)
+ {
+ // If we've become an "end()" iterator, we're done.
+ return;
+ }
+ posFirstCharNotInToken = sequence.value.find_first_of(sequence.delimiters, posFirstCharInToken + 1);
+ if (posFirstCharNotInToken == T::npos)
+ {
+ posFirstCharNotInToken = sequence.value.length();
+ }
+ }
+
+public:
+ bool operator==(const TokenSequenceConstIterator& other) const
+ {
+ if (&sequence != &other.sequence)
+ {
+ return false; // iterators to different sequences cannot be equal
+ }
+ // Iterators with the same initial token position will also have the same final final position
+ // "end()" iterators use "npos" as their position
+ return posFirstCharInToken == other.posFirstCharInToken;
+ }
+
+ bool operator!=(const TokenSequenceConstIterator& other) const
+ {
+ return !operator==(other);
+ }
+
+ void operator++()
+ {
+ if (posFirstCharInToken == T::npos)
+ {
+ return; // Incrementing "end()" yields "end()"
+ }
+ if (posFirstCharNotInToken >= sequence.value.length())
+ {
+ // We are already at the end of the sequence. No need to search more.
+ posFirstCharInToken = T::npos;
+ return;
+ }
+ Advance(posFirstCharNotInToken + 1);
+ }
+
+ T operator*() const
+ {
+ if (posFirstCharInToken == T::npos)
+ {
+ throw std::runtime_error("Cannot dereference end() iterator");
+ }
+ return sequence.value.substr(posFirstCharInToken, posFirstCharNotInToken - posFirstCharInToken);
+ }
+};

Powered by Google App Engine
This is Rietveld