Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions include/boost/archive/iterators/remove_whitespace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ class filter_iterator
typedef filter_iterator<Predicate, Base> this_t;
typedef typename super_t::reference reference_type;

void satisfy_predicate(){
while(this->base_reference() != m_end
&& ! m_predicate(* this->base_reference())){
++(this->base_reference());
}
}

reference_type dereference_impl(){
if(! m_full){
while(! m_predicate(* this->base_reference()))
Expand All @@ -110,23 +117,47 @@ class filter_iterator
}

reference_type dereference() const {
if(m_bounded){
return * this->base_reference();
}
return const_cast<this_t *>(this)->dereference_impl();
}

Predicate m_predicate;
bool m_full;
Base m_end;
bool m_bounded;
public:
// note: this function is public only because comeau compiler complained
// I don't know if this is because the compiler is wrong or what
void increment(){
m_full = false;
++(this->base_reference());
if(m_bounded){
satisfy_predicate();
}
else{
m_full = false;
}
}
filter_iterator(Base start) :
super_t(start),
m_full(false)
m_full(false),
m_end(),
m_bounded(false)
{}
filter_iterator(Base start, Base end) :
super_t(start),
m_full(false),
m_end(end),
m_bounded(true)
{
satisfy_predicate();
}
filter_iterator() :
m_full(false),
m_end(),
m_bounded(false)
{}
filter_iterator(){}
};

template<class Base>
Expand Down Expand Up @@ -154,6 +185,10 @@ class remove_whitespace :
remove_whitespace(T start) :
super_t(Base(static_cast< T >(start)))
{}
template<class T>
remove_whitespace(T start, T end) :
super_t(Base(static_cast< T >(start)), Base(static_cast< T >(end)))
{}
};

} // namespace iterators
Expand Down
21 changes: 21 additions & 0 deletions test/test_iterators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <cstdlib> // for rand
#include <functional>
#include <sstream> // used to test stream iterators
#include <string>
#include <clocale>
#include <iterator> // begin
#include <locale> // setlocale
Expand All @@ -32,6 +33,7 @@ namespace std{
#endif
#include <boost/archive/iterators/xml_escape.hpp>
#include <boost/archive/iterators/xml_unescape.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/istream_iterator.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
Expand Down Expand Up @@ -195,6 +197,23 @@ void test_stream_iterators(
BOOST_CHECK(std::equal(test_data, test_data + size,isi));
}

// Regression test for issue #254: the bounded (two-argument) filter form
// must handle a range that ends in a non-matching element without running
// past the end.
void test_remove_whitespace(){
typedef boost::archive::iterators::remove_whitespace<const char *> translator;

const char with_ws[] = " a b\tc \n"; // leading, embedded and trailing ws
const char * b = with_ws;
const char * e = with_ws + sizeof(with_ws) / sizeof(char) - 1;
BOOST_CHECK(std::string(translator(b, e), translator(e, e)) == "abc");

const char all_ws[] = " "; // filters to empty, must not overrun
const char * wb = all_ws;
const char * we = all_ws + sizeof(all_ws) / sizeof(char) - 1;
BOOST_CHECK(std::string(translator(wb, we), translator(we, we)).empty());
}

int
test_main(int /* argc */, char* /* argv */ [] )
{
Expand Down Expand Up @@ -253,5 +272,7 @@ test_main(int /* argc */, char* /* argv */ [] )
test_transform_width<6, 8>(7);
test_transform_width<6, 8>(8);

test_remove_whitespace();

return EXIT_SUCCESS;
}