mirror of
https://github.com/boostorg/dynamic_bitset.git
synced 2026-01-19 04:12:09 +00:00
312 lines
12 KiB
C++
312 lines
12 KiB
C++
// -----------------------------------------------------------
|
|
// Copyright (c) 2001 Jeremy Siek
|
|
// Copyright (c) 2003-2006, 2025 Gennaro Prota
|
|
//
|
|
// Distributed under 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 "bitset_test.hpp"
|
|
#include "boost/config.hpp"
|
|
#include "boost/config/workaround.hpp"
|
|
#include "boost/dynamic_bitset/dynamic_bitset.hpp"
|
|
#include <assert.h>
|
|
#include <cstddef>
|
|
#include <fstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
#if ! defined( BOOST_NO_STRINGSTREAM )
|
|
# include <sstream>
|
|
#endif
|
|
|
|
#if defined BOOST_NO_STD_WSTRING || defined BOOST_NO_STD_LOCALE
|
|
# define BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
|
|
#endif
|
|
|
|
#if ! defined BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
|
|
std::wstring
|
|
widen_string( const std::string & str, const std::locale & loc = std::locale() )
|
|
{
|
|
std::wstring result;
|
|
const std::string::size_type len = str.length();
|
|
if ( len != 0 ) {
|
|
typedef std::ctype< wchar_t > ct_type;
|
|
typedef std::wstring::traits_type tr_type;
|
|
const ct_type & ct = BOOST_USE_FACET( ct_type, loc );
|
|
|
|
result.resize( len );
|
|
for ( std::size_t i = 0; i < len; ++i )
|
|
tr_type::assign( result[ i ], ct.widen( str[ i ] ) );
|
|
}
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
template< typename Block >
|
|
void
|
|
run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE( Block ) )
|
|
{
|
|
typedef boost::dynamic_bitset< Block > bitset_type;
|
|
typedef bitset_test< bitset_type > Tests;
|
|
|
|
//=====================================================================
|
|
// Test stream operator<<
|
|
{
|
|
// The test "variables" are: the stream type and its state, the
|
|
// exception mask, the width, the fill char and the padding side (left/right)
|
|
|
|
std::ios::iostate masks[] = {
|
|
std::ios::goodbit,
|
|
std::ios::eofbit,
|
|
std::ios::failbit,
|
|
std::ios::eofbit | std::ios::failbit
|
|
};
|
|
|
|
static std::string strings[] = {
|
|
std::string( "" ),
|
|
std::string( "0" ),
|
|
std::string( "1" ),
|
|
std::string( "11100" ),
|
|
get_long_string()
|
|
};
|
|
|
|
char fill_chars[] = { '*', 'x', ' ' };
|
|
|
|
std::size_t num_masks = sizeof( masks ) / sizeof( masks[ 0 ] );
|
|
std::size_t num_strings = sizeof( strings ) / sizeof( strings[ 0 ] );
|
|
std::size_t num_chars = sizeof( fill_chars ) / sizeof( fill_chars[ 0 ] );
|
|
|
|
std::fstream not_good_stream( "dynamic_bitset_tests - this file shouldn't exist", std::ios::in );
|
|
|
|
for ( std::size_t mi = 0; mi < num_masks; ++mi ) {
|
|
for ( std::size_t si = 0; si < num_strings; ++si ) {
|
|
std::streamsize slen = (std::streamsize)( strings[ si ].length() );
|
|
|
|
assert( ( std::numeric_limits< std::streamsize >::max )() >= (std::streamsize)( 1 + slen * 2 ) );
|
|
|
|
for ( std::size_t ci = 0; ci < num_chars; ++ci ) {
|
|
// note how "negative widths" are tested too
|
|
const std::streamsize widths[] = { -1 - slen / 2, 0, slen / 2, 1 + slen * 2 };
|
|
std::size_t num_widths = sizeof( widths ) / sizeof( widths[ 0 ] );
|
|
|
|
for ( std::size_t wi = 0; wi < num_widths; ++wi ) {
|
|
std::streamsize w = widths[ wi ];
|
|
{
|
|
// test 0 - stream !good()
|
|
if ( not_good_stream.good() )
|
|
throw std::logic_error( "Error in operator << tests"
|
|
" - please, double check" );
|
|
bitset_type b( strings[ si ] );
|
|
not_good_stream.width( w );
|
|
not_good_stream.fill( fill_chars[ ci ] );
|
|
try {
|
|
not_good_stream.exceptions( masks[ mi ] );
|
|
} catch ( ... ) {
|
|
}
|
|
|
|
Tests::stream_inserter( b, not_good_stream, "<unused_string>" );
|
|
}
|
|
{
|
|
// test 1a - file stream
|
|
scoped_temp_file stf;
|
|
bitset_type b( strings[ si ] );
|
|
std::ofstream file( stf.path().string().c_str(), std::ios::trunc );
|
|
file.width( w );
|
|
file.fill( fill_chars[ ci ] );
|
|
file.exceptions( masks[ mi ] );
|
|
Tests::stream_inserter( b, file, stf.path().string().c_str() );
|
|
}
|
|
{
|
|
// NOTE: there are NO string stream tests
|
|
}
|
|
#if ! defined( BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS )
|
|
{
|
|
// test 1b - wide file stream
|
|
scoped_temp_file stf;
|
|
bitset_type b( strings[ si ] );
|
|
std::wofstream file( stf.path().string().c_str() );
|
|
file.width( w );
|
|
file.fill( fill_chars[ ci ] );
|
|
file.exceptions( masks[ mi ] );
|
|
Tests::stream_inserter( b, file, stf.path().string().c_str() );
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
} // for (; mi..)
|
|
}
|
|
|
|
//=====================================================================
|
|
// Test stream operator>>
|
|
{
|
|
// The test "variables" are: the stream type, the exception mask,
|
|
// the actual contents (and/or state) of the stream, and width.
|
|
//
|
|
// With few exceptions, each test case consists of writing a different
|
|
// assortment of digits and "whitespaces" to a text stream and then checking
|
|
// that what was written gets read back unchanged. That's NOT guaranteed by
|
|
// the standard, unless the assortment always ends with a '\n' and satisfies
|
|
// other conditions (see C99, 7.19.2/2), however it works in practice and is
|
|
// a good "real life" test. Some characters, such as '\v' and '\f', are not
|
|
// used exactly because they are the ones which will most likely give problems
|
|
// on some systems (for instance '\f' could actually be written as a sequence
|
|
// of new-lines, and we could never be able to read it back)
|
|
//
|
|
// Note how the bitset object is not initially empty. That helps checking
|
|
// that it isn't erroneously clear()ed by operator>>.
|
|
|
|
std::ios::iostate masks[] = {
|
|
std::ios::goodbit,
|
|
std::ios::eofbit,
|
|
std::ios::failbit,
|
|
std::ios::eofbit | std::ios::failbit
|
|
};
|
|
|
|
const std::string spaces = "\t\n "; //"\t\n\v\f ";
|
|
|
|
const std::string long_string = get_long_string();
|
|
const static std::string strings[] = {
|
|
|
|
// empty string
|
|
std::string( "" ),
|
|
// no bitset
|
|
spaces,
|
|
|
|
// no bitset
|
|
std::string( "x" ),
|
|
std::string( "\t xyz" ),
|
|
|
|
// bitset of size 1
|
|
std::string( "0" ),
|
|
std::string( "1" ),
|
|
|
|
std::string( " 0 " ),
|
|
std::string( " 1 " ),
|
|
spaces + "1",
|
|
"1" + spaces,
|
|
spaces + "1" + spaces,
|
|
std::string( " x1x " ),
|
|
std::string( " 1x " ),
|
|
|
|
// long bitset
|
|
long_string,
|
|
" " + long_string + " xyz",
|
|
spaces + long_string,
|
|
spaces + long_string + spaces
|
|
};
|
|
|
|
//-----------------------------------------------------
|
|
|
|
std::stringstream not_good_stream;
|
|
not_good_stream << "test";
|
|
std::string sink;
|
|
not_good_stream >> sink; // now the stream should be in eof state
|
|
|
|
const std::size_t num_masks = sizeof( masks ) / sizeof( masks[ 0 ] );
|
|
const std::size_t num_strings = sizeof( strings ) / sizeof( strings[ 0 ] );
|
|
|
|
for ( std::size_t mi = 0; mi < num_masks; ++mi ) {
|
|
for ( std::size_t si = 0; si < num_strings; ++si ) {
|
|
const std::streamsize slen = (std::streamsize)( strings[ si ].length() );
|
|
assert( ( std::numeric_limits< std::streamsize >::max )() >= (std::streamsize)( 1 + slen * 2 ) );
|
|
|
|
std::streamsize widths[] = { -1, 0, slen / 2, slen, 1 + slen * 2 };
|
|
std::size_t num_widths = sizeof( widths ) / sizeof( widths[ 0 ] );
|
|
|
|
for ( std::size_t wi = 0; wi < num_widths; ++wi ) {
|
|
const std::streamsize w = widths[ wi ];
|
|
|
|
// test 0 - !good() stream
|
|
{
|
|
if ( not_good_stream.good() )
|
|
throw std::logic_error( "Error in operator >> tests"
|
|
" - please, double check" );
|
|
bitset_type b( 1, 15ul ); // note: b is not empty
|
|
not_good_stream.width( w );
|
|
try {
|
|
not_good_stream.exceptions( masks[ mi ] );
|
|
} catch ( ... ) {
|
|
}
|
|
std::string irrelevant;
|
|
Tests::stream_extractor( b, not_good_stream, irrelevant );
|
|
}
|
|
// test 1a - (narrow) file stream
|
|
{
|
|
scoped_temp_file stf;
|
|
bitset_type b( 1, 255ul );
|
|
{
|
|
std::ofstream f( stf.path().string().c_str() );
|
|
f << strings[ si ];
|
|
}
|
|
|
|
std::ifstream f( stf.path().string().c_str() );
|
|
f.width( w );
|
|
f.exceptions( masks[ mi ] );
|
|
Tests::stream_extractor( b, f, strings[ si ] );
|
|
}
|
|
#if ! defined( BOOST_NO_STRINGSTREAM )
|
|
// test 2a - stringstream
|
|
{
|
|
bitset_type b( 1, 255ul );
|
|
std::istringstream stream( strings[ si ] );
|
|
stream.width( w );
|
|
stream.exceptions( masks[ mi ] );
|
|
Tests::stream_extractor( b, stream, strings[ si ] );
|
|
}
|
|
#endif
|
|
|
|
#if ! defined( BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS )
|
|
// test 1b - wchar_t file stream
|
|
{
|
|
scoped_temp_file stf;
|
|
std::wstring wstr = widen_string( strings[ si ] );
|
|
bitset_type b( 1, 255ul );
|
|
{
|
|
std::basic_ofstream< wchar_t > of( stf.path().string().c_str() );
|
|
of << wstr;
|
|
}
|
|
|
|
std::basic_ifstream< wchar_t > f( stf.path().string().c_str() );
|
|
f.width( w );
|
|
f.exceptions( masks[ mi ] );
|
|
Tests::stream_extractor( b, f, wstr );
|
|
}
|
|
// test 2b - wstringstream
|
|
{
|
|
bitset_type b( 1, 255ul );
|
|
std::wstring wstr = widen_string( strings[ si ] );
|
|
|
|
std::wistringstream wstream( wstr );
|
|
wstream.width( w );
|
|
wstream.exceptions( masks[ mi ] );
|
|
Tests::stream_extractor( b, wstream, wstr );
|
|
}
|
|
#endif // BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
|
|
}
|
|
}
|
|
|
|
} // for ( mi = 0; ...)
|
|
}
|
|
//=====================================================================
|
|
// << Any other tests go here >>
|
|
// .....
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
run_test_cases< unsigned char >();
|
|
run_test_cases< unsigned short >();
|
|
run_test_cases< unsigned int >();
|
|
run_test_cases< unsigned long >();
|
|
#ifdef BOOST_HAS_LONG_LONG
|
|
run_test_cases< ::boost::ulong_long_type >();
|
|
#endif
|
|
|
|
return boost::report_errors();
|
|
}
|