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

482 lines
12 KiB
C
Raw Normal View History

2011-03-04 20:58:19 +00:00
#ifndef MYSQLXX_MANIP_H
#define MYSQLXX_MANIP_H
#include <cstring>
#include <iostream>
2011-03-04 20:58:19 +00:00
#include <mysqlxx/Types.h>
2011-03-09 20:11:29 +00:00
#include <mysqlxx/Row.h>
#include <mysqlxx/Null.h>
2011-03-04 20:58:19 +00:00
namespace mysqlxx
{
2011-03-18 20:26:54 +00:00
/** @brief Манипулятор ostream, который escape-ит строки для записи в tab delimited файл.
* Использование: tab_separated_ostr << mysqlxx::escape << x;
*/
2011-03-04 20:58:19 +00:00
enum escape_enum
{
escape
};
/** @brief Манипулятор ostream, который quote-ит строки для записи в MySQL запрос.
* Внимание! Не использует функции MySQL API, а использует свой метод quote-инга,
2011-03-18 20:26:54 +00:00
* который может быть некорректным при использовании некоторых кодировок
2011-03-04 20:58:19 +00:00
* (multi-byte attack), а также может оказаться некорректным при изменении libmysqlclient.
* Это сделано для увеличения производительности и это имеет значение.
2011-03-18 20:26:54 +00:00
*
* Использование: query << mysqlxx::quote << x;
2011-03-04 20:58:19 +00:00
*/
enum quote_enum
{
quote
};
struct EscapeManipResult
{
std::ostream & ostr;
EscapeManipResult(std::ostream & ostr_) : ostr(ostr_) {}
std::ostream & operator<< (bool value) { return ostr << value; }
std::ostream & operator<< (char value) { return ostr << value; }
std::ostream & operator<< (unsigned char value) { return ostr << value; }
std::ostream & operator<< (signed char value) { return ostr << value; }
std::ostream & operator<< (short value) { return ostr << value; }
std::ostream & operator<< (unsigned short value) { return ostr << value; }
std::ostream & operator<< (int value) { return ostr << value; }
std::ostream & operator<< (unsigned int value) { return ostr << value; }
std::ostream & operator<< (long value) { return ostr << value; }
std::ostream & operator<< (unsigned long value) { return ostr << value; }
std::ostream & operator<< (float value) { return ostr << value; }
std::ostream & operator<< (double value) { return ostr << value; }
std::ostream & operator<< (long long value) { return ostr << value; }
std::ostream & operator<< (unsigned long long value) { return ostr << value; }
2011-03-16 14:47:51 +00:00
std::ostream & operator<< (Date value) { return ostr << value; }
std::ostream & operator<< (DateTime value) { return ostr << value; }
2011-03-04 20:58:19 +00:00
std::ostream & operator<< (const std::string & value)
{
writeEscapedData(value.data(), value.length());
return ostr;
}
std::ostream & operator<< (const char * value)
{
while (const char * it = std::strpbrk(value, "\t\n\\"))
{
ostr.write(value, it - value);
switch (*it)
{
case '\t':
ostr.write("\\t", 2);
break;
case '\n':
ostr.write("\\n", 2);
break;
case '\\':
ostr.write("\\\\", 2);
break;
default:
;
}
value = it + 1;
}
return ostr << value;
}
2011-03-09 20:11:29 +00:00
std::ostream & operator<< (const String & string)
{
writeEscapedData(string.data(), string.size());
return ostr;
}
std::ostream & operator<< (const Row & row)
{
for (size_t i = 0; i < row.size(); ++i)
{
if (i != 0)
ostr << '\t';
if (row[i].isNull())
{
ostr << "\\N";
continue;
}
(*this) << row[i];
}
return ostr;
}
template <typename T>
std::ostream & operator<< (const Null<T> & value)
{
if(value.is_null)
{
ostr << "\\N";
}
else
{
*this << value.data;
}
return ostr ;
}
2011-03-09 20:11:29 +00:00
2011-03-04 20:58:19 +00:00
private:
void writeEscapedData(const char * data, size_t length)
{
size_t i = 0;
while (true)
{
size_t remaining_length = std::strlen(data);
(*this) << data;
if (i + remaining_length == length)
break;
ostr.write("\\0", 2);
i += remaining_length + 1;
data += remaining_length + 1;
}
}
};
inline EscapeManipResult operator<< (std::ostream & ostr, escape_enum manip)
{
return EscapeManipResult(ostr);
}
struct QuoteManipResult
{
public:
std::ostream & ostr;
QuoteManipResult(std::ostream & ostr_) : ostr(ostr_) {}
std::ostream & operator<< (bool value) { return ostr << value; }
std::ostream & operator<< (char value) { return ostr << value; }
std::ostream & operator<< (unsigned char value) { return ostr << value; }
std::ostream & operator<< (signed char value) { return ostr << value; }
std::ostream & operator<< (short value) { return ostr << value; }
std::ostream & operator<< (unsigned short value) { return ostr << value; }
std::ostream & operator<< (int value) { return ostr << value; }
std::ostream & operator<< (unsigned int value) { return ostr << value; }
std::ostream & operator<< (long value) { return ostr << value; }
std::ostream & operator<< (unsigned long value) { return ostr << value; }
std::ostream & operator<< (float value) { return ostr << value; }
std::ostream & operator<< (double value) { return ostr << value; }
std::ostream & operator<< (long long value) { return ostr << value; }
std::ostream & operator<< (unsigned long long value) { return ostr << value; }
2011-03-16 14:47:51 +00:00
std::ostream & operator<< (Date value) { return ostr << '\'' << value << '\''; }
std::ostream & operator<< (DateTime value) { return ostr << '\'' << value << '\''; }
2011-03-04 20:58:19 +00:00
std::ostream & operator<< (const std::string & value)
{
ostr.put('\'');
writeEscapedData(value.data(), value.length());
ostr.put('\'');
return ostr;
}
std::ostream & operator<< (const char * value)
{
ostr.put('\'');
writeEscapedCString(value);
ostr.put('\'');
return ostr;
}
template <typename T>
std::ostream & operator<< (const Null<T> & value)
{
if(value.is_null)
{
ostr << "\\N";
}
else
{
*this << value.data;
}
return ostr ;
}
2011-03-04 20:58:19 +00:00
private:
void writeEscapedCString(const char * value)
{
while (const char * it = std::strpbrk(value, "'\\\""))
{
ostr.write(value, it - value);
switch (*it)
{
case '"':
ostr.write("\\\"", 2);
break;
case '\'':
ostr.write("\\'", 2);
break;
case '\\':
ostr.write("\\\\", 2);
break;
default:
;
}
value = it + 1;
}
ostr << value;
}
void writeEscapedData(const char * data, size_t length)
{
size_t i = 0;
while (true)
{
size_t remaining_length = std::strlen(data);
writeEscapedCString(data);
if (i + remaining_length == length)
break;
ostr.write("\\0", 2);
i += remaining_length + 1;
data += remaining_length + 1;
}
}
};
inline QuoteManipResult operator<< (std::ostream & ostr, quote_enum manip)
{
return QuoteManipResult(ostr);
}
/** Манипулятор istream, позволяет считывать значения из tab delimited файла.
*/
enum unescape_enum
{
unescape
};
/** Манипулятор istream, который позволяет читать значения в кавычках или без.
*/
enum unquote_enum
{
unquote
};
inline void parseEscapeSequence(std::istream & istr, std::string & value)
{
char c = istr.get();
if (!istr.good())
throw Poco::Exception("Cannot parse string: unexpected end of input.");
switch(c)
{
case 'b':
value.push_back('\b');
break;
case 'f':
value.push_back('\f');
break;
case 'n':
value.push_back('\n');
break;
case 'r':
value.push_back('\r');
break;
case 't':
value.push_back('\t');
break;
default:
value.push_back(c);
break;
}
}
struct UnEscapeManipResult
{
std::istream & istr;
UnEscapeManipResult(std::istream & istr_) : istr(istr_) {}
std::istream & operator>> (bool & value) { return istr >> value; }
std::istream & operator>> (char & value) { return istr >> value; }
std::istream & operator>> (unsigned char & value) { return istr >> value; }
std::istream & operator>> (signed char & value) { return istr >> value; }
std::istream & operator>> (short & value) { return istr >> value; }
std::istream & operator>> (unsigned short & value) { return istr >> value; }
std::istream & operator>> (int & value) { return istr >> value; }
std::istream & operator>> (unsigned int & value) { return istr >> value; }
std::istream & operator>> (long & value) { return istr >> value; }
std::istream & operator>> (unsigned long & value) { return istr >> value; }
std::istream & operator>> (float & value) { return istr >> value; }
std::istream & operator>> (double & value) { return istr >> value; }
std::istream & operator>> (long long & value) { return istr >> value; }
std::istream & operator>> (unsigned long long & value) { return istr >> value; }
std::istream & operator>> (std::string & value)
{
value.clear();
char c;
while (1)
{
istr.get(c);
if (!istr.good())
break;
switch (c)
{
case '\\':
parseEscapeSequence(istr, value);
break;
case '\t':
istr.unget();
return istr;
break;
case '\n':
istr.unget();
return istr;
break;
default:
value.push_back(c);
break;
}
}
return istr;
}
/// Чтение NULL-able типа.
template <typename T>
std::istream & operator>> (Null<T> & value)
{
char c;
istr.get(c);
if (c == '\\' && istr.peek() == 'N')
{
value.is_null = true;
istr.ignore();
}
else
{
istr.unget();
value.is_null = false;
*this >> value.data;
}
return istr;
}
std::istream & operator>> (Date & value)
{
std::string s;
(*this) >> s;
value = Date(s);
return istr;
}
std::istream & operator>> (DateTime & value)
{
std::string s;
(*this) >> s;
value = DateTime(s);
return istr;
}
};
inline UnEscapeManipResult operator>> (std::istream & istr, unescape_enum manip)
{
return UnEscapeManipResult(istr);
}
struct UnQuoteManipResult
{
public:
std::istream & istr;
UnQuoteManipResult(std::istream & istr_) : istr(istr_) {}
std::istream & operator>> (bool & value) { return istr >> value; }
std::istream & operator>> (char & value) { return istr >> value; }
std::istream & operator>> (unsigned char & value) { return istr >> value; }
std::istream & operator>> (signed char & value) { return istr >> value; }
std::istream & operator>> (short & value) { return istr >> value; }
std::istream & operator>> (unsigned short & value) { return istr >> value; }
std::istream & operator>> (int & value) { return istr >> value; }
std::istream & operator>> (unsigned int & value) { return istr >> value; }
std::istream & operator>> (long & value) { return istr >> value; }
std::istream & operator>> (unsigned long & value) { return istr >> value; }
std::istream & operator>> (float & value) { return istr >> value; }
std::istream & operator>> (double & value) { return istr >> value; }
std::istream & operator>> (long long & value) { return istr >> value; }
std::istream & operator>> (unsigned long long & value) { return istr >> value; }
std::istream & operator>> (std::string & value)
{
value.clear();
readQuote();
char c;
while (1)
{
istr.get(c);
if (!istr.good())
break;
switch (c)
{
case '\\':
parseEscapeSequence(istr, value);
break;
case '\'':
return istr;
break;
default:
value.push_back(c);
break;
}
}
throw Poco::Exception("Cannot parse string: unexpected end of input.");
}
private:
void readQuote()
{
char c = istr.get();
if (!istr.good())
throw Poco::Exception("Cannot parse string: unexpected end of input.");
if (c != '\'')
throw Poco::Exception("Cannot parse string: missing opening single quote.");
}
};
inline UnQuoteManipResult operator>> (std::istream & istr, unquote_enum manip)
{
return UnQuoteManipResult(istr);
}
2011-03-04 20:58:19 +00:00
}
#endif