1 // Boost.Range library
2 //
3 // Copyright Neil Groves 2014. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // For more information, see http://www.boost.org/libs/range/
9 //
10
11 #include <boost/detail/workaround.hpp>
12 #include <boost/range/iterator_range_core.hpp>
13 #include <boost/cstdint.hpp>
14
15 #include <boost/test/test_tools.hpp>
16 #include <boost/test/unit_test.hpp>
17
18 #include <vector>
19
20 namespace boost_range_test
21 {
22 namespace
23 {
24
25 class single_pass_iterator
26 : public boost::iterator_facade<
27 single_pass_iterator,
28 boost::int32_t,
29 boost::single_pass_traversal_tag,
30 const boost::int32_t&
31 >
32 {
33 friend class boost::iterator_core_access;
34
35 typedef std::vector<boost::int32_t>::const_iterator iterator_t;
36
37 public:
single_pass_iterator()38 single_pass_iterator() { }
39
single_pass_iterator(iterator_t it)40 explicit single_pass_iterator(iterator_t it)
41 : m_it(it)
42 {
43 }
44
45 private:
increment()46 void increment()
47 {
48 ++m_it;
49 }
50
equal(single_pass_iterator other) const51 bool equal(single_pass_iterator other) const
52 {
53 return m_it == other.m_it;
54 }
55
dereference() const56 reference dereference() const
57 {
58 return *m_it;
59 }
60
61 iterator_t m_it;
62 };
63
64 class bidirectional_iterator
65 : public boost::iterator_facade<
66 bidirectional_iterator,
67 boost::int32_t,
68 boost::bidirectional_traversal_tag,
69 const boost::int32_t&
70 >
71 {
72 friend class boost::iterator_core_access;
73
74 typedef std::vector<boost::int32_t>::const_iterator iterator_t;
75
76 public:
bidirectional_iterator()77 bidirectional_iterator() { }
78
bidirectional_iterator(iterator_t it)79 explicit bidirectional_iterator(iterator_t it)
80 : m_it(it)
81 {
82 }
83
84 private:
increment()85 void increment()
86 {
87 ++m_it;
88 }
89
decrement()90 void decrement()
91 {
92 --m_it;
93 }
94
equal(bidirectional_iterator other) const95 bool equal(bidirectional_iterator other) const
96 {
97 return m_it == other.m_it;
98 }
99
dereference() const100 reference dereference() const
101 {
102 return *m_it;
103 }
104
105 iterator_t m_it;
106 };
107
108 template<typename SinglePassRange>
109 boost::iterator_range<single_pass_iterator>
single_pass_range(const SinglePassRange & rng)110 single_pass_range(const SinglePassRange& rng)
111 {
112 return boost::iterator_range<single_pass_iterator>(
113 single_pass_iterator(boost::begin(rng)),
114 single_pass_iterator(boost::end(rng)));
115 }
116
117 template<typename BidirectionalRange>
118 boost::iterator_range<bidirectional_iterator>
bidirectional_range(const BidirectionalRange & rng)119 bidirectional_range(const BidirectionalRange& rng)
120 {
121 return boost::iterator_range<bidirectional_iterator>(
122 bidirectional_iterator(boost::begin(rng)),
123 bidirectional_iterator(boost::end(rng)));
124 }
125
test_drop_front()126 void test_drop_front()
127 {
128 std::vector<boost::int32_t> v;
129 std::vector<boost::int32_t> ref_output;
130
131 for (boost::int32_t i = 0; i < 10; ++i)
132 {
133 v.push_back(i);
134 ref_output.push_back(i);
135 }
136
137 boost::iterator_range<single_pass_iterator> rng = single_pass_range(v);
138
139 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
140 ref_output.begin(), ref_output.end());
141
142 rng.drop_front();
143
144 ref_output.erase(ref_output.begin());
145
146 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
147 ref_output.begin(), ref_output.end());
148
149 rng.drop_front(5);
150
151 ref_output.erase(ref_output.begin(), ref_output.begin() + 5);
152
153 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
154 ref_output.begin(), ref_output.end());
155 }
156
test_drop_back()157 void test_drop_back()
158 {
159 std::vector<boost::int32_t> v;
160 std::vector<boost::int32_t> ref_output;
161
162 for (boost::int32_t i = 0; i < 10; ++i)
163 {
164 v.push_back(i);
165 ref_output.push_back(i);
166 }
167
168 boost::iterator_range<bidirectional_iterator> rng = bidirectional_range(v);
169
170 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
171 ref_output.begin(), ref_output.end());
172
173 rng.drop_back();
174
175 ref_output.pop_back();
176
177 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
178 ref_output.begin(), ref_output.end());
179
180 rng.drop_back(5);
181
182 ref_output.erase(ref_output.end() - 5, ref_output.end());
183
184 BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(),
185 ref_output.begin(), ref_output.end());
186 }
187
188 } // anonymous namespace
189 } // namespace boost_range_test
190
init_unit_test_suite(int argc,char * argv[])191 boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] )
192 {
193 boost::unit_test::test_suite* test =
194 BOOST_TEST_SUITE("Boost.Range iterator_range drop functions");
195
196 test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_front));
197 test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_back));
198
199 return test;
200 }
201