4368 oracle odbc tests (#4410)

* feat(format): Add string_view format type spec #4409

* chore(Types): add demangle

* fix(Data): Oracle failing ODBC tests #4368

* fix some CQL and fuzz warnings; add Var::typeName()

* fix(build): -std=c++17 and c11

* fix windows build

* fix(Foundation): test apps vs projects c++17

* chore(build): remove uneeded compiler flag

* fix(VarHolder): number of digits range check for int->float conversion (reported by CIFuzz)

* fix(test): CIFuzz

* fix(CIFuzz): another attempt

* fix(progen): add LanguageStandard (stdcpp17, stdc11); regenerate vs170 projects

* fix(CiFuzz): add int->float precision loss barrier; fix erroneous number of digits logic

* enh(Var): silent loss of precision on int->float conversion #4423

* enh(Var): silent loss of precision on int->float conversion #4423

* chore(build): remove old build files

* chore: fix missing parens warning

* enh(Thread_POSIX): prevent double-joining; add error description to exceptions

* fix(Data): unresolved Column<long> linkage in test

* fix(demangle): determine type name from template parameter; add eror diagnostic for demangling failures

* chore(buildwin): remove old vs versions from build and progen scripts; update documentation

* chore(buildwin): remove leftover closing curly
This commit is contained in:
Aleksandar Fabijanic
2024-01-31 22:07:07 +01:00
committed by GitHub
parent bf2f96847a
commit c7d16b2a7e
243 changed files with 7158 additions and 1434 deletions

View File

@@ -475,6 +475,11 @@ public:
const std::type_info& type() const;
/// Returns the type information of the stored content.
std::string typeName(bool demangle = true) const;
/// Returns the type name of the stored content.
/// If demangling is available and emangle is true,
/// the returnsed string will be demangled.
//@ deprecated
void empty();
/// Empties Var.
@@ -521,23 +526,8 @@ public:
/// This function returns 0 when Var is empty, 1 for POD or the size (i.e. length)
/// for held container.
std::string toString() const
std::string toString() const;
/// Returns the stored value as string.
{
VarHolder* pHolder = content();
if (!pHolder)
throw InvalidAccessException("Can not convert empty value.");
if (typeid(std::string) == pHolder->type())
return extract<std::string>();
else
{
std::string result;
pHolder->convert(result);
return result;
}
}
static Var parse(const std::string& val);
/// Parses the string which must be in JSON format
@@ -617,17 +607,8 @@ private:
_placeholder.assign<VarHolderImpl<ValueType>, ValueType>(value);
}
void construct(const char* value)
{
std::string val(value);
_placeholder.assign<VarHolderImpl<std::string>, std::string>(val);
}
void construct(const Var& other)
{
if (!other.isEmpty())
other.content()->clone(&_placeholder);
}
void construct(const char* value);
void construct(const Var& other);
Placeholder<VarHolder> _placeholder;
};
@@ -642,6 +623,20 @@ private:
/// Var members
///
inline void Var::construct(const char* value)
{
std::string val(value);
_placeholder.assign<VarHolderImpl<std::string>, std::string>(val);
}
inline void Var::construct(const Var& other)
{
if (!other.isEmpty())
other.content()->clone(&_placeholder);
}
inline void Var::swap(Var& other)
{
if (this == &other) return;
@@ -674,6 +669,13 @@ inline const std::type_info& Var::type() const
}
inline std::string Var::typeName(bool demangle) const
{
VarHolder* pHolder = content();
return pHolder ? demangle ? Poco::demangle(pHolder->type().name()) : pHolder->type().name() : std::string();
}
inline Var::ConstIterator Var::begin() const
{
if (size() == 0) return ConstIterator(const_cast<Var*>(this), true);

View File

@@ -33,17 +33,27 @@
#include "Poco/UTF8String.h"
#include "Poco/UUID.h"
#include "Poco/Any.h"
#include "Poco/Format.h"
#include "Poco/Debugger.h"
#include "Poco/Exception.h"
#include <vector>
#include <list>
#include <deque>
#include <typeinfo>
#include <type_traits>
#include <string_view>
#undef min
#undef max
#include <limits>
#define POCO_VAR_RANGE_EXCEPTION(str, from) \
throw RangeException(Poco::format("%v ((%s/%d) %s > (%s/%d) %s) @ %s.", \
std::string_view(#str), Poco::demangle<F>(), numValDigits(from), std::to_string(from), \
Poco::demangle<T>(), numTypeDigits<T>(), std::to_string(static_cast<T>(from)), \
poco_src_loc))
namespace Poco {
namespace Dynamic {
@@ -312,140 +322,186 @@ protected:
return pVarHolder->assign<VarHolderImpl<T>, T>(val);
}
template <typename F, typename T>
void convertToSmaller(const F& from, T& to) const
/// This function is meant to convert signed numeric values from
template <typename F, typename T,
typename std::enable_if<(std::is_integral<F>::value && std::is_signed<F>::value) ||
std::is_floating_point<F>::value, F>::type* = nullptr,
typename std::enable_if<(std::is_integral<T>::value && std::is_signed<T>::value) ||
std::is_floating_point<F>::value, T>::type* = nullptr>
static void convertToSmaller(const F& from, T& to)
/// Converts signed integral, as well as floating-point, values from
/// larger to smaller type. It checks the upper and lower bound and
/// if from value is within limits of type T (i.e. check calls do not throw),
/// it is converted.
{
poco_static_assert (std::numeric_limits<F>::is_specialized);
poco_static_assert (std::numeric_limits<T>::is_specialized);
poco_static_assert (std::numeric_limits<F>::is_signed);
poco_static_assert (std::numeric_limits<T>::is_signed);
if constexpr((std::is_integral<F>::value) && (std::is_floating_point<T>::value))
{
if (isPrecisionLost<F, T>(from))
POCO_VAR_RANGE_EXCEPTION ("Lost precision", from);
}
checkUpperLimit<F,T>(from);
checkLowerLimit<F,T>(from);
to = static_cast<T>(from);
}
template <typename F, typename T>
void convertToSmallerUnsigned(const F& from, T& to) const
/// This function is meant for converting unsigned integral data types,
/// from larger to smaller type. Since lower limit is always 0 for unsigned types,
/// only the upper limit is checked, thus saving some cycles compared to the signed
/// version of the function. If the value to be converted is smaller than
/// the maximum value for the target type, the conversion is performed.
template <typename F, typename T,
typename std::enable_if<std::is_integral<F>::value && std::is_signed<T>::value, F>::type* = nullptr,
typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr>
static void convertToSmaller(const F& from, T& to)
/// Converts signed integral values from integral to floating-point type. Checks for
/// the loss of precision and if from value is within limits of type T (i.e. check calls do not throw),
/// it is converted.
{
poco_static_assert (std::numeric_limits<F>::is_specialized);
poco_static_assert (std::numeric_limits<T>::is_specialized);
poco_static_assert (!std::numeric_limits<F>::is_signed);
poco_static_assert (!std::numeric_limits<T>::is_signed);
if (isPrecisionLost<F, T>(from))
POCO_VAR_RANGE_EXCEPTION ("Lost precision", from);
to = static_cast<T>(from);
}
template <typename F, typename T,
typename std::enable_if<std::is_same<F, bool>::value>::type* = nullptr,
typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr>
static void convertToSmaller(const F& from, T& to)
/// Converts boolean values to floating-point type.
{
to = static_cast<T>(from);
}
template <typename F, typename T,
typename std::enable_if<std::is_integral<F>::value && !std::is_signed<F>::value, F>::type* = nullptr,
typename std::enable_if<(std::is_integral<T>::value && !std::is_signed<T>::value) || std::is_floating_point<T>::value, T>::type* = nullptr>
static void convertToSmallerUnsigned(const F& from, T& to)
/// Converts unsigned integral data types from larger to smaller, as well as to floating-point, types.
/// Since lower limit is always 0 for unsigned types, only the upper limit is checked, thus
/// saving some cycles compared to the signed version of the function. If the
/// value to be converted is smaller than the maximum value for the target type,
/// the conversion is performed.
{
checkUpperLimit<F,T>(from);
to = static_cast<T>(from);
}
template <typename F, typename T>
void convertSignedToUnsigned(const F& from, T& to) const
/// This function is meant for converting signed integral data types to
/// unsigned data types. Negative values can not be converted and if one
/// is encountered, RangeException is thrown.
template <typename F, typename T,
typename std::enable_if<std::is_integral<F>::value && std::is_signed<F>::value, F>::type* = nullptr,
typename std::enable_if<std::is_integral<T>::value && !std::is_signed<T>::value, T>::type* = nullptr>
static void convertSignedToUnsigned(const F& from, T& to)
/// Converts signed integral data types to unsigned data types.
/// Negative values can not be converted and if one is encountered, RangeException is thrown.
/// If upper limit is within the target data type limits, the conversion is performed.
{
poco_static_assert (std::numeric_limits<F>::is_specialized);
poco_static_assert (std::numeric_limits<T>::is_specialized);
poco_static_assert (std::numeric_limits<F>::is_signed);
poco_static_assert (!std::numeric_limits<T>::is_signed);
if (from < 0)
throw RangeException("Value too small.");
POCO_VAR_RANGE_EXCEPTION ("Value too small", from);
checkUpperLimit<std::make_unsigned_t<F>,T>(from);
to = static_cast<T>(from);
}
template <typename F, typename T, std::enable_if_t<std::is_floating_point<F>::value, bool> = true>
void convertSignedFloatToUnsigned(const F& from, T& to) const
/// This function is meant for converting floating point data types to
/// unsigned integral data types. Negative values can not be converted and if one
/// is encountered, RangeException is thrown.
template <typename F, typename T, std::enable_if_t<std::is_floating_point<F>::value, bool> = true,
typename std::enable_if<std::is_integral<T>::value && !std::is_signed<T>::value, T>::type* = nullptr>
static void convertSignedFloatToUnsigned(const F& from, T& to)
/// Converts floating point data types to unsigned integral data types. Negative values
/// can not be converted and if one is encountered, RangeException is thrown.
/// If upper limit is within the target data type limits, the conversion is performed.
{
poco_static_assert (std::numeric_limits<F>::is_specialized);
poco_static_assert (std::numeric_limits<T>::is_specialized);
poco_static_assert (!std::numeric_limits<F>::is_integer);
poco_static_assert (std::numeric_limits<T>::is_integer);
poco_static_assert (!std::numeric_limits<T>::is_signed);
if (from < 0)
throw RangeException("Value too small.");
POCO_VAR_RANGE_EXCEPTION ("Value too small", from);
checkUpperLimit<F,T>(from);
to = static_cast<T>(from);
}
template <typename F, typename T>
void convertUnsignedToSigned(const F& from, T& to) const
/// This function is meant for converting unsigned integral data types to
/// signed integral data types. Negative values can not be converted and if one
/// is encountered, RangeException is thrown.
template <typename F, typename T,
typename std::enable_if<std::is_integral<F>::value && !std::is_signed<F>::value, F>::type* = nullptr,
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type* = nullptr>
static void convertUnsignedToSigned(const F& from, T& to)
/// Converts unsigned integral data types to signed integral data types.
/// If upper limit is within the target data type limits, the conversion is performed.
{
poco_static_assert (std::numeric_limits<F>::is_specialized);
poco_static_assert (std::numeric_limits<T>::is_specialized);
poco_static_assert (!std::numeric_limits<F>::is_signed);
poco_static_assert (std::numeric_limits<T>::is_signed);
checkUpperLimit<F,T>(from);
to = static_cast<T>(from);
}
template <typename F, typename T,
std::enable_if_t<std::is_integral<F>::value, bool> = true,
std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
static void convertToFP(F& from, T& to)
/// Converts unsigned integral data types to floating-point data types.
/// If the number of significant digits used for the integer vaue exceeds the number
/// of available digits in the floatinng-point destination (ie. if precision would be lost
/// by casting the value), RangeException is thrown.
{
if (isPrecisionLost<F, T>(from))
POCO_VAR_RANGE_EXCEPTION ("Lost precision", from);
to = static_cast<T>(from);
}
private:
template <typename F, typename T, std::enable_if_t<std::is_integral<F>::value, bool> = true>
void checkUpperLimit(const F& from) const
template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
static constexpr int numValDigits(const T& value)
{
if (from > std::numeric_limits<T>::max())
throw RangeException("Value too large.");
using U = std::make_unsigned_t<T>;
if (value == 0) return 0;
int digitCount = 0;
U locVal = value; // to prevent sign preservation
while (locVal >>= 1) ++digitCount;
return digitCount;
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
static constexpr int numValDigits(T value)
{
return numValDigits<int64_t>(static_cast<int64_t>(value));
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
static constexpr int numTypeDigits()
{
return std::numeric_limits<T>::digits;
}
template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
static constexpr int numTypeDigits()
{
return numValDigits(std::numeric_limits<T>::max());
}
template <typename F, typename T,
std::enable_if_t<std::is_integral<F>::value, bool> = true,
std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
static bool isPrecisionLost(const F& from)
// Checks for loss of precision in integral -> floating point conversion.
{
return numValDigits(from) > numTypeDigits<T>();
}
template <typename F, typename T, std::enable_if_t<std::is_integral<F>::value, bool> = true>
void checkLowerLimit(const F& from) const
static void checkUpperLimit(const F& from)
{
if (from < std::numeric_limits<T>::min())
throw RangeException("Value too small.");
if (from > static_cast<F>(std::numeric_limits<T>::max()))
POCO_VAR_RANGE_EXCEPTION ("Value too big", from);
}
template <typename F, typename T, std::enable_if_t<std::is_integral<F>::value, bool> = true>
static void checkLowerLimit(const F& from)
{
if (from < static_cast<F>(std::numeric_limits<T>::min()))
POCO_VAR_RANGE_EXCEPTION ("Value too small", from);
}
template <typename F, typename T, std::enable_if_t<std::is_floating_point<F>::value, bool> = true>
void checkUpperLimit(const F& from) const
static void checkUpperLimit(const F& from)
{
if (std::is_floating_point<T>::value)
{
if (from > std::numeric_limits<T>::max())
throw RangeException("Value too large.");
}
else
{
// Avoid clang -Wimplicit-int-float-conversion warning with an explicit cast.
if (from > static_cast<F>(std::numeric_limits<T>::max()))
throw RangeException("Value too large.");
}
if ((from > static_cast<F>(std::numeric_limits<T>::max())))
POCO_VAR_RANGE_EXCEPTION ("Value too big", from);
}
template <typename F, typename T, std::enable_if_t<std::is_floating_point<F>::value, bool> = true>
void checkLowerLimit(const F& from) const
static void checkLowerLimit(const F& from)
{
if (std::is_floating_point<T>::value)
if constexpr(std::is_floating_point<T>::value)
{
if (from < -std::numeric_limits<T>::max())
throw RangeException("Value too small.");
}
else
{
// Avoid clang -Wimplicit-int-float-conversion warning with an explicit cast.
if (from < static_cast<F>(std::numeric_limits<T>::min()))
throw RangeException("Value too small.");
if (static_cast<F>(-std::numeric_limits<T>::max()) > from)
POCO_VAR_RANGE_EXCEPTION ("Value too small", from);
}
else if (from < static_cast<F>(std::numeric_limits<T>::min()))
POCO_VAR_RANGE_EXCEPTION ("Value too small", from);
}
};
@@ -828,12 +884,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -984,12 +1040,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1137,12 +1193,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1289,12 +1345,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1456,12 +1512,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1608,12 +1664,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1760,12 +1816,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const
@@ -1912,12 +1968,12 @@ public:
void convert(float& val) const
{
val = static_cast<float>(_val);
convertToFP(_val, val);
}
void convert(double& val) const
{
val = static_cast<double>(_val);
convertToFP(_val, val);
}
void convert(char& val) const