• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // -----------------------------------------------------------
2 //              Copyright (c) 2001 Jeremy Siek
3 //           Copyright (c) 2003-2006 Gennaro Prota
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // -----------------------------------------------------------
10 
11 #include <fstream>
12 #include <string>
13 #include <cstddef>   // for std::size_t
14 #include <stdexcept> // for std::logic_error
15 #include <assert.h>
16 
17 #include <boost/config.hpp>
18 #if !defined (BOOST_NO_STRINGSTREAM)
19 # include <sstream>
20 #endif
21 
22 #include "bitset_test.hpp"
23 #include <boost/dynamic_bitset/dynamic_bitset.hpp>
24 #include <boost/config/workaround.hpp>
25 
26 
27 // Codewarrior 8.3 for Win fails without this.
28 // Thanks Howard Hinnant ;)
29 #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
30 # pragma parse_func_templ off
31 #endif
32 
33 
34 #if defined BOOST_NO_STD_WSTRING || defined BOOST_NO_STD_LOCALE
35 # define BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
36 #endif
37 
38 #if !defined BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
widen_string(const std::string & str,const std::locale & loc=std::locale ())39 std::wstring widen_string( const std::string & str,
40                            const std::locale & loc = std::locale() )
41 {
42   std::wstring result;
43   const std::string::size_type len = str.length();
44   if(len != 0) {
45 
46     typedef std::ctype<wchar_t> ct_type;
47     typedef std::wstring::traits_type tr_type;
48     const ct_type & ct = BOOST_USE_FACET(ct_type, loc);
49 
50     result.resize(len);
51     for (std::size_t i = 0; i < len; ++i)
52         tr_type::assign(result[i], ct.widen(str[i]));
53 
54   }
55   return result;
56 }
57 #endif
58 
59 template <typename Block>
run_test_cases(BOOST_EXPLICIT_TEMPLATE_TYPE (Block))60 void run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE(Block) )
61 {
62 
63   typedef boost::dynamic_bitset<Block> bitset_type;
64   typedef bitset_test<bitset_type> Tests;
65 
66   //=====================================================================
67   // Test stream operator<<
68   {
69 
70     // The test "variables" are: the stream type and its state, the
71     // exception mask, the width, the fill char and the padding side (left/right)
72 
73     std::ios::iostate masks[] = {
74                                   std::ios::goodbit,
75                                   std::ios::eofbit,
76                                   std::ios::failbit,
77                                   std::ios::eofbit | std::ios::failbit
78                                 };
79 
80     static std::string strings[] = {
81                                   std::string(""),
82                                   std::string("0"),
83                                   std::string("1"),
84                                   std::string("11100"),
85                                   get_long_string()
86                                 };
87 
88     char fill_chars[] =         { '*', 'x', ' ' };
89 
90     std::size_t num_masks   = sizeof(masks) / sizeof(masks[0]);
91     std::size_t num_strings = sizeof(strings) / sizeof(strings[0]);
92     std::size_t num_chars   = sizeof(fill_chars) / sizeof(fill_chars[0]);
93 
94     std::fstream not_good_stream("dynamic_bitset_tests - this file shouldn't exist",
95                                  std::ios::in);
96 
97 
98     for (std::size_t mi = 0; mi < num_masks; ++mi) {
99       for (std::size_t si = 0; si < num_strings; ++si) {
100 
101         std::streamsize slen = (std::streamsize)(strings[si].length());
102 
103         assert( (std::numeric_limits<std::streamsize>::max)()
104                  >=(std::streamsize)(1+slen*2) );
105 
106         for (std::size_t ci = 0; ci < num_chars; ++ci) {
107 
108           // note how "negative widths" are tested too
109           const std::streamsize widths[] = { -1 - slen/2, 0, slen/2, 1 + slen*2 };
110           std::size_t num_widths = sizeof(widths) / sizeof(widths[0]);
111 
112           for (std::size_t wi = 0; wi < num_widths; ++wi) {
113             std::streamsize w = widths[wi];
114             {
115               // test 0 - stream !good()
116               if(not_good_stream.good())
117                   throw std::logic_error("Error in operator << tests"
118                                          " - please, double check");
119               bitset_type b(strings[si]);
120               not_good_stream.width(w);
121               not_good_stream.fill(fill_chars[ci]);
122               try { not_good_stream.exceptions(masks[mi]); } catch(...) {}
123 
124               Tests::stream_inserter(b, not_good_stream, "<unused_string>");
125             }
126             {
127               // test 1a - file stream
128               scoped_temp_file stf;
129               bitset_type b(strings[si]);
130               std::ofstream file(stf.path().string().c_str(), std::ios::trunc);
131               file.width(w);
132               file.fill(fill_chars[ci]);
133               file.exceptions(masks[mi]);
134               Tests::stream_inserter(b, file, stf.path().string().c_str());
135             }
136             {
137               //NOTE: there are NO string stream tests
138             }
139 #if !defined (BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS)
140             {
141               // test 1b - wide file stream
142               scoped_temp_file stf;
143               bitset_type b(strings[si]);
144               std::wofstream file(stf.path().string().c_str());
145               file.width(w);
146               file.fill(fill_chars[ci]);
147               file.exceptions(masks[mi]);
148               Tests::stream_inserter(b, file, stf.path().string().c_str());
149             }
150 #endif
151           }
152         }
153       }
154     } // for (; mi..)
155 
156   }
157 
158   //=====================================================================
159   // Test stream operator>>
160   {
161 
162   // The test "variables" are: the stream type, the exception mask,
163   // the actual contents (and/or state) of the stream, and width.
164   //
165   // With few exceptions, each test case consists of writing a different
166   // assortment of digits and "whitespaces" to a text stream and then checking
167   // that what was written gets read back unchanged. That's NOT guaranteed by
168   // the standard, unless the assortment always ends with a '\n' and satisfies
169   // other conditions (see C99, 7.19.2/2), however it works in practice and is
170   // a good "real life" test. Some characters, such as '\v' and '\f', are not
171   // used exactly because they are the ones which will most likely give problems
172   // on some systems (for instance '\f' could actually be written as a sequence
173   // of new-lines, and we could never be able to read it back)
174   //
175   // Note how the bitset object is not initially empty. That helps checking
176   // that it isn't erroneously clear()ed by operator>>.
177 
178 
179   std::ios::iostate masks[] = {
180                                 std::ios::goodbit,
181                                 std::ios::eofbit,
182                                 std::ios::failbit,
183                                 std::ios::eofbit | std::ios::failbit
184                               };
185 
186   const std::string spaces = "\t\n "; //"\t\n\v\f ";
187 
188   const std::string long_string = get_long_string();
189   /*const*/ static std::string strings[] = {
190                   // NOTE: "const" gives the usual problems with Borland
191                   //       (in Tests::stream_extractor instantiation)
192 
193 
194 #if !(defined BOOST_BORLANDC     \
195       && BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)))
196                                         // Borland 5.5.1 with RW library crashes
197             // empty string
198             std::string(""),
199             // no bitset
200             spaces,
201 #endif
202             // no bitset
203             std::string("x"),
204             std::string("\t  xyz"),
205 
206             // bitset of size 1
207             std::string("0"),
208             std::string("1"),
209 
210             std::string("  0  "),
211             std::string("  1  "),
212             spaces + "1",
213             "1" + spaces,
214             spaces + "1" + spaces,
215             std::string("  x1x  "),
216             std::string("  1x  "),
217 
218             // long bitset
219             long_string,
220             "  " + long_string + " xyz",
221             spaces + long_string,
222             spaces + long_string + spaces
223     };
224 
225 
226   //-----------------------------------------------------
227 
228   std::stringstream not_good_stream;
229   not_good_stream << "test";
230   std::string sink;
231   not_good_stream >> sink; // now the stream should be in eof state
232 
233   const std::size_t num_masks = sizeof(masks) / sizeof(masks[0]);
234   const std::size_t num_strings = sizeof(strings) / sizeof(strings[0]);
235 
236   for (std::size_t mi = 0; mi < num_masks; ++mi) {
237     for (std::size_t si = 0; si < num_strings; ++si) {
238 
239       const std::streamsize slen = (std::streamsize)(strings[si].length());
240       assert((std::numeric_limits<std::streamsize>::max)() >= (std::streamsize)(1+slen*2));
241 
242       std::streamsize widths[] = { -1, 0, slen/2, slen, 1 + slen*2 };
243       std::size_t num_widths = sizeof(widths) / sizeof(widths[0]);
244 
245       for(std::size_t wi = 0; wi < num_widths; ++wi) {
246         const std::streamsize w = widths[wi];
247 
248         // test 0 - !good() stream
249         {
250           if(not_good_stream.good())
251             throw std::logic_error("Error in operator >> tests"
252                                    " - please, double check");
253           bitset_type b(1, 15ul); // note: b is not empty
254           not_good_stream.width(w);
255           try { not_good_stream.exceptions(masks[mi]); } catch(...) {}
256           std::string irrelevant;
257           Tests::stream_extractor(b, not_good_stream, irrelevant);
258         }
259         // test 1a - (narrow) file stream
260         {
261           scoped_temp_file stf;
262           bitset_type b(1, 255ul);
263           {
264             std::ofstream f(stf.path().string().c_str());
265             f << strings[si];
266           }
267 
268           std::ifstream f(stf.path().string().c_str());
269           f.width(w);
270           f.exceptions(masks[mi]);
271           Tests::stream_extractor(b, f, strings[si]);
272         }
273 #if !defined(BOOST_NO_STRINGSTREAM)
274         // test 2a - stringstream
275         {
276           bitset_type b(1, 255ul);
277           std::istringstream stream(strings[si]);
278           stream.width(w);
279           stream.exceptions(masks[mi]);
280           Tests::stream_extractor(b, stream, strings[si]);
281         }
282 #endif
283 
284 #if !defined(BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS)
285         // test 1b - wchar_t file stream
286         {
287           scoped_temp_file stf;
288           std::wstring wstr = widen_string(strings[si]);
289           bitset_type b(1, 255ul);
290           {
291             std::basic_ofstream<wchar_t> of(stf.path().string().c_str());
292             of << wstr;
293           }
294 
295           std::basic_ifstream<wchar_t> f(stf.path().string().c_str());
296           f.width(w);
297           f.exceptions(masks[mi]);
298           Tests::stream_extractor(b, f, wstr);
299         }
300         // test 2b - wstringstream
301         {
302           bitset_type b(1, 255ul);
303           std::wstring wstr = widen_string(strings[si]);
304 
305           std::wistringstream wstream(wstr);
306           wstream.width(w);
307           wstream.exceptions(masks[mi]);
308           Tests::stream_extractor(b, wstream, wstr);
309         }
310 #endif // BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
311 
312       }
313     }
314 
315   } // for ( mi = 0; ...)
316 
317 
318   }
319   //=====================================================================
320   // << Any other tests go here >>
321   //         .....
322 
323 }
324 
325 
326 int
main()327 main()
328 {
329   run_test_cases<unsigned char>();
330   run_test_cases<unsigned short>();
331   run_test_cases<unsigned int>();
332   run_test_cases<unsigned long>();
333 # ifdef BOOST_HAS_LONG_LONG
334   run_test_cases< ::boost::ulong_long_type>();
335 # endif
336 
337   return boost::report_errors();
338 }
339