Skip to content

Commit

Permalink
Inline QIntC functions
Browse files Browse the repository at this point in the history
  • Loading branch information
m-holger authored and jberkenbilt committed Feb 11, 2023
1 parent deb1c33 commit 72bf719
Showing 1 changed file with 84 additions and 48 deletions.
132 changes: 84 additions & 48 deletions include/qpdf/QIntC.hh
Original file line number Diff line number Diff line change
Expand Up @@ -63,183 +63,203 @@ namespace QIntC // QIntC = qpdf Integer Conversion
class IntConverter<From, To, false, false>
{
public:
static To
inline static To
convert(From const& i)
{
// From and To are both unsigned.
if (i > std::numeric_limits<To>::max()) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
<< "-byte unsigned type";
throw std::range_error(msg.str());
error(i);
}
return static_cast<To>(i);
}

static void
error(From i)
{
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
<< "-byte unsigned type";
throw std::range_error(msg.str());
}
};

template <typename From, typename To>
class IntConverter<From, To, true, true>
{
public:
static To
inline static To
convert(From const& i)
{
// From and To are both signed.
if ((i < std::numeric_limits<To>::min()) ||
(i > std::numeric_limits<To>::max())) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
<< "-byte signed type";
throw std::range_error(msg.str());
error(i);
}
return static_cast<To>(i);
}

static void
error(From i)
{
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
<< "-byte signed type";
throw std::range_error(msg.str());
}
};

template <typename From, typename To>
class IntConverter<From, To, true, false>
{
public:
static To
inline static To
convert(From const& i)
{
// From is signed, and To is unsigned. If i > 0, it's safe to
// convert it to the corresponding unsigned type and to
// compare with To's max.
auto ii = static_cast<typename to_u<From>::type>(i);
if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
<< "-byte unsigned type";
throw std::range_error(msg.str());
error(i);
}
return static_cast<To>(i);
}

static void
error(From i)
{
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
<< "-byte unsigned type";
throw std::range_error(msg.str());
}
};

template <typename From, typename To>
class IntConverter<From, To, false, true>
{
public:
static To
inline static To
convert(From const& i)
{
// From is unsigned, and to is signed. Convert To's max to the
// unsigned version of To and compare i against that.
auto maxval = static_cast<typename to_u<To>::type>(
std::numeric_limits<To>::max());
if (i > maxval) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
<< "-byte signed type";
throw std::range_error(msg.str());
error(i);
}
return static_cast<To>(i);
}

static void
error(From i)
{
std::ostringstream msg;
msg.imbue(std::locale::classic());
msg << "integer out of range converting " << i << " from a "
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
<< "-byte signed type";
throw std::range_error(msg.str());
}
};

// Specific converters. The return type of each function must match
// the second template parameter to IntConverter.
template <typename T>
char
inline char
to_char(T const& i)
{
return IntConverter<T, char>::convert(i);
}

template <typename T>
unsigned char
inline unsigned char
to_uchar(T const& i)
{
return IntConverter<T, unsigned char>::convert(i);
}

template <typename T>
short
inline short
to_short(T const& i)
{
return IntConverter<T, short>::convert(i);
}

template <typename T>
unsigned short
inline unsigned short
to_ushort(T const& i)
{
return IntConverter<T, unsigned short>::convert(i);
}

template <typename T>
int
inline int
to_int(T const& i)
{
return IntConverter<T, int>::convert(i);
}

template <typename T>
unsigned int
inline unsigned int
to_uint(T const& i)
{
return IntConverter<T, unsigned int>::convert(i);
}

template <typename T>
size_t
inline size_t
to_size(T const& i)
{
return IntConverter<T, size_t>::convert(i);
}

template <typename T>
qpdf_offset_t
inline qpdf_offset_t
to_offset(T const& i)
{
return IntConverter<T, qpdf_offset_t>::convert(i);
}

template <typename T>
long
inline long
to_long(T const& i)
{
return IntConverter<T, long>::convert(i);
}

template <typename T>
unsigned long
inline unsigned long
to_ulong(T const& i)
{
return IntConverter<T, unsigned long>::convert(i);
}

template <typename T>
long long
inline long long
to_longlong(T const& i)
{
return IntConverter<T, long long>::convert(i);
}

template <typename T>
unsigned long long
inline unsigned long long
to_ulonglong(T const& i)
{
return IntConverter<T, unsigned long long>::convert(i);
}

template <typename T>
void
range_check(T const& cur, T const& delta)
range_check_error(T const& cur, T const& delta)
{
if ((delta > 0) != (cur > 0)) {
return;
}

if ((delta > 0) && ((std::numeric_limits<T>::max() - cur) < delta)) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
Expand All @@ -257,13 +277,19 @@ namespace QIntC // QIntC = qpdf Integer Conversion
}

template <typename T>
void
range_check_substract(T const& cur, T const& delta)
inline void
range_check(T const& cur, T const& delta)
{
if ((delta >= 0) == (cur >= 0)) {
if ((delta > 0) != (cur > 0)) {
return;
}
QIntC::range_check_error<T>(cur, delta);
}

template <typename T>
void
range_check_substract_error(T const& cur, T const& delta)
{
if ((delta > 0) && ((std::numeric_limits<T>::min() + delta) > cur)) {
std::ostringstream msg;
msg.imbue(std::locale::classic());
Expand All @@ -279,6 +305,16 @@ namespace QIntC // QIntC = qpdf Integer Conversion
throw std::range_error(msg.str());
}
}

template <typename T>
inline void
range_check_substract(T const& cur, T const& delta)
{
if ((delta >= 0) == (cur >= 0)) {
return;
}
QIntC::range_check_substract_error<T>(cur, delta);
}
}; // namespace QIntC

#endif // QINTC_HH

0 comments on commit 72bf719

Please sign in to comment.