in cpp-ch/local-engine/Storages/Serializations/ExcelNumberReader.h [156:331]
inline bool readExcelFloatTextFastImpl(T & x, DB::ReadBuffer & in, bool has_quote, const DB::FormatSettings & settings)
{
static_assert(std::is_same_v<T, double> || std::is_same_v<T, float>, "Argument for readFloatTextImpl must be float or double");
static_assert('a' > '.' && 'A' > '.' && '\n' < '.' && '\t' < '.' && '\'' < '.' && '"' < '.', "Layout of char is not like ASCII");
const UInt8 MAX_HEAD_SKIP = 2;
const UInt8 MAX_TAIL_SKIP = 2;
UInt8 head_skip = 0;
UInt8 tail_skip = 0;
bool negative = false;
x = 0;
UInt64 before_point = 0;
UInt64 after_point = 0;
int after_point_exponent = 0;
int exponent = 0;
if (in.eof())
return false;
while (!in.eof())
{
if ((*in.position() < '0' || *in.position() > '9') && *in.position() != '-' && *in.position() != '+' && *in.position() != '.'
&& !checkMoneySymbol(in))
{
if (!((static_cast<UInt8>(*in.position()) & 0b11000000u) == 0b10000000u)) // learn from UTF8Helpers.h
{
head_skip++;
if (head_skip > MAX_HEAD_SKIP)
return false;
}
++in.position();
}
else
break ;
}
if (*in.position() == '-')
{
negative = true;
++in.position();
}
else if (*in.position() == '+')
++in.position();
auto count_after_sign = in.count();
constexpr int significant_digits = std::numeric_limits<UInt64>::digits10;
if (!local_engine::readUIntTextUpToNSignificantDigits<significant_digits, true>(before_point, in, has_quote, settings))
return false;
size_t read_digits = in.count() - count_after_sign;
if (unlikely(read_digits > significant_digits))
{
int before_point_additional_exponent = static_cast<int>(read_digits) - significant_digits;
x = static_cast<T>(shift10(before_point, before_point_additional_exponent));
}
else
{
x = before_point;
}
if (checkChar('.', in))
{
auto after_point_count = in.count();
while (!in.eof() && *in.position() == '0')
++in.position();
auto after_leading_zeros_count = in.count();
int after_point_num_leading_zeros = static_cast<int>(after_leading_zeros_count - after_point_count);
local_engine::readUIntTextUpToNSignificantDigits<significant_digits>(after_point, in, has_quote, settings);
read_digits = in.count() - after_leading_zeros_count;
after_point_exponent
= (read_digits > significant_digits ? -significant_digits : static_cast<int>(-read_digits)) - after_point_num_leading_zeros;
}
if (checkChar('e', in) || checkChar('E', in))
{
if (in.eof())
return false;
bool exponent_negative = false;
if (*in.position() == '-')
{
exponent_negative = true;
++in.position();
}
else if (*in.position() == '+')
{
++in.position();
}
local_engine::readUIntTextUpToNSignificantDigits<4>(exponent, in, has_quote, settings);
if (exponent_negative)
exponent = -exponent;
}
if (!(*in.position() >= '0' && *in.position() <= '9')) // process suffix
{
while (!in.eof())
{
if(*in.position() == settings.csv.delimiter ||*in.position() == '\'' ||*in.position() == '\"'
|| *in.position() == '\n' || *in.position() == '\r')
{
break;
}
if (!((static_cast<UInt8>(*in.position()) & 0b11000000u) == 0b10000000u)) // learn from UTF8Helpers.h
{
tail_skip++;
if (tail_skip>MAX_TAIL_SKIP)
return false;
}
++in.position();
}
}
if (after_point)
x += static_cast<T>(shift10(after_point, after_point_exponent));
if (exponent)
x = static_cast<T>(shift10(x, exponent));
if (negative)
x = -x;
auto num_characters_without_sign = in.count() - count_after_sign;
/// Denormals. At most one character is read before denormal and it is '-'.
if (num_characters_without_sign == 0)
{
if (in.eof())
return false;
if (*in.position() == '+')
{
++in.position();
if (in.eof())
return false;
else if (negative)
return false;
}
if (*in.position() == 'i' || *in.position() == 'I')
{
if (assertOrParseInfinity<false>(in))
{
x = std::numeric_limits<T>::infinity();
if (negative)
x = -x;
return true;
}
return false;
}
else if (*in.position() == 'n' || *in.position() == 'N')
{
if (assertOrParseNaN<false>(in))
{
x = std::numeric_limits<T>::quiet_NaN();
if (negative)
x = -x;
return true;
}
return false;
}
}
return true;
}