This commit is contained in:
Evgeniy Gatov 2015-08-19 12:15:57 +03:00
commit a8cdd43cc1
2 changed files with 27 additions and 68 deletions

View File

@ -129,20 +129,18 @@ void readIntText(T & x, ReadBuffer & buf)
if (buf.eof()) if (buf.eof())
throwReadAfterEOF(); throwReadAfterEOF();
if (*buf.position() == '-')
{
if (!std::is_signed<T>::value)
return;
negative = true;
++buf.position();
}
else if (*buf.position() == '+')
++buf.position();
while (!buf.eof()) while (!buf.eof())
{ {
switch (*buf.position()) switch (*buf.position())
{ {
case '+':
break;
case '-':
if (std::is_signed<T>::value)
negative = true;
else
return;
break;
case '0': case '0':
case '1': case '1':
case '2': case '2':
@ -218,9 +216,6 @@ void readIntTextUnsafe(T & x, ReadBuffer & buf)
template <typename T> template <typename T>
void readFloatText(T & x, ReadBuffer & buf) void readFloatText(T & x, ReadBuffer & buf)
{ {
/// Если вдруг тут перед каждым return надо будет еще что-то делать, типа домножать на экспоненту -- это можно сделать тут.
#define SCOPE_GUARDED_RETURN do { if (negative) x = -x; return; } while (0)
bool negative = false; bool negative = false;
x = 0; x = 0;
bool after_point = false; bool after_point = false;
@ -229,21 +224,16 @@ void readFloatText(T & x, ReadBuffer & buf)
if (buf.eof()) if (buf.eof())
throwReadAfterEOF(); throwReadAfterEOF();
if (*buf.position() == '-')
{
negative = true;
++buf.position();
}
else if (*buf.position() == '+')
++buf.position();
while (!buf.eof()) while (!buf.eof())
{ {
switch (*buf.position()) switch (*buf.position())
{ {
case '+':
break;
case '-':
negative = true;
break;
case '.': case '.':
if (after_point)
SCOPE_GUARDED_RETURN;
after_point = true; after_point = true;
break; break;
case '0': case '0':
@ -274,18 +264,24 @@ void readFloatText(T & x, ReadBuffer & buf)
Int32 exponent = 0; Int32 exponent = 0;
readIntText(exponent, buf); readIntText(exponent, buf);
x *= exp10(exponent); x *= exp10(exponent);
SCOPE_GUARDED_RETURN; if (negative)
x = -x;
return;
} }
case 'i': case 'i':
++buf.position(); ++buf.position();
assertString("nf", buf); assertString("nf", buf);
x = std::numeric_limits<T>::infinity(); x = std::numeric_limits<T>::infinity();
SCOPE_GUARDED_RETURN; if (negative)
x = -x;
return;
case 'I': case 'I':
++buf.position(); ++buf.position();
assertString("NF", buf); assertString("NF", buf);
x = std::numeric_limits<T>::infinity(); x = std::numeric_limits<T>::infinity();
SCOPE_GUARDED_RETURN; if (negative)
x = -x;
return;
case 'n': case 'n':
++buf.position(); ++buf.position();
assertString("an", buf); assertString("an", buf);
@ -297,13 +293,14 @@ void readFloatText(T & x, ReadBuffer & buf)
x = std::numeric_limits<T>::quiet_NaN(); x = std::numeric_limits<T>::quiet_NaN();
return; return;
default: default:
SCOPE_GUARDED_RETURN; if (negative)
x = -x;
return;
} }
++buf.position(); ++buf.position();
} }
SCOPE_GUARDED_RETURN; if (negative)
x = -x;
#undef SCOPE_GUARDED_RETURN
} }

View File

@ -1,38 +0,0 @@
#include <DB/IO/ReadBuffer.h>
#include <DB/IO/ReadHelpers.h>
#include <iostream>
int main()
{
const char input[] = "1 1.0 10.5 115e2 -5 -5.0 10- 7+8 90-3 .5 127.0.0.1 +1 +1-1";
DB::ReadBuffer buf(const_cast<char *>(input), strlen(input), 0);
Int64 i;
double f;
double Epsilon = 1e-10;
int t = 0;
#define CHECK(x, y) do { DB::readText(x, buf); ++t; if (((x-y) > Epsilon) || (y-x) > Epsilon) return t; buf.ignore();} while (0);
CHECK(i, 1);
CHECK(f, 1.0f);
CHECK(f, 10.5f);
CHECK(f, 115e2);
CHECK(i, -5);
CHECK(f, -5);
CHECK(i, 10);
buf.ignore();
CHECK(i, 7);
buf.ignore(2);
CHECK(i, 90);
buf.ignore(2);
/// Интересный случай: хотим ли мы, чтобы .5 парсилось как 0.5? Вроде бы это уместно.
CHECK(f, 0.5f);
CHECK(f, 127);
buf.ignore(4); // "0.1 "
CHECK(i, 1);
CHECK(i, 1);
#undef CHECK
return 0;
}