Make line_iterator less slow

This commit is contained in:
Thomas Goyne 2013-12-17 20:04:52 -08:00
parent 45726bea3c
commit f534205a91
1 changed files with 29 additions and 34 deletions

View File

@ -34,9 +34,7 @@ namespace agi {
template<class OutputType = std::string> template<class OutputType = std::string>
class line_iterator : public std::iterator<std::input_iterator_tag, OutputType> { class line_iterator : public std::iterator<std::input_iterator_tag, OutputType> {
std::istream *stream; ///< Stream to iterator over std::istream *stream; ///< Stream to iterator over
bool valid; ///< Are there any more values to read?
OutputType value; ///< Value to return when this is dereference OutputType value; ///< Value to return when this is dereference
std::string encoding; ///< Encoding of source stream
std::shared_ptr<agi::charset::IconvWrapper> conv; std::shared_ptr<agi::charset::IconvWrapper> conv;
int cr; ///< CR character in the source encoding int cr; ///< CR character in the source encoding
int lf; ///< LF character in the source encoding int lf; ///< LF character in the source encoding
@ -65,8 +63,6 @@ public:
/// @param encoding Encoding of the text read from the stream /// @param encoding Encoding of the text read from the stream
line_iterator(std::istream &stream, std::string encoding = "utf-8") line_iterator(std::istream &stream, std::string encoding = "utf-8")
: stream(&stream) : stream(&stream)
, valid(true)
, encoding(encoding)
, cr('\r') , cr('\r')
, lf('\n') , lf('\n')
, width(1) , width(1)
@ -84,25 +80,11 @@ public:
} }
/// @brief Invalid iterator constructor; use for end iterator /// @brief Invalid iterator constructor; use for end iterator
line_iterator() line_iterator() : stream(nullptr) { }
: stream(nullptr)
, valid(false)
{
}
/// @brief Copy constructor /// @brief Copy constructor
/// @param that line_iterator to copy from /// @param that line_iterator to copy from
line_iterator(line_iterator<OutputType> const& that) line_iterator(line_iterator<OutputType> const&) = default;
: stream(that.stream)
, valid(that.valid)
, value(that.value)
, encoding(that.encoding)
, conv(that.conv)
, cr(that.cr)
, lf(that.lf)
, width(that.width)
{
}
OutputType const& operator*() const { return value; } OutputType const& operator*() const { return value; }
OutputType const* operator->() const { return &value; } OutputType const* operator->() const { return &value; }
@ -117,7 +99,7 @@ public:
return tmp; return tmp;
} }
bool operator==(line_iterator<OutputType> const& rgt) const { return valid == rgt.valid; } bool operator==(line_iterator<OutputType> const& rgt) const { return stream == rgt.stream; }
bool operator!=(line_iterator<OutputType> const& rgt) const { return !operator==(rgt); } bool operator!=(line_iterator<OutputType> const& rgt) const { return !operator==(rgt); }
// typedefs needed by some stl algorithms // typedefs needed by some stl algorithms
@ -126,7 +108,7 @@ public:
typedef const OutputType* const_pointer; typedef const OutputType* const_pointer;
typedef const OutputType& const_reference; typedef const OutputType& const_reference;
line_iterator<OutputType> operator=(line_iterator<OutputType> that) { line_iterator<OutputType>& operator=(line_iterator<OutputType> that) {
using std::swap; using std::swap;
swap(*this, that); swap(*this, that);
return *this; return *this;
@ -135,9 +117,7 @@ public:
void swap(line_iterator<OutputType> &that) throw() { void swap(line_iterator<OutputType> &that) throw() {
using std::swap; using std::swap;
swap(stream, that.stream); swap(stream, that.stream);
swap(valid, that.valid);
swap(value, that.value); swap(value, that.value);
swap(encoding, that.encoding);
swap(conv, that.conv); swap(conv, that.conv);
swap(lf, that.lf); swap(lf, that.lf);
swap(cr, that.cr); swap(cr, that.cr);
@ -179,16 +159,16 @@ void line_iterator<OutputType>::getline(std::string &str) {
template<class OutputType> template<class OutputType>
void line_iterator<OutputType>::next() { void line_iterator<OutputType>::next() {
if (!valid) return; if (!stream) return;
if (!stream->good()) { if (!stream->good()) {
valid = false; stream = nullptr;
return; return;
} }
std::string str, cstr, *target; std::string str, cstr, *target;
if (width == 1) { if (width == 1) {
std::getline(*stream, str); std::getline(*stream, str);
if (str.size() && *str.rbegin() == '\r') if (str.size() && str.back() == '\r')
str.resize(str.size() - 1); str.pop_back();
} }
else { else {
getline(str); getline(str);
@ -200,10 +180,30 @@ void line_iterator<OutputType>::next() {
else { else {
target = &str; target = &str;
} }
if (!convert(*target)) { if (!convert(*target))
next(); next();
}
template<>
inline void line_iterator<std::string>::next() {
if (!stream) return;
if (!stream->good()) {
stream = nullptr;
return; return;
} }
std::string cstr;
std::string *target = conv ? &cstr : &value;
if (width == 1) {
std::getline(*stream, *target);
if (target->size() && target->back() == '\r')
target->pop_back();
}
else
getline(*target);
if (conv.get()) {
value.clear();
conv->Convert(*target, value);
}
} }
template<class OutputType> template<class OutputType>
@ -212,11 +212,6 @@ inline bool line_iterator<OutputType>::convert(std::string &str) {
ss >> value; ss >> value;
return !ss.fail(); return !ss.fail();
} }
template<>
inline bool line_iterator<std::string>::convert(std::string &str) {
value = str;
return true;
}
template<class T> template<class T>
void swap(agi::line_iterator<T> &lft, agi::line_iterator<T> &rgt) { void swap(agi::line_iterator<T> &lft, agi::line_iterator<T> &rgt) {