1 | // Boost.Range library |
2 | // |
3 | // Copyright Thorsten Ottosen 2003-2004. 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 | //#define _MSL_USING_NAMESPACE 1 |
12 | |
13 | #include <boost/detail/workaround.hpp> |
14 | |
15 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
16 | # pragma warn -8091 // suppress warning in Boost.Test |
17 | # pragma warn -8057 // unused argument argc/argv in Boost.Test |
18 | #endif |
19 | |
20 | #include <boost/array.hpp> |
21 | #include <boost/range/as_array.hpp> |
22 | #include <boost/range/as_literal.hpp> |
23 | #include <boost/range/functions.hpp> |
24 | #include <boost/range/metafunctions.hpp> |
25 | #include <boost/static_assert.hpp> |
26 | #include <boost/type_traits.hpp> |
27 | #include <boost/test/test_tools.hpp> |
28 | #include <boost/config.hpp> |
29 | #include <vector> |
30 | #include <fstream> |
31 | #include <iterator> |
32 | #include <algorithm> |
33 | |
34 | namespace |
35 | { |
36 | template< class CharT, std::size_t Length > |
37 | class test_string |
38 | { |
39 | public: |
40 | typedef CharT value_type; |
41 | typedef value_type* pointer; |
42 | typedef const value_type* const_pointer; |
43 | typedef std::size_t size_type; |
44 | typedef value_type array_t[Length]; |
45 | typedef const value_type const_array_t[Length]; |
46 | |
47 | explicit test_string(const CharT literal_sz[]) |
48 | { |
49 | std::copy(literal_sz, literal_sz + Length, m_buffer.data()); |
50 | m_buffer[Length] = value_type(); |
51 | } |
52 | |
53 | const_pointer const_sz() const { return m_buffer.data(); } |
54 | pointer mutable_sz() { return m_buffer.data(); } |
55 | |
56 | private: |
57 | typedef boost::array<value_type, Length + 1> buffer_t; |
58 | buffer_t m_buffer; |
59 | }; |
60 | } |
61 | |
62 | template< class T > |
63 | inline BOOST_DEDUCED_TYPENAME boost::range_iterator<T>::type |
64 | str_begin( T& r ) |
65 | { |
66 | return boost::begin( boost::as_literal(r) ); |
67 | } |
68 | |
69 | template< class T > |
70 | inline BOOST_DEDUCED_TYPENAME boost::range_iterator<T>::type |
71 | str_end( T& r ) |
72 | { |
73 | return boost::end( boost::as_literal(r) ); |
74 | } |
75 | |
76 | template< class T > |
77 | inline BOOST_DEDUCED_TYPENAME boost::range_difference<T>::type |
78 | str_size( const T& r ) |
79 | { |
80 | return boost::size( boost::as_literal(r) ); |
81 | } |
82 | |
83 | template< class T > |
84 | inline bool |
85 | str_empty( T& r ) |
86 | { |
87 | return boost::empty( boost::as_literal(r) ); |
88 | } |
89 | |
90 | template< typename Container, typename T > |
91 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
92 | find( Container& c, T value ) |
93 | { |
94 | return std::find( str_begin(c), str_end(c), |
95 | value ); |
96 | } |
97 | |
98 | template< typename Container, typename T > |
99 | BOOST_DEDUCED_TYPENAME boost::range_iterator<const Container>::type |
100 | find( const Container& c, T value ) |
101 | { |
102 | return std::find( str_begin(c), str_end(c), |
103 | value ); |
104 | } |
105 | |
106 | template< typename Container, typename T > |
107 | BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type |
108 | find_mutable( Container& c, T value ) |
109 | { |
110 | str_size( c ); |
111 | return std::find( str_begin(c), str_end(c), |
112 | value ); |
113 | } |
114 | |
115 | template< typename Container, typename T > |
116 | BOOST_DEDUCED_TYPENAME boost::range_iterator<const Container>::type |
117 | find_const( const Container& c, T value ) |
118 | { |
119 | str_size( c ); |
120 | return std::find( str_begin(c), str_end(c), |
121 | value ); |
122 | } |
123 | |
124 | |
125 | std::vector<char> |
126 | check_rvalue_return() |
127 | { |
128 | return std::vector<char>( 10, 'm' ); |
129 | } |
130 | |
131 | using namespace boost; |
132 | |
133 | |
134 | void check_char() |
135 | { |
136 | typedef boost::range_difference<std::string>::type diff_t; |
137 | typedef char* char_iterator_t; |
138 | typedef char char_array_t[10]; |
139 | |
140 | test_string<char, 8> a_string("a string" ); |
141 | test_string<char, 14> another_string("another string" ); |
142 | |
143 | const char* char_s = a_string.const_sz(); |
144 | char my_string[] = "another_string" ; |
145 | const char my_const_string[] = "another string" ; |
146 | const diff_t my_string_length = 14; |
147 | char* char_s2 = a_string.mutable_sz(); |
148 | |
149 | BOOST_STATIC_ASSERT(( is_same< range_value<char_iterator_t>::type, |
150 | std::iterator_traits<char_iterator_t>::value_type>::value )); |
151 | BOOST_STATIC_ASSERT(( is_same< range_iterator<char_iterator_t>::type, char_iterator_t >::value )); |
152 | |
153 | BOOST_STATIC_ASSERT(( is_same< range_difference<char_iterator_t>::type, |
154 | ::std::ptrdiff_t >::value )); |
155 | BOOST_STATIC_ASSERT(( is_same< range_size<char_iterator_t>::type, std::size_t >::value )); |
156 | BOOST_STATIC_ASSERT(( is_same< range_iterator<char_iterator_t>::type, char_iterator_t >::value )); |
157 | BOOST_STATIC_ASSERT(( is_same< range_iterator<const char*>::type, const char* >::value )); |
158 | |
159 | BOOST_STATIC_ASSERT(( is_same< range_value<char_array_t>::type, |
160 | char>::value )); |
161 | BOOST_STATIC_ASSERT(( is_same< range_iterator<char_array_t>::type, char* >::value )); |
162 | BOOST_STATIC_ASSERT(( is_same< range_iterator<const char_array_t>::type, const char* >::value )); |
163 | BOOST_STATIC_ASSERT(( is_same< range_difference<char_array_t>::type, |
164 | ::std::ptrdiff_t >::value )); |
165 | BOOST_STATIC_ASSERT(( is_same< range_size<char_array_t>::type, std::size_t >::value )); |
166 | BOOST_STATIC_ASSERT(( is_same< range_iterator<char_array_t>::type, char* >::value )); |
167 | BOOST_STATIC_ASSERT(( is_same< range_iterator<const char_array_t>::type, const char* >::value )); |
168 | |
169 | BOOST_CHECK_EQUAL( str_begin( char_s ), char_s ); |
170 | const diff_t sz = str_size(r: char_s); |
171 | const char* str_end1 = str_begin( r&: char_s ) + sz; |
172 | BOOST_CHECK_EQUAL( str_end( char_s ), str_end1 ); |
173 | BOOST_CHECK_EQUAL( str_empty( char_s ), (char_s == 0 || char_s[0] == char()) ); |
174 | BOOST_CHECK_EQUAL( sz, static_cast<diff_t>(std::char_traits<char>::length(char_s)) ); |
175 | |
176 | BOOST_CHECK_EQUAL( str_begin( my_string ), my_string ); |
177 | range_iterator<char_array_t>::type str_end2 = str_begin( r&: my_string ) + str_size(r: my_string); |
178 | range_iterator<char_array_t>::type str_end3 = str_end(r&: my_string); |
179 | BOOST_CHECK_EQUAL( str_end3, str_end2 ); |
180 | BOOST_CHECK_EQUAL( str_empty( my_string ), (my_string == 0 || my_string[0] == char()) ); |
181 | BOOST_CHECK_EQUAL( str_size( my_string ), my_string_length ); |
182 | BOOST_CHECK_EQUAL( str_size( my_string ), static_cast<diff_t>(std::char_traits<char>::length(my_string)) ); |
183 | |
184 | char to_search = 'n'; |
185 | BOOST_CHECK( find_mutable( char_s, to_search ) != str_end( char_s ) ); |
186 | BOOST_CHECK( find_const( char_s, to_search ) != str_end(char_s) ); |
187 | |
188 | BOOST_CHECK( find_mutable( my_string, to_search ) != str_end(my_string) ); |
189 | BOOST_CHECK( find_const( my_string, to_search ) != str_end(my_string) ); |
190 | |
191 | BOOST_CHECK( find_mutable( char_s2, to_search ) != str_end(char_s) ); |
192 | BOOST_CHECK( find_const( char_s2, to_search ) != str_end(char_s2) ); |
193 | |
194 | BOOST_CHECK( find_const( as_array( my_string ), to_search ) != str_end(my_string) ); |
195 | BOOST_CHECK( find_const( as_array( my_const_string ), to_search ) != str_end(my_string) ); |
196 | |
197 | // |
198 | // Test that as_literal() always scan for null terminator |
199 | // |
200 | char an_array[] = "foo\0bar" ; |
201 | BOOST_CHECK_EQUAL( str_begin( an_array ), an_array ); |
202 | BOOST_CHECK_EQUAL( str_end( an_array ), an_array + 3 ); |
203 | BOOST_CHECK_EQUAL( str_size( an_array ), 3 ); |
204 | |
205 | const char a_const_array[] = "foobar\0doh" ; |
206 | BOOST_CHECK_EQUAL( str_begin( a_const_array ), a_const_array ); |
207 | BOOST_CHECK_EQUAL( str_end( a_const_array ), a_const_array + 6 ); |
208 | BOOST_CHECK_EQUAL( str_size( a_const_array ), 6 ); |
209 | |
210 | } |
211 | |
212 | |
213 | |
214 | void check_string() |
215 | { |
216 | check_char(); |
217 | |
218 | #ifndef BOOST_NO_STD_WSTRING |
219 | typedef wchar_t* wchar_iterator_t; |
220 | |
221 | test_string<wchar_t, 13> a_wide_string(L"a wide string" ); |
222 | test_string<wchar_t, 19> another_wide_string(L"another wide string" ); |
223 | |
224 | const wchar_t* char_ws = a_wide_string.const_sz(); |
225 | wchar_t my_wstring[] = L"another wide string" ; |
226 | wchar_t* char_ws2 = a_wide_string.mutable_sz(); |
227 | |
228 | BOOST_STATIC_ASSERT(( is_same< range_value<wchar_iterator_t>::type, |
229 | std::iterator_traits<wchar_iterator_t>::value_type>::value )); |
230 | BOOST_STATIC_ASSERT(( is_same< range_iterator<wchar_iterator_t>::type, wchar_iterator_t >::value )); |
231 | BOOST_STATIC_ASSERT(( is_same< range_iterator<const wchar_t*>::type, const wchar_t* >::value )); |
232 | BOOST_STATIC_ASSERT(( is_same< range_difference<wchar_iterator_t>::type, |
233 | std::iterator_traits<wchar_iterator_t>::difference_type >::value )); |
234 | BOOST_STATIC_ASSERT(( is_same< range_size<wchar_iterator_t>::type, std::size_t >::value )); |
235 | BOOST_STATIC_ASSERT(( is_same< range_iterator<wchar_iterator_t>::type, wchar_iterator_t >::value )); |
236 | BOOST_STATIC_ASSERT(( is_same< range_iterator<const wchar_t*>::type, const wchar_t* >::value )); |
237 | |
238 | typedef boost::range_difference<std::wstring>::type diff_t; |
239 | const diff_t sz = str_size( r: char_ws ); |
240 | BOOST_CHECK_EQUAL( str_begin( char_ws ), char_ws ); |
241 | BOOST_CHECK_EQUAL( str_end(char_ws), (str_begin( char_ws ) + sz) ); |
242 | BOOST_CHECK_EQUAL( str_empty( char_ws ), (char_ws == 0 || char_ws[0] == wchar_t()) ); |
243 | BOOST_CHECK_EQUAL( sz, static_cast<diff_t>(std::char_traits<wchar_t>::length(char_ws)) ); |
244 | |
245 | wchar_t to_search = L'n'; |
246 | BOOST_CHECK( find( char_ws, to_search ) != str_end(char_ws) ); |
247 | BOOST_CHECK( find( char_ws2, to_search ) != str_end(char_ws2) ); |
248 | |
249 | #if BOOST_WORKAROUND(_MSC_VER, BOOST_TESTED_AT(1300)) |
250 | |
251 | BOOST_CHECK( find( my_wstring, to_search ) != str_end(my_wstring) ); |
252 | |
253 | #else |
254 | |
255 | boost::ignore_unused_variable_warning( my_wstring ); |
256 | |
257 | #endif |
258 | #endif |
259 | |
260 | find( c: check_rvalue_return(), value: 'n' ); |
261 | |
262 | } |
263 | |
264 | #include <boost/test/unit_test.hpp> |
265 | using boost::unit_test::test_suite; |
266 | |
267 | |
268 | test_suite* init_unit_test_suite( int argc, char* argv[] ) |
269 | { |
270 | test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); |
271 | |
272 | test->add( BOOST_TEST_CASE( &check_string ) ); |
273 | |
274 | return test; |
275 | } |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 | |