#ifndef MYSQLXX_MANIP_H #define MYSQLXX_MANIP_H #include #include #include #include namespace mysqlxx { /** @brief Манипулятор ostream, который escape-ит строки для записи в tab delimited файл. */ enum escape_enum { escape }; /** @brief Манипулятор ostream, который quote-ит строки для записи в MySQL запрос. * Внимание! Не использует функции MySQL API, а использует свой метод quote-инга, * который может быть некорректным при использовании некоторых японских кодировок * (multi-byte attack), а также может оказаться некорректным при изменении libmysqlclient. * Это сделано для увеличения производительности и это имеет значение. */ 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; } 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; } 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; } 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; } 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 std::ostream & operator<< (const std::pair & pair) { return ostr << quote << pair.first << ',' << quote << pair.second; } template std::ostream & operator<< (const Poco::Tuple & tuple) { return ostr << quote << tuple.template get<0>() << ',' << quote << tuple.template get<1>() << ',' << quote << tuple.template get<2>(); }*/ 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); } } #endif