/src/qpdf/include/qpdf/QIntC.hh
Line | Count | Source |
1 | | // Copyright (c) 2005-2021 Jay Berkenbilt |
2 | | // Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger |
3 | | // |
4 | | // This file is part of qpdf. |
5 | | // |
6 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | // you may not use this file except in compliance with the License. |
8 | | // You may obtain a copy of the License at |
9 | | // |
10 | | // http://www.apache.org/licenses/LICENSE-2.0 |
11 | | // |
12 | | // Unless required by applicable law or agreed to in writing, software |
13 | | // distributed under the License is distributed on an "AS IS" BASIS, |
14 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | // See the License for the specific language governing permissions and |
16 | | // limitations under the License. |
17 | | // |
18 | | // Versions of qpdf prior to version 7 were released under the terms |
19 | | // of version 2.0 of the Artistic License. At your option, you may |
20 | | // continue to consider qpdf to be licensed under those terms. Please |
21 | | // see the manual for additional information. |
22 | | |
23 | | #ifndef QINTC_HH |
24 | | #define QINTC_HH |
25 | | |
26 | | #include <qpdf/DLL.h> |
27 | | #include <qpdf/Types.h> |
28 | | #include <iostream> |
29 | | #include <limits> |
30 | | #include <locale> |
31 | | #include <sstream> |
32 | | #include <stdexcept> |
33 | | #include <type_traits> |
34 | | |
35 | | // This namespace provides safe integer conversion that detects |
36 | | // overflows. It uses short, cryptic names for brevity. |
37 | | |
38 | | namespace QIntC // QIntC = qpdf Integer Conversion |
39 | | { |
40 | | // to_u is here for backward-compatibility from before we required |
41 | | // C++-11. |
42 | | template <typename T> |
43 | | class to_u |
44 | | { |
45 | | public: |
46 | | typedef typename std::make_unsigned<T>::type type; |
47 | | }; |
48 | | |
49 | | // Basic IntConverter class, which converts an integer from the |
50 | | // From class to one of the To class if it can be done safely and |
51 | | // throws a range_error otherwise. This class is specialized for |
52 | | // each permutation of signed/unsigned for the From and To |
53 | | // classes. |
54 | | template < |
55 | | typename From, |
56 | | typename To, |
57 | | bool From_signed = std::numeric_limits<From>::is_signed, |
58 | | bool To_signed = std::numeric_limits<To>::is_signed> |
59 | | class IntConverter |
60 | | { |
61 | | }; |
62 | | |
63 | | template <typename From, typename To> |
64 | | class IntConverter<From, To, false, false> |
65 | | { |
66 | | public: |
67 | | inline static To |
68 | | convert(From const& i) |
69 | 18.7M | { |
70 | | // From and To are both unsigned. |
71 | 18.7M | if (i > std::numeric_limits<To>::max()) { |
72 | 0 | error(i); |
73 | 0 | } |
74 | 18.7M | return static_cast<To>(i); |
75 | 18.7M | } QIntC::IntConverter<unsigned int, unsigned long, false, false>::convert(unsigned int const&) Line | Count | Source | 69 | 66.9k | { | 70 | | // From and To are both unsigned. | 71 | 66.9k | if (i > std::numeric_limits<To>::max()) { | 72 | 0 | error(i); | 73 | 0 | } | 74 | 66.9k | return static_cast<To>(i); | 75 | 66.9k | } |
QIntC::IntConverter<unsigned long, unsigned int, false, false>::convert(unsigned long const&) Line | Count | Source | 69 | 9.77M | { | 70 | | // From and To are both unsigned. | 71 | 9.77M | if (i > std::numeric_limits<To>::max()) { | 72 | 0 | error(i); | 73 | 0 | } | 74 | 9.77M | return static_cast<To>(i); | 75 | 9.77M | } |
QIntC::IntConverter<unsigned long, unsigned long, false, false>::convert(unsigned long const&) Line | Count | Source | 69 | 8.74M | { | 70 | | // From and To are both unsigned. | 71 | 8.74M | if (i > std::numeric_limits<To>::max()) { | 72 | 0 | error(i); | 73 | 0 | } | 74 | 8.74M | return static_cast<To>(i); | 75 | 8.74M | } |
QIntC::IntConverter<unsigned long long, unsigned long, false, false>::convert(unsigned long long const&) Line | Count | Source | 69 | 27.7k | { | 70 | | // From and To are both unsigned. | 71 | 27.7k | if (i > std::numeric_limits<To>::max()) { | 72 | 0 | error(i); | 73 | 0 | } | 74 | 27.7k | return static_cast<To>(i); | 75 | 27.7k | } |
Unexecuted instantiation: QIntC::IntConverter<unsigned long long, unsigned int, false, false>::convert(unsigned long long const&) Unexecuted instantiation: QIntC::IntConverter<unsigned char, unsigned long, false, false>::convert(unsigned char const&) QIntC::IntConverter<unsigned long, unsigned char, false, false>::convert(unsigned long const&) Line | Count | Source | 69 | 87.1k | { | 70 | | // From and To are both unsigned. | 71 | 87.1k | if (i > std::numeric_limits<To>::max()) { | 72 | 0 | error(i); | 73 | 0 | } | 74 | 87.1k | return static_cast<To>(i); | 75 | 87.1k | } |
|
76 | | |
77 | | static void |
78 | | error(From i) |
79 | 0 | { |
80 | 0 | std::ostringstream msg; |
81 | 0 | msg.imbue(std::locale::classic()); |
82 | 0 | msg << "integer out of range converting " << i << " from a " << sizeof(From) |
83 | 0 | << "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type"; |
84 | 0 | throw std::range_error(msg.str()); |
85 | 0 | } Unexecuted instantiation: QIntC::IntConverter<unsigned int, unsigned long, false, false>::error(unsigned int) Unexecuted instantiation: QIntC::IntConverter<unsigned long, unsigned int, false, false>::error(unsigned long) Unexecuted instantiation: QIntC::IntConverter<unsigned long, unsigned long, false, false>::error(unsigned long) Unexecuted instantiation: QIntC::IntConverter<unsigned long long, unsigned long, false, false>::error(unsigned long long) Unexecuted instantiation: QIntC::IntConverter<unsigned long long, unsigned int, false, false>::error(unsigned long long) Unexecuted instantiation: QIntC::IntConverter<unsigned char, unsigned long, false, false>::error(unsigned char) Unexecuted instantiation: QIntC::IntConverter<unsigned long, unsigned char, false, false>::error(unsigned long) |
86 | | }; |
87 | | |
88 | | template <typename From, typename To> |
89 | | class IntConverter<From, To, true, true> |
90 | | { |
91 | | public: |
92 | | inline static To |
93 | | convert(From const& i) |
94 | 4.97M | { |
95 | | // From and To are both signed. |
96 | 4.97M | if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) { |
97 | 1.01k | error(i); |
98 | 1.01k | } |
99 | 4.97M | return static_cast<To>(i); |
100 | 4.97M | } QIntC::IntConverter<long long, int, true, true>::convert(long long const&) Line | Count | Source | 94 | 4.96M | { | 95 | | // From and To are both signed. | 96 | 4.96M | if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) { | 97 | 1.01k | error(i); | 98 | 1.01k | } | 99 | 4.96M | return static_cast<To>(i); | 100 | 4.96M | } |
Unexecuted instantiation: QIntC::IntConverter<double, int, true, true>::convert(double const&) QIntC::IntConverter<long, int, true, true>::convert(long const&) Line | Count | Source | 94 | 6.97k | { | 95 | | // From and To are both signed. | 96 | 6.97k | if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) { | 97 | 0 | error(i); | 98 | 0 | } | 99 | 6.97k | return static_cast<To>(i); | 100 | 6.97k | } |
Unexecuted instantiation: QIntC::IntConverter<long long, long, true, true>::convert(long long const&) Unexecuted instantiation: QIntC::IntConverter<long, long long, true, true>::convert(long const&) |
101 | | |
102 | | static void |
103 | | error(From i) |
104 | 1.01k | { |
105 | 1.01k | std::ostringstream msg; |
106 | 1.01k | msg.imbue(std::locale::classic()); |
107 | 1.01k | msg << "integer out of range converting " << i << " from a " << sizeof(From) |
108 | 1.01k | << "-byte signed type to a " << sizeof(To) << "-byte signed type"; |
109 | 1.01k | throw std::range_error(msg.str()); |
110 | 1.01k | } QIntC::IntConverter<long long, int, true, true>::error(long long) Line | Count | Source | 104 | 1.01k | { | 105 | 1.01k | std::ostringstream msg; | 106 | 1.01k | msg.imbue(std::locale::classic()); | 107 | 1.01k | msg << "integer out of range converting " << i << " from a " << sizeof(From) | 108 | 1.01k | << "-byte signed type to a " << sizeof(To) << "-byte signed type"; | 109 | 1.01k | throw std::range_error(msg.str()); | 110 | 1.01k | } |
Unexecuted instantiation: QIntC::IntConverter<double, int, true, true>::error(double) Unexecuted instantiation: QIntC::IntConverter<long, int, true, true>::error(long) Unexecuted instantiation: QIntC::IntConverter<long long, long, true, true>::error(long long) Unexecuted instantiation: QIntC::IntConverter<long, long long, true, true>::error(long) |
111 | | }; |
112 | | |
113 | | template <typename From, typename To> |
114 | | class IntConverter<From, To, true, false> |
115 | | { |
116 | | public: |
117 | | inline static To |
118 | | convert(From const& i) |
119 | 7.30M | { |
120 | | // From is signed, and To is unsigned. If i > 0, it's safe to |
121 | | // convert it to the corresponding unsigned type and to |
122 | | // compare with To's max. |
123 | 7.30M | auto ii = static_cast<typename to_u<From>::type>(i); |
124 | 7.30M | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { |
125 | 0 | error(i); |
126 | 0 | } |
127 | 7.30M | return static_cast<To>(i); |
128 | 7.30M | } QIntC::IntConverter<long long, unsigned long, true, false>::convert(long long const&) Line | Count | Source | 119 | 2.65M | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 2.65M | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 2.65M | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 2.65M | return static_cast<To>(i); | 128 | 2.65M | } |
QIntC::IntConverter<long, unsigned long, true, false>::convert(long const&) Line | Count | Source | 119 | 2.32M | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 2.32M | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 2.32M | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 2.32M | return static_cast<To>(i); | 128 | 2.32M | } |
QIntC::IntConverter<int, unsigned int, true, false>::convert(int const&) Line | Count | Source | 119 | 306k | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 306k | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 306k | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 306k | return static_cast<To>(i); | 128 | 306k | } |
QIntC::IntConverter<int, unsigned long, true, false>::convert(int const&) Line | Count | Source | 119 | 1.47M | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 1.47M | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 1.47M | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 1.47M | return static_cast<To>(i); | 128 | 1.47M | } |
QIntC::IntConverter<long long, unsigned long long, true, false>::convert(long long const&) Line | Count | Source | 119 | 79.8k | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 79.8k | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 79.8k | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 79.8k | return static_cast<To>(i); | 128 | 79.8k | } |
QIntC::IntConverter<int, unsigned long long, true, false>::convert(int const&) Line | Count | Source | 119 | 461k | { | 120 | | // From is signed, and To is unsigned. If i > 0, it's safe to | 121 | | // convert it to the corresponding unsigned type and to | 122 | | // compare with To's max. | 123 | 461k | auto ii = static_cast<typename to_u<From>::type>(i); | 124 | 461k | if ((i < 0) || (ii > std::numeric_limits<To>::max())) { | 125 | 0 | error(i); | 126 | 0 | } | 127 | 461k | return static_cast<To>(i); | 128 | 461k | } |
Unexecuted instantiation: QIntC::IntConverter<char, unsigned long, true, false>::convert(char const&) Unexecuted instantiation: QIntC::IntConverter<int, unsigned char, true, false>::convert(int const&) Unexecuted instantiation: QIntC::IntConverter<int, unsigned short, true, false>::convert(int const&) |
129 | | |
130 | | static void |
131 | | error(From i) |
132 | 0 | { |
133 | 0 | std::ostringstream msg; |
134 | 0 | msg.imbue(std::locale::classic()); |
135 | 0 | msg << "integer out of range converting " << i << " from a " << sizeof(From) |
136 | 0 | << "-byte signed type to a " << sizeof(To) << "-byte unsigned type"; |
137 | 0 | throw std::range_error(msg.str()); |
138 | 0 | } Unexecuted instantiation: QIntC::IntConverter<long long, unsigned long, true, false>::error(long long) Unexecuted instantiation: QIntC::IntConverter<long, unsigned long, true, false>::error(long) Unexecuted instantiation: QIntC::IntConverter<int, unsigned int, true, false>::error(int) Unexecuted instantiation: QIntC::IntConverter<int, unsigned long, true, false>::error(int) Unexecuted instantiation: QIntC::IntConverter<long long, unsigned long long, true, false>::error(long long) Unexecuted instantiation: QIntC::IntConverter<int, unsigned long long, true, false>::error(int) Unexecuted instantiation: QIntC::IntConverter<char, unsigned long, true, false>::error(char) Unexecuted instantiation: QIntC::IntConverter<int, unsigned char, true, false>::error(int) Unexecuted instantiation: QIntC::IntConverter<int, unsigned short, true, false>::error(int) |
139 | | }; |
140 | | |
141 | | template <typename From, typename To> |
142 | | class IntConverter<From, To, false, true> |
143 | | { |
144 | | public: |
145 | | inline static To |
146 | | convert(From const& i) |
147 | 6.42M | { |
148 | | // From is unsigned, and to is signed. Convert To's max to the |
149 | | // unsigned version of To and compare i against that. |
150 | 6.42M | auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max()); |
151 | 6.42M | if (i > maxval) { |
152 | 29 | error(i); |
153 | 29 | } |
154 | 6.42M | return static_cast<To>(i); |
155 | 6.42M | } QIntC::IntConverter<unsigned long, long long, false, true>::convert(unsigned long const&) Line | Count | Source | 147 | 5.91M | { | 148 | | // From is unsigned, and to is signed. Convert To's max to the | 149 | | // unsigned version of To and compare i against that. | 150 | 5.91M | auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max()); | 151 | 5.91M | if (i > maxval) { | 152 | 0 | error(i); | 153 | 0 | } | 154 | 5.91M | return static_cast<To>(i); | 155 | 5.91M | } |
QIntC::IntConverter<unsigned long, int, false, true>::convert(unsigned long const&) Line | Count | Source | 147 | 510k | { | 148 | | // From is unsigned, and to is signed. Convert To's max to the | 149 | | // unsigned version of To and compare i against that. | 150 | 510k | auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max()); | 151 | 510k | if (i > maxval) { | 152 | 29 | error(i); | 153 | 29 | } | 154 | 510k | return static_cast<To>(i); | 155 | 510k | } |
|
156 | | |
157 | | static void |
158 | | error(From i) |
159 | 29 | { |
160 | 29 | std::ostringstream msg; |
161 | 29 | msg.imbue(std::locale::classic()); |
162 | 29 | msg << "integer out of range converting " << i << " from a " << sizeof(From) |
163 | 29 | << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; |
164 | 29 | throw std::range_error(msg.str()); |
165 | 29 | } Unexecuted instantiation: QIntC::IntConverter<unsigned long, long long, false, true>::error(unsigned long) QIntC::IntConverter<unsigned long, int, false, true>::error(unsigned long) Line | Count | Source | 159 | 29 | { | 160 | 29 | std::ostringstream msg; | 161 | 29 | msg.imbue(std::locale::classic()); | 162 | 29 | msg << "integer out of range converting " << i << " from a " << sizeof(From) | 163 | 29 | << "-byte unsigned type to a " << sizeof(To) << "-byte signed type"; | 164 | 29 | throw std::range_error(msg.str()); | 165 | 29 | } |
|
166 | | }; |
167 | | |
168 | | // Specific converters. The return type of each function must match |
169 | | // the second template parameter to IntConverter. |
170 | | template <typename T> |
171 | | inline char |
172 | | to_char(T const& i) |
173 | | { |
174 | | return IntConverter<T, char>::convert(i); |
175 | | } |
176 | | |
177 | | template <typename T> |
178 | | inline unsigned char |
179 | | to_uchar(T const& i) |
180 | 87.1k | { |
181 | 87.1k | return IntConverter<T, unsigned char>::convert(i); |
182 | 87.1k | } Unexecuted instantiation: unsigned char QIntC::to_uchar<int>(int const&) unsigned char QIntC::to_uchar<unsigned long>(unsigned long const&) Line | Count | Source | 180 | 87.1k | { | 181 | 87.1k | return IntConverter<T, unsigned char>::convert(i); | 182 | 87.1k | } |
|
183 | | |
184 | | template <typename T> |
185 | | inline short |
186 | | to_short(T const& i) |
187 | | { |
188 | | return IntConverter<T, short>::convert(i); |
189 | | } |
190 | | |
191 | | template <typename T> |
192 | | inline unsigned short |
193 | | to_ushort(T const& i) |
194 | 0 | { |
195 | 0 | return IntConverter<T, unsigned short>::convert(i); |
196 | 0 | } |
197 | | |
198 | | template <typename T> |
199 | | inline int |
200 | | to_int(T const& i) |
201 | 5.48M | { |
202 | 5.48M | return IntConverter<T, int>::convert(i); |
203 | 5.48M | } int QIntC::to_int<unsigned long>(unsigned long const&) Line | Count | Source | 201 | 510k | { | 202 | 510k | return IntConverter<T, int>::convert(i); | 203 | 510k | } |
int QIntC::to_int<long long>(long long const&) Line | Count | Source | 201 | 4.96M | { | 202 | 4.96M | return IntConverter<T, int>::convert(i); | 203 | 4.96M | } |
Unexecuted instantiation: int QIntC::to_int<double>(double const&) int QIntC::to_int<long>(long const&) Line | Count | Source | 201 | 6.97k | { | 202 | 6.97k | return IntConverter<T, int>::convert(i); | 203 | 6.97k | } |
|
204 | | |
205 | | template <typename T> |
206 | | inline unsigned int |
207 | | to_uint(T const& i) |
208 | 10.0M | { |
209 | 10.0M | return IntConverter<T, unsigned int>::convert(i); |
210 | 10.0M | } unsigned int QIntC::to_uint<int>(int const&) Line | Count | Source | 208 | 306k | { | 209 | 306k | return IntConverter<T, unsigned int>::convert(i); | 210 | 306k | } |
unsigned int QIntC::to_uint<unsigned long>(unsigned long const&) Line | Count | Source | 208 | 9.77M | { | 209 | 9.77M | return IntConverter<T, unsigned int>::convert(i); | 210 | 9.77M | } |
Unexecuted instantiation: unsigned int QIntC::to_uint<unsigned long long>(unsigned long long const&) |
211 | | |
212 | | template <typename T> |
213 | | inline size_t |
214 | | to_size(T const& i) |
215 | 6.54M | { |
216 | 6.54M | return IntConverter<T, size_t>::convert(i); |
217 | 6.54M | } unsigned long QIntC::to_size<long long>(long long const&) Line | Count | Source | 215 | 2.65M | { | 216 | 2.65M | return IntConverter<T, size_t>::convert(i); | 217 | 2.65M | } |
unsigned long QIntC::to_size<long>(long const&) Line | Count | Source | 215 | 2.32M | { | 216 | 2.32M | return IntConverter<T, size_t>::convert(i); | 217 | 2.32M | } |
unsigned long QIntC::to_size<unsigned int>(unsigned int const&) Line | Count | Source | 215 | 66.9k | { | 216 | 66.9k | return IntConverter<T, size_t>::convert(i); | 217 | 66.9k | } |
unsigned long QIntC::to_size<int>(int const&) Line | Count | Source | 215 | 1.47M | { | 216 | 1.47M | return IntConverter<T, size_t>::convert(i); | 217 | 1.47M | } |
unsigned long QIntC::to_size<unsigned long>(unsigned long const&) Line | Count | Source | 215 | 486 | { | 216 | 486 | return IntConverter<T, size_t>::convert(i); | 217 | 486 | } |
unsigned long QIntC::to_size<unsigned long long>(unsigned long long const&) Line | Count | Source | 215 | 27.7k | { | 216 | 27.7k | return IntConverter<T, size_t>::convert(i); | 217 | 27.7k | } |
|
218 | | |
219 | | template <typename T> |
220 | | inline qpdf_offset_t |
221 | | to_offset(T const& i) |
222 | 5.91M | { |
223 | 5.91M | return IntConverter<T, qpdf_offset_t>::convert(i); |
224 | 5.91M | } long long QIntC::to_offset<unsigned long>(unsigned long const&) Line | Count | Source | 222 | 5.91M | { | 223 | 5.91M | return IntConverter<T, qpdf_offset_t>::convert(i); | 224 | 5.91M | } |
Unexecuted instantiation: long long QIntC::to_offset<long>(long const&) |
225 | | |
226 | | template <typename T> |
227 | | inline long |
228 | | to_long(T const& i) |
229 | | { |
230 | | return IntConverter<T, long>::convert(i); |
231 | | } |
232 | | |
233 | | template <typename T> |
234 | | inline unsigned long |
235 | | to_ulong(T const& i) |
236 | 8.74M | { |
237 | 8.74M | return IntConverter<T, unsigned long>::convert(i); |
238 | 8.74M | } unsigned long QIntC::to_ulong<unsigned long>(unsigned long const&) Line | Count | Source | 236 | 8.74M | { | 237 | 8.74M | return IntConverter<T, unsigned long>::convert(i); | 238 | 8.74M | } |
Unexecuted instantiation: unsigned long QIntC::to_ulong<char>(char const&) Unexecuted instantiation: unsigned long QIntC::to_ulong<unsigned char>(unsigned char const&) Unexecuted instantiation: unsigned long QIntC::to_ulong<int>(int const&) |
239 | | |
240 | | template <typename T> |
241 | | inline long long |
242 | | to_longlong(T const& i) |
243 | 1.75k | { |
244 | 1.75k | return IntConverter<T, long long>::convert(i); |
245 | 1.75k | } |
246 | | |
247 | | template <typename T> |
248 | | inline unsigned long long |
249 | | to_ulonglong(T const& i) |
250 | 541k | { |
251 | 541k | return IntConverter<T, unsigned long long>::convert(i); |
252 | 541k | } unsigned long long QIntC::to_ulonglong<long long>(long long const&) Line | Count | Source | 250 | 79.8k | { | 251 | 79.8k | return IntConverter<T, unsigned long long>::convert(i); | 252 | 79.8k | } |
unsigned long long QIntC::to_ulonglong<int>(int const&) Line | Count | Source | 250 | 461k | { | 251 | 461k | return IntConverter<T, unsigned long long>::convert(i); | 252 | 461k | } |
|
253 | | |
254 | | template <typename T> |
255 | | void |
256 | | range_check_error(T const& cur, T const& delta) |
257 | 26.1k | { |
258 | 26.1k | if ((delta > 0) && ((std::numeric_limits<T>::max() - cur) < delta)) { |
259 | 48 | std::ostringstream msg; |
260 | 48 | msg.imbue(std::locale::classic()); |
261 | 48 | msg << "adding " << delta << " to " << cur << " would cause an integer overflow"; |
262 | 48 | throw std::range_error(msg.str()); |
263 | 26.0k | } else if ((delta < 0) && ((std::numeric_limits<T>::min() - cur) > delta)) { |
264 | 0 | std::ostringstream msg; |
265 | 0 | msg.imbue(std::locale::classic()); |
266 | 0 | msg << "adding " << delta << " to " << cur << " would cause an integer underflow"; |
267 | 0 | throw std::range_error(msg.str()); |
268 | 0 | } |
269 | 26.1k | } |
270 | | |
271 | | template <typename T> |
272 | | inline void |
273 | | range_check(T const& cur, T const& delta) |
274 | 182k | { |
275 | 182k | if ((delta > 0) != (cur > 0)) { |
276 | 156k | return; |
277 | 156k | } |
278 | 26.1k | QIntC::range_check_error<T>(cur, delta); |
279 | 26.1k | } |
280 | | |
281 | | template <typename T> |
282 | | void |
283 | | range_check_subtract_error(T const& cur, T const& delta) |
284 | | { |
285 | | if ((delta > 0) && ((std::numeric_limits<T>::min() + delta) > cur)) { |
286 | | std::ostringstream msg; |
287 | | msg.imbue(std::locale::classic()); |
288 | | msg << "subtracting " << delta << " from " << cur |
289 | | << " would cause an integer underflow"; |
290 | | throw std::range_error(msg.str()); |
291 | | } else if ((delta < 0) && ((std::numeric_limits<T>::max() + delta) < cur)) { |
292 | | std::ostringstream msg; |
293 | | msg.imbue(std::locale::classic()); |
294 | | msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow"; |
295 | | throw std::range_error(msg.str()); |
296 | | } |
297 | | } |
298 | | |
299 | | template <typename T> |
300 | | inline void |
301 | | range_check_subtract(T const& cur, T const& delta) |
302 | | { |
303 | | if ((delta >= 0) == (cur >= 0)) { |
304 | | return; |
305 | | } |
306 | | QIntC::range_check_subtract_error<T>(cur, delta); |
307 | | } |
308 | | }; // namespace QIntC |
309 | | |
310 | | #endif // QINTC_HH |