summaryrefslogtreecommitdiff
path: root/boost/test/data/size.hpp
blob: 3e9ba96795d3370d5b114559840d9a338bc65911 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//  (C) Copyright Gennadiy Rozental 2001.
//  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)

//  See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief simple dataset size abstraction (can be infinite)
// ***************************************************************************

#ifndef BOOST_TEST_DATA_SIZE_HPP_102211GER
#define BOOST_TEST_DATA_SIZE_HPP_102211GER

// Boost.Test
#include <boost/test/data/config.hpp>

// STL
#include <iosfwd>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {

// ************************************************************************** //
// **************                    size_t                    ************** //
// ************************************************************************** //

//! Utility for handling the size of a datasets
class size_t {
    struct dummy { void nonnull() {} };
    typedef void (dummy::*safe_bool)();
public:
    // Constructors
    size_t( std::size_t s = 0 )         : m_value( s ), m_infinity( false ) {}
    explicit        size_t( bool )      : m_value( 0 ), m_infinity( true ) {}
    template<typename T>
    size_t( T v )                       : m_value( static_cast<std::size_t>(v) ), m_infinity( false ) {}

    // Access methods
    std::size_t     value() const       { return m_value; }
    bool            is_inf() const      { return m_infinity; }
    operator        safe_bool() const   { return is_inf() || m_value != 0 ? &dummy::nonnull : 0; }

    // Unary operators
    data::size_t    operator--()        { if( !is_inf() ) m_value--; return *this; }
    data::size_t    operator--(int)     { data::size_t res(*this); if( !is_inf() ) m_value--; return res; }
    data::size_t    operator++()        { if( !is_inf() ) m_value++; return *this; }
    data::size_t    operator++(int)     { data::size_t res(*this); if( !is_inf() ) m_value++; return res; }

    // Binary operators
    data::size_t&   operator+=( std::size_t rhs ) { if( !is_inf() ) m_value += rhs; return *this; }
    data::size_t&   operator+=( data::size_t rhs )
    {
        if( !is_inf() ) {
            if( rhs.is_inf() )
                *this = rhs;
            else
                m_value += rhs.value();
        }
        return *this;
    }
    data::size_t&   operator-=( std::size_t rhs ) { if( !is_inf() ) m_value -= rhs; return *this; }
    data::size_t&   operator-=( data::size_t rhs )
    {
        if( !is_inf() ) {
            if( value() < rhs.value() )
                m_value = 0;
            else
                m_value -= rhs.value();
        }
        return *this;
    }

private:
    // Data members
    std::size_t     m_value;
    bool            m_infinity;
};

namespace { const data::size_t BOOST_TEST_DS_INFINITE_SIZE( true ); }

//____________________________________________________________________________//

// Binary operators
inline bool operator>(data::size_t lhs, std::size_t rhs)    { return lhs.is_inf()  || (lhs.value() > rhs); }
inline bool operator>(std::size_t lhs, data::size_t rhs)    { return !rhs.is_inf() && (lhs > rhs.value()); }
inline bool operator>(data::size_t lhs, data::size_t rhs)   { return lhs.is_inf() ^ rhs.is_inf() ? lhs.is_inf() : lhs.value() > rhs.value(); }

inline bool operator>=(data::size_t lhs, std::size_t rhs )  { return lhs.is_inf()  || (lhs.value() >= rhs); }
inline bool operator>=(std::size_t lhs, data::size_t rhs)   { return !rhs.is_inf() && (lhs >= rhs.value()); }
inline bool operator>=(data::size_t lhs, data::size_t rhs)  { return lhs.is_inf() ^ rhs.is_inf() ? lhs.is_inf() : lhs.value() >= rhs.value(); }

inline bool operator<(data::size_t lhs, std::size_t rhs)    { return !lhs.is_inf() && (lhs.value() < rhs); }
inline bool operator<(std::size_t lhs, data::size_t rhs)    { return rhs.is_inf()  || (lhs < rhs.value()); }
inline bool operator<(data::size_t lhs, data::size_t rhs)   { return lhs.is_inf() ^ rhs.is_inf() ? rhs.is_inf() : lhs.value() < rhs.value(); }

inline bool operator<=(data::size_t lhs, std::size_t rhs)   { return !lhs.is_inf() && (lhs.value() <= rhs); }
inline bool operator<=(std::size_t lhs, data::size_t rhs)   { return rhs.is_inf()  || (lhs <= rhs.value()); }
inline bool operator<=(data::size_t lhs, data::size_t rhs)  { return lhs.is_inf() ^ rhs.is_inf() ? rhs.is_inf() : lhs.value() <= rhs.value(); }

inline bool operator==(data::size_t lhs, std::size_t rhs)   { return !lhs.is_inf() && (lhs.value() == rhs); }
inline bool operator==(std::size_t lhs, data::size_t rhs)   { return !rhs.is_inf() && (lhs == rhs.value()); }
inline bool operator==(data::size_t lhs, data::size_t rhs)  { return !(lhs.is_inf() ^ rhs.is_inf()) && lhs.value() == rhs.value(); }

inline bool operator!=(data::size_t lhs, std::size_t rhs)   { return lhs.is_inf() || (lhs.value() != rhs); }
inline bool operator!=(std::size_t lhs, data::size_t rhs)   { return rhs.is_inf() || (lhs != rhs.value()); }
inline bool operator!=(data::size_t lhs, data::size_t rhs)  { return lhs.is_inf() ^ rhs.is_inf() || lhs.value() != rhs.value(); }

inline data::size_t operator+(data::size_t lhs, std::size_t rhs)  { return lhs.is_inf() ? lhs : data::size_t( lhs.value()+rhs ); }
inline data::size_t operator+(std::size_t lhs, data::size_t rhs)  { return rhs.is_inf() ? rhs : data::size_t( lhs+rhs.value() ); }
inline data::size_t operator+(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() || rhs.is_inf() ? data::size_t(true) : data::size_t( lhs.value()+rhs.value() ); }

inline data::size_t operator*(data::size_t lhs, std::size_t rhs)  { return lhs.is_inf() ? lhs : data::size_t( lhs.value()*rhs ); }
inline data::size_t operator*(std::size_t lhs, data::size_t rhs)  { return rhs.is_inf() ? rhs : data::size_t( lhs*rhs.value() ); }
inline data::size_t operator*(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() || rhs.is_inf() ? data::size_t(true) : data::size_t( lhs.value()*rhs.value() ); }

//____________________________________________________________________________//

template<typename CharT1, typename Tr>
inline std::basic_ostream<CharT1,Tr>&
operator<<( std::basic_ostream<CharT1,Tr>& os, data::size_t const& s )
{
    if( s.is_inf() )
        os << "infinity";
    else
        os << s.value();

    return os;
}

//____________________________________________________________________________//

} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_DATA_SIZE_HPP_102211GER