Created
March 1, 2014 15:54
-
-
Save m-ou-se/9291825 to your computer and use it in GitHub Desktop.
Peeking Idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class input { | |
// ... | |
/// Read the next character, but put it back. | |
/** | |
* \warning peek() does not work like std::istream::peek(). | |
* This function will actually take the next character from | |
* the stream, and the object returned by peek() will put it back | |
* when it is destroyed, unless take() was called on that object. | |
* This means, when correctly used, you can peek more than just one | |
* character. If you want to peek a lot, consider using 'start_peeking'. | |
*/ | |
peeked_char peek() { | |
return {this, get()}; | |
} | |
/// Start peeking characters. | |
/** | |
* Returns an object on which you can call get() with the same | |
* effect as calling get() on this \ref input object, except | |
* that when the object is destroyed, all of the characters obtained | |
* through it (limited to the ones since the last call to take(), if | |
* any), will be put back. | |
*/ | |
peeker start_peeking() { | |
return this; | |
} | |
protected: | |
class peeked_char { | |
private: | |
input * input_ = nullptr; | |
char character; | |
peeked_char(input * i, char c) : character(c), input_(i) {} | |
friend class input; | |
public: | |
peeked_char(peeked_char const &) = delete; | |
peeked_char & operator = (peeked_char const &) = delete; | |
peeked_char(peeked_char && o) { *this = std::move(o); } | |
peeked_char & operator = (peeked_char && o) { | |
character = o.character; | |
input_ = o.input_; | |
o.input_ = nullptr; | |
return *this; | |
} | |
char take() { | |
input_ = 0; | |
return character; | |
} | |
~peeked_char() { | |
if (input_) input_->output_buffer_.push_back(*this); | |
} | |
}; | |
class peeker { | |
private: | |
input * input_; | |
std::vector<char> buffer_; | |
peeker(input * i) : input_(i) {} | |
friend class input; | |
public: | |
peeker(peeker const &) = delete; | |
peeker & operator = (peeker const &) = delete; | |
peeker(peeker && o) { *this = std::move(o); } | |
peeker & operator = (peeker && o) { | |
input_ = o.input_; | |
buffer_ = std::move(o.buffer_); | |
o.buffer_.clear(); | |
return *this; | |
} | |
char get() { | |
auto c = input_->get(); | |
buffer_.push_back(c); | |
return c; | |
} | |
void take() { | |
buffer_.clear(); | |
} | |
~peeker() { | |
auto & b = input_->output_buffer_; | |
b.insert(b.end(), buffer_.rbegin(), buffer_.rend()); | |
} | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment