ClickHouse/libs/libmysqlxx/include/mysqlxx/String.h

345 lines
7.2 KiB
C
Raw Normal View History

2011-03-03 19:57:34 +00:00
#ifndef MYSQLXX_STRING_H
#define MYSQLXX_STRING_H
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <limits>
2011-03-05 20:47:46 +00:00
#include <Yandex/Common.h>
2011-03-03 19:57:34 +00:00
#include <Yandex/DateLUT.h>
#include <mysqlxx/Types.h>
#include <mysqlxx/Exception.h>
namespace mysqlxx
{
template <typename T>
static void readIntText(T & x, const char * buf, size_t length)
{
bool negative = false;
x = 0;
2011-03-10 20:31:02 +00:00
const char * start = buf;
2011-03-03 19:57:34 +00:00
const char * end = buf + length;
while (buf != end)
{
switch (*buf)
{
case '+':
break;
case '-':
negative = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
x *= 10;
x += *buf - '0';
break;
default:
2011-03-10 20:31:02 +00:00
throw Exception("Cannot parse integer: " + std::string(start, length));
2011-03-03 19:57:34 +00:00
}
++buf;
}
if (negative)
x = -x;
}
/// грубо
template <typename T>
static void readFloatText(T & x, const char * buf, size_t length)
{
bool negative = false;
x = 0;
bool after_point = false;
double power_of_ten = 1;
2011-03-10 20:31:02 +00:00
const char * start = buf;
2011-03-03 19:57:34 +00:00
const char * end = buf + length;
while (buf != end)
{
switch (*buf)
{
case '+':
break;
case '-':
negative = true;
break;
case '.':
after_point = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (after_point)
{
power_of_ten /= 10;
x += (*buf - '0') * power_of_ten;
}
else
{
x *= 10;
x += *buf - '0';
}
break;
case 'e':
case 'E':
{
++buf;
Int32 exponent = 0;
readIntText(exponent, buf, end - buf);
if (exponent == 0)
{
if (negative)
x = -x;
return;
}
else if (exponent > 0)
{
for (Int32 i = 0; i < exponent; ++i)
x *= 10;
if (negative)
x = -x;
return;
}
else
{
for (Int32 i = 0; i < exponent; ++i)
x /= 10;
if (negative)
x = -x;
return;
}
}
case 'i':
case 'I':
x = std::numeric_limits<T>::infinity();
if (negative)
x = -x;
return;
case 'n':
case 'N':
x = std::numeric_limits<T>::quiet_NaN();
return;
default:
2011-03-10 20:31:02 +00:00
throw Exception("Cannot parse floating point number: " + std::string(start, length));
2011-03-03 19:57:34 +00:00
}
++buf;
}
if (negative)
x = -x;
}
class String
{
public:
String(const char * data_, size_t length_) : m_data(data_), m_length(length_)
{
}
2011-03-04 20:58:19 +00:00
bool getBool() const
{
2011-03-05 16:56:30 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
2011-03-04 20:58:19 +00:00
return m_length > 0 && m_data[0] != '0';
}
UInt64 getUInt() const
2011-03-03 19:57:34 +00:00
{
2011-03-05 16:56:30 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
2011-03-03 19:57:34 +00:00
UInt64 res;
readIntText(res, m_data, m_length);
return res;
}
2011-03-04 20:58:19 +00:00
Int64 getInt() const
2011-03-03 19:57:34 +00:00
{
2011-03-10 20:31:02 +00:00
return getIntOrDateTime();
2011-03-03 19:57:34 +00:00
}
2011-03-04 20:58:19 +00:00
double getDouble() const
2011-03-03 19:57:34 +00:00
{
2011-03-05 16:56:30 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
2011-03-03 19:57:34 +00:00
double res;
readFloatText(res, m_data, m_length);
return res;
}
2011-03-10 20:31:02 +00:00
DateTime getDateTime() const
{
return DateTime(data(), size());
}
Date getDate() const
{
return Date(data(), size());
}
std::string getString() const
2011-03-03 19:57:34 +00:00
{
2011-03-05 16:56:30 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
2011-03-10 20:31:02 +00:00
return std::string(m_data, m_length);
}
bool isNull() const
{
return m_data == NULL;
}
/// Для совместимости
bool is_null() const { return isNull(); }
template <typename T> T get() const;
/// Для совместимости
template <typename T> operator T() const { return get<T>(); }
const char * data() const { return m_data; }
size_t length() const { return m_length; }
size_t size() const { return m_length; }
private:
const char * m_data;
size_t m_length;
bool checkDateTime() const
{
return (m_length == 10 || m_length == 19) && m_data[4] == '-' && m_data[7] == '-';
}
time_t getDateTimeImpl() const
{
2011-03-03 19:57:34 +00:00
Yandex::DateLUTSingleton & date_lut = Yandex::DateLUTSingleton::instance();
2011-03-10 20:31:02 +00:00
2011-03-03 19:57:34 +00:00
if (m_length == 10)
{
return date_lut.makeDate(
m_data[0] * 1000 + m_data[1] * 100 + m_data[2] * 10 + m_data[3],
m_data[5] * 10 + m_data[6],
m_data[8] * 10 + m_data[9]);
}
2011-03-05 20:47:46 +00:00
else
2011-03-03 19:57:34 +00:00
{
return date_lut.makeDateTime(
m_data[0] * 1000 + m_data[1] * 100 + m_data[2] * 10 + m_data[3],
m_data[5] * 10 + m_data[6],
m_data[8] * 10 + m_data[9],
m_data[11] * 10 + m_data[12],
m_data[14] * 10 + m_data[15],
m_data[17] * 10 + m_data[18]);
}
}
2011-03-10 20:31:02 +00:00
time_t getDateImpl() const
2011-03-05 16:56:30 +00:00
{
Yandex::DateLUTSingleton & date_lut = Yandex::DateLUTSingleton::instance();
if (m_length == 10 || m_length == 19)
{
return date_lut.makeDate(
m_data[0] * 1000 + m_data[1] * 100 + m_data[2] * 10 + m_data[3],
m_data[5] * 10 + m_data[6],
m_data[8] * 10 + m_data[9]);
}
else
throw Exception("Cannot parse Date: " + getString());
}
2011-03-10 20:31:02 +00:00
Int64 getIntImpl() const
2011-03-03 19:57:34 +00:00
{
2011-03-10 20:31:02 +00:00
Int64 res;
readIntText(res, m_data, m_length);
return res;
2011-03-03 19:57:34 +00:00
}
2011-03-10 20:31:02 +00:00
Int64 getIntOrDateTime() const
2011-03-05 16:56:30 +00:00
{
2011-03-10 20:31:02 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
2011-03-03 19:57:34 +00:00
2011-03-10 20:31:02 +00:00
if (checkDateTime())
return getDateTimeImpl();
else
return getIntImpl();
}
2011-03-03 19:57:34 +00:00
2011-03-10 20:31:02 +00:00
Int64 getIntOrDate() const
2011-03-03 19:57:34 +00:00
{
2011-03-10 20:31:02 +00:00
if (unlikely(isNull()))
throw Exception("Value is NULL");
if (checkDateTime())
return getDateImpl();
else
{
Yandex::DateLUTSingleton & date_lut = Yandex::DateLUTSingleton::instance();
return date_lut.toDate(getIntImpl());
}
2011-03-03 19:57:34 +00:00
}
};
2011-03-05 16:56:30 +00:00
template <> inline bool String::get<bool >() const { return getBool(); }
template <> inline char String::get<char >() const { return getInt(); }
template <> inline signed char String::get<signed char >() const { return getInt(); }
template <> inline unsigned char String::get<unsigned char >() const { return getUInt(); }
template <> inline short String::get<short >() const { return getInt(); }
template <> inline unsigned short String::get<unsigned short >() const { return getUInt(); }
template <> inline int String::get<int >() const { return getInt(); }
template <> inline unsigned int String::get<unsigned int >() const { return getUInt(); }
template <> inline long String::get<long >() const { return getInt(); }
template <> inline unsigned long String::get<unsigned long >() const { return getUInt(); }
template <> inline long long String::get<long long >() const { return getInt(); }
template <> inline unsigned long long String::get<unsigned long long >() const { return getUInt(); }
template <> inline float String::get<float >() const { return getDouble(); }
template <> inline double String::get<double >() const { return getDouble(); }
template <> inline std::string String::get<std::string >() const { return getString(); }
2011-03-10 20:31:02 +00:00
template <> inline Date String::get<Date >() const { return getDate(); }
template <> inline DateTime String::get<DateTime >() const { return getDateTime(); }
2011-03-04 20:58:19 +00:00
2011-03-05 20:47:46 +00:00
template <> inline Yandex::VisitID_t String::get<Yandex::VisitID_t >() const { return Yandex::VisitID_t(getUInt()); }
//template <> inline Date String::get<Date >() const { return getString(); }
template <typename T> inline T String::get() const { return T(*this); }
2011-03-04 20:58:19 +00:00
inline std::ostream & operator<< (std::ostream & ostr, const String & x)
2011-03-03 19:57:34 +00:00
{
return ostr.write(x.data(), x.size());
}
}
#endif