/*============================================================================= Copyright (c) 2003 Giovanni Bajo http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include // Our baby #include using namespace std; using namespace BOOST_SPIRIT_CLASSIC_NS; namespace mpl = boost::mpl; /////////////////////////////////////////////////////////////////////////////// namespace test_impl { template void InstanciateTestOne(void) { IterT(); // Check that the iterator is a full non-mutable forward iterator typedef boost::ForwardIteratorConcept concept_t; boost::function_requires(); } struct InstanciateTest { template void operator()(BaseIterT ) { InstanciateTestOne >(); InstanciateTestOne >(); InstanciateTestOne >(); InstanciateTestOne >(); } }; /////////////////////////////////////////////////////////////////////////////// } /* namespace test_impl */ // These tests are defined after main() to be absolutely sure that the // instantiation test will happen before any other (since it's mainly // a compile-time test). void CheckInstantiation(void); void CheckConstructors(void); void CheckBasicFunctionality(void); void CheckColumnCounting(void); void CheckLineExtraction(void); void CheckDistance(void); void CheckSingular(); void CheckInstantiation(void) { typedef mpl::list < char* ,const char* ,string::iterator ,string::const_iterator > iter_list_t; mpl::for_each(test_impl::InstanciateTest()); } int main(void) { CheckInstantiation(); CheckConstructors(); CheckBasicFunctionality(); CheckColumnCounting(); CheckLineExtraction(); CheckDistance(); CheckSingular(); return boost::report_errors(); } /////////////////////////////////////////////////////////////////////////////// namespace test_impl { template void CheckIncrement(IterT iter) { IterT end; // Check also that copy construction and assignment do not // interfere with increment IterT iter2(iter); IterT iter3 = iter; BOOST_TEST(iter != end); BOOST_TEST(iter2 != end); BOOST_TEST(iter3 != end); BOOST_TEST(*iter == '0'); ++iter; ++iter2; ++iter3; BOOST_TEST(iter == iter2); BOOST_TEST(iter == iter3); BOOST_TEST(*iter == *iter2); BOOST_TEST(*iter == *iter3); BOOST_TEST(iter.get_position() == iter2.get_position()); BOOST_TEST(iter.get_position() == iter3.get_position()); BOOST_TEST(*iter == '1'); BOOST_TEST(*iter++ == '1'); BOOST_TEST(*iter2++ == '1'); BOOST_TEST(*iter3++ == '1'); BOOST_TEST(*iter == *iter2); BOOST_TEST(*iter == *iter3); BOOST_TEST(iter.get_position() == iter2.get_position()); BOOST_TEST(iter.get_position() == iter3.get_position()); BOOST_TEST(*iter == '2'); ++iter; ++iter; ++iter; ++iter; ++iter; ++iter; ++iter; BOOST_TEST(*iter == '9'); ++iter; BOOST_TEST(iter == end); // Check that one after end is no more end ++iter; BOOST_TEST(iter != end); } template void CheckLineCounting(IterT iter) { IterT end; BOOST_TEST(*iter == '\n'); BOOST_TEST(iter.get_position().line == 1); ++iter; // 0 BOOST_TEST(iter.get_position().line == 2); ++iter; // 1 ++iter; // 2 ++iter; // 3 ++iter; // \r BOOST_TEST(*iter == '\r'); BOOST_TEST(iter.get_position().line == 2); ++iter; // \n BOOST_TEST(*iter == '\n'); BOOST_TEST(iter.get_position().line == 2); ++iter; // 4 BOOST_TEST(iter.get_position().line == 3); ++iter; // 5 ++iter; // 6 ++iter; // 7 ++iter; // \n BOOST_TEST(*iter == '\n'); BOOST_TEST(iter.get_position().line == 3); ++iter; // 8 BOOST_TEST(iter.get_position().line == 4); ++iter; // 9 ++iter; // \n BOOST_TEST(iter.get_position().line == 4); BOOST_TEST(*iter == '\n'); ++iter; // \r BOOST_TEST(iter.get_position().line == 5); BOOST_TEST(*iter == '\r'); ++iter; // end BOOST_TEST(iter.get_position().line == 6); BOOST_TEST(iter == end); } template void CheckColumnCounting_Tab4(IterT iter) { IterT end; // Don't call set_tabchars() here because // default must be 3. BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 1); ++iter; // 0 BOOST_TEST(iter.get_position().column == 5); ++iter; // 1 BOOST_TEST(iter.get_position().column == 6); ++iter; // 2 BOOST_TEST(iter.get_position().column == 7); ++iter; // 3 BOOST_TEST(iter.get_position().column == 8); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 9); ++iter; // 4 BOOST_TEST(iter.get_position().column == 13); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 14); ++iter; // 5 BOOST_TEST(iter.get_position().column == 17); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 18); ++iter; // end BOOST_TEST(iter == end); } template void CheckColumnCounting_Tab3(IterT iter) { IterT end; iter.set_tabchars(3); // Check also that tab settings propagates through // assignment and copy construction IterT iter2(iter); IterT iter3; iter3 = iter2; BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 1); ++iter; // 0 ++iter2; ++iter3; BOOST_TEST(iter.get_position().column == 4); BOOST_TEST(iter2.get_position().column == 4); BOOST_TEST(iter3.get_position().column == 4); ++iter; // 1 BOOST_TEST(iter.get_position().column == 5); ++iter; // 2 BOOST_TEST(iter.get_position().column == 6); ++iter; // 3 BOOST_TEST(iter.get_position().column == 7); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 8); ++iter; // 4 BOOST_TEST(iter.get_position().column == 10); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 11); ++iter; // 5 BOOST_TEST(iter.get_position().column == 13); ++iter; // tab BOOST_TEST(*iter == '\t'); BOOST_TEST(iter.get_position().column == 14); ++iter; // end BOOST_TEST(iter == end); } const string line1 = "abcd"; const string line2 = "efgh"; const string linebuf = "\n" + line1 + "\n" + line2 + "\n"; template void AssertIterString(IterT begin, IterT end, string s) { BOOST_TEST(string(begin, end) == s); } template void CheckLineExtractionOne(IterT iter) { IterT end; // At the start, we are on a newline, which is an empty // string BOOST_TEST(iter.get_currentline() == string()); BOOST_TEST( string(iter.get_currentline_begin(), iter.get_currentline_end()) == string()); ++iter; // a ++iter; // b ++iter; // c BOOST_TEST(iter.get_currentline() == line1); AssertIterString( iter.get_currentline_begin(), iter.get_currentline_end(), line1); ++iter; // d ++iter; // newline ++iter; // e // check that copy construction and assignment do // not interfere with get_currentline IterT iter2(iter); IterT iter3; iter3 = iter; BOOST_TEST(iter2.get_currentline() == line2); BOOST_TEST(iter3.get_currentline() == line2); AssertIterString( iter2.get_currentline_begin(), iter2.get_currentline_end(), line2); AssertIterString( iter3.get_currentline_begin(), iter3.get_currentline_end(), line2); ++iter; // f ++iter; // g ++iter; // h ++iter; // newline // Check when the iterator is on a newline BOOST_TEST(iter.get_currentline() == line2); AssertIterString( iter.get_currentline_begin(), iter.get_currentline_end(), line2); ++iter; BOOST_TEST(iter == end); } void CheckLineExtraction(void) { typedef string::const_iterator iter_t; CheckLineExtractionOne( position_iterator2 (linebuf.begin(), linebuf.end(), "")); CheckLineExtractionOne( position_iterator2 (linebuf.begin(), linebuf.end(), "")); } template void CheckEmptySequence(void) { typedef IterT iter_t; char a[10]; // Check construction with empty sequence, and // correct propagation of the information iter_t iter(a,a, ""); iter_t iter2(iter); iter_t iter3; iter3 = iter; BOOST_TEST(iter == iter_t()); BOOST_TEST(iter2 == iter_t()); BOOST_TEST(iter3 == iter_t()); } template void CheckConstructors(void) { char a[20]; std::string name = "abc"; file_position_without_column pos(name,1); file_position posc(name,1,1); typedef IterC iterc_t; typedef Iter iter_t; BOOST_TEST(iterc_t(a,a+20,name).get_position() == posc); BOOST_TEST(iterc_t(a,a+20,name,1).get_position() == posc); BOOST_TEST(iterc_t(a,a+20,name,1,1).get_position() == posc); BOOST_TEST(iterc_t(a,a+20,posc).get_position() == posc); BOOST_TEST(iter_t(a,a+20,name).get_position() == pos); BOOST_TEST(iter_t(a,a+20,name,1).get_position() == pos); BOOST_TEST(iter_t(a,a+20,pos).get_position() == pos); // Check copy constructor and assignment. Notice that we want // an implicit copy constructor. iterc_t ic1(a,a+20,name); iterc_t ic2 = ic1; iterc_t ic3; ic3 = ic1; BOOST_TEST(ic1 == ic2); BOOST_TEST(ic1 == ic3); BOOST_TEST(ic1.get_position() == ic2.get_position()); BOOST_TEST(ic1.get_position() == ic3.get_position()); iter_t i1(a,a+20,name); iter_t i2 = i1; iter_t i3; i3 = i1; BOOST_TEST(i1 == i2); BOOST_TEST(i1 == i3); BOOST_TEST(i1.get_position() == i2.get_position()); BOOST_TEST(i1.get_position() == i3.get_position()); // Check construction with an empty sequence CheckEmptySequence(); CheckEmptySequence(); } template void CheckDistance(IterT begin) { IterT end; std::size_t std_distance = std::distance(begin, end); std::size_t manual_count = 0; for(IterT it = begin; it != end; ++it) ++manual_count; BOOST_TEST(std_distance == manual_count); } /////////////////////////////////////////////////////////////////////////////// } /* namespace test_impl */ void CheckConstructors(void) { test_impl::CheckConstructors < position_iterator, position_iterator >(); test_impl::CheckConstructors < position_iterator2, position_iterator2 >(); } void CheckBasicFunctionality(void) { const char* a = "0123456789"; typedef const char* iter_t; test_impl::CheckIncrement(position_iterator(a, a+10, "")); test_impl::CheckIncrement(position_iterator2(a, a+10, "")); test_impl::CheckIncrement(position_iterator(a, a+10, "")); test_impl::CheckIncrement(position_iterator2(a, a+10, "")); const char* b = "\n0123\r\n4567\n89\n\r"; test_impl::CheckLineCounting(position_iterator(b, b+16, "")); test_impl::CheckLineCounting(position_iterator2(b, b+16, "")); test_impl::CheckLineCounting(position_iterator(b, b+16, "")); test_impl::CheckLineCounting(position_iterator2(b, b+16, "")); } void CheckColumnCounting(void) { const char* a = "\t0123\t4\t5\t"; typedef const char* iter_t; test_impl::CheckColumnCounting_Tab4(position_iterator(a, a+10, "")); test_impl::CheckColumnCounting_Tab4(position_iterator2(a, a+10, "")); test_impl::CheckColumnCounting_Tab3(position_iterator(a, a+10, "")); test_impl::CheckColumnCounting_Tab3(position_iterator2(a, a+10, "")); } void CheckLineExtraction(void) { test_impl::CheckLineExtraction(); } void CheckDistance(void) { const char* b = "\n0123\r\n4567\n89\n\r"; typedef const char* iter_t; test_impl::CheckDistance(position_iterator(b, b+15, "")); test_impl::CheckDistance(position_iterator2(b, b+15, "")); test_impl::CheckDistance(position_iterator(b, b+15, "")); test_impl::CheckDistance(position_iterator2(b, b+15, "")); } /////////////////////////////////////////////////////////////////////////////// namespace test_impl { template class check_singular_iterator { bool singular_; int count_; public: typedef std::forward_iterator_tag iterator_category; typedef int value_type; typedef std::ptrdiff_t difference_type; typedef int const* pointer; typedef typename boost::mpl::if_c::type reference; check_singular_iterator() : singular_(true), count_(0) {} explicit check_singular_iterator(int x) : singular_(false), count_(x) {} reference operator*() const { BOOST_TEST(!singular_); return count_; } pointer operator->() const { BOOST_TEST(!singular_); return &count_; } check_singular_iterator& operator++() { BOOST_TEST(count_ > 0); --count_; return *this; } check_singular_iterator operator++(int) { check_singular_iterator tmp(*this); ++(*this); return tmp; } bool operator==(check_singular_iterator const& other) const { BOOST_TEST(!singular_ && !other.singular_); return count_ == other.count_; } bool operator!=(check_singular_iterator const& other) const { return !(*this == other); } }; template void CheckSingularImpl() { CountIterator begin(Iterator(5), Iterator(0)); CountIterator end1(Iterator(0), Iterator(0)); CountIterator end2; BOOST_TEST(begin == begin); BOOST_TEST(begin != end1); BOOST_TEST(begin != end2); BOOST_TEST(end1 != begin); BOOST_TEST(end1 == end1); BOOST_TEST(end1 == end2); BOOST_TEST(end2 != begin); BOOST_TEST(end2 == end1); BOOST_TEST(end2 == end2); BOOST_TEST(std::distance(begin, begin) == 0); BOOST_TEST(std::distance(begin, end1) == 5); BOOST_TEST(std::distance(begin, end2) == 5); BOOST_TEST(std::distance(end1, end1) == 0); BOOST_TEST(std::distance(end1, end2) == 0); BOOST_TEST(std::distance(end2, end1) == 0); BOOST_TEST(std::distance(end2, end2) == 0); BOOST_TEST(*begin == 5); } template void CheckSingular() { { typedef check_singular_iterator interator_type; CheckSingularImpl, interator_type>(); CheckSingularImpl, interator_type>(); } { typedef check_singular_iterator interator_type; CheckSingularImpl, interator_type>(); CheckSingularImpl, interator_type>(); } } } void CheckSingular() { test_impl::CheckSingular(); test_impl::CheckSingular(); }