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
|
#include <qpdf/QIntC.hh>
#include <stdint.h>
#include <cassert>
#define try_convert(exp_pass, fn, i) \
try_convert_real(#fn "(" #i ")", exp_pass, fn, i)
template <typename From, typename To>
static void try_convert_real(
char const* description, bool exp_pass,
To (*fn)(From const&), From const& i)
{
bool passed = false;
try
{
To result = fn(i);
passed = true;
std::cout << description << ": " << i << " " << result;
}
catch (std::range_error& e)
{
std::cout << description << ": " << e.what();
passed = false;
}
std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl;
}
#define try_range_check(exp_pass, a, b) \
try_range_check_real(#a " + " #b, exp_pass, a, b)
template <typename T>
static void try_range_check_real(
char const* description, bool exp_pass,
T const& a, T const& b)
{
bool passed = false;
try
{
QIntC::range_check(a, b);
std::cout << description << ": okay";
passed = true;
}
catch (std::range_error& e)
{
std::cout << description << ": " << e.what();
passed = false;
}
std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl;
}
#define try_range_check_subtract(exp_pass, a, b) \
try_range_check_subtract_real(#a " - " #b, exp_pass, a, b)
template <typename T>
static void try_range_check_subtract_real(
char const* description, bool exp_pass,
T const& a, T const& b)
{
bool passed = false;
try
{
QIntC::range_check_substract(a, b);
std::cout << description << ": okay";
passed = true;
}
catch (std::range_error& e)
{
std::cout << description << ": " << e.what();
passed = false;
}
std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl;
}
int main()
{
uint32_t u1 = 3141592653U; // Too big for signed type
int32_t i1 = -1153374643; // Same bit pattern as u1
uint64_t ul1 = 1099511627776LL; // Too big for 32-bit
uint64_t ul2 = 12345; // Fits into 32-bit
int32_t i2 = 81; // Fits in char and uchar
signed char c1 = static_cast<signed char>('\xf7'); // Signed value when char
char c2 = 'W'; // char; may be signed or unsigned
// Verify i1 and u1 have same bit pattern
assert(static_cast<uint32_t>(i1) == u1);
// Verify that we can unsafely convert between signed and unsigned char
assert(c1 == static_cast<signed char>(static_cast<unsigned char>(c1)));
try_convert(true, QIntC::to_int<int32_t>, i1);
try_convert(true, QIntC::to_uint<uint32_t>, u1);
try_convert(false, QIntC::to_int<uint32_t>, u1);
try_convert(false, QIntC::to_uint<int32_t>, i1);
try_convert(false, QIntC::to_int<uint64_t>, ul1);
try_convert(true, QIntC::to_int<uint64_t>, ul2);
try_convert(true, QIntC::to_uint<uint64_t>, ul2);
try_convert(true, QIntC::to_offset<uint32_t>, u1);
try_convert(true, QIntC::to_offset<int32_t>, i1);
try_convert(false, QIntC::to_ulonglong<int32_t>, i1);
try_convert(true, QIntC::to_char<int32_t>, i2);
try_convert(true, QIntC::to_uchar<int32_t>, i2);
try_convert(false, QIntC::to_uchar<signed char>, c1);
try_convert(true, QIntC::to_uchar<char>, c2);
try_convert(true, QIntC::to_char<char>, c2);
auto constexpr max_ll = std::numeric_limits<long long>::max();
auto constexpr max_ull = std::numeric_limits<unsigned long long>::max();
auto constexpr min_ll = std::numeric_limits<long long>::min();
auto constexpr max_sc = std::numeric_limits<signed char>::max();
try_range_check(true, 1, 2);
try_range_check(true, -1, 2);
try_range_check(true, -100, -200);
try_range_check(true, max_ll, 0LL);
try_range_check(false, max_ll, 1LL);
try_range_check(true, max_ll, 0LL);
try_range_check(false, max_ll, 1LL);
try_range_check(true, max_ull, 0ULL);
try_range_check(false, max_ull, 1ULL);
try_range_check(true, min_ll, 0LL);
try_range_check(false, min_ll, -1LL);
try_range_check(false, max_sc, max_sc);
try_range_check(true, '!', '#');
try_range_check_subtract(true, 1, 2);
try_range_check_subtract(true, -1, -2);
try_range_check_subtract(true, 1, 10);
try_range_check_subtract(true, -1, -10);
try_range_check_subtract(false, 0LL, min_ll);
try_range_check_subtract(false, 1LL, min_ll);
try_range_check_subtract(true, 0LL, max_ll);
try_range_check_subtract(true, -1LL, max_ll);
try_range_check_subtract(false, -2LL, max_ll);
return 0;
}
|