diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 9a3bbfc..dacfbae 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -381,6 +381,38 @@ void BaseExpression::char_to_hex(char c, pt::TextStream & stream) } +void BaseExpression::char_to_hex(wchar_t c, pt::TextStream & stream) +{ + unsigned int z = static_cast(c); + + char_to_hex((char)(unsigned char)(z >> 24), stream); + char_to_hex((char)(unsigned char)(z >> 16), stream); + char_to_hex((char)(unsigned char)(z >> 8), stream); + char_to_hex((char)(unsigned char)(z), stream); +} + + + +/* + * return true if the val character was escaped and put (or ignored) to the stream + * + */ +bool BaseExpression::esc_char(char val, pt::TextStream & stream) +{ + return esc_char((wchar_t)(unsigned char)val, stream); +} + + +/* + * return true if the val character was escaped and put (or ignored) to the stream + * + * in most caces you have to provide your own esc_char(wchar_t val, pt::TextStream & stream) method + * + */ +bool BaseExpression::esc_char(wchar_t val, pt::TextStream & stream) +{ + return false; +} void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_type) @@ -391,7 +423,10 @@ void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_typ } else { - stream << val; + if( !esc_char(val, stream) ) + { + stream << val; + } } } @@ -404,48 +439,46 @@ void BaseExpression::esc(unsigned char val, pt::TextStream & stream, const FT & void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_type) { - if( field_type.use_utf8() ) + if( field_type.is_binary() || field_type.is_hexadecimal() ) { - char utf8_buf[10]; - - // FIXME surrogate pairs are not used - size_t utf8_len = pt::int_to_utf8((int)val, utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) - { - esc(utf8_buf[a], stream, field_type); - } + char_to_hex(val, stream); } else { - esc(static_cast(val), stream, field_type); + if( field_type.use_utf8() ) + { + if( !esc_char(val, stream) ) + { + stream << val; + } + } + else + { + char val_char = (char)(unsigned char)val; + + if( !esc_char(val_char, stream) ) + { + stream << val_char; + } + } } } void BaseExpression::esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) { - if( field_type.use_utf8() ) + for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) { - char utf8_buf[10]; - - for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) - { - // FIXME surrogate pairs are not used - size_t utf8_len = pt::int_to_utf8((int)val[i], utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) - { - esc(utf8_buf[a], stream, field_type); - } - } + esc(val[i], stream, field_type); } - else +} + + +void BaseExpression::esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) +{ + for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) { - for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) - { - esc(static_cast(val[i]), stream, field_type); - } + esc(val[i], stream, field_type); } } @@ -464,19 +497,13 @@ void BaseExpression::esc(const wchar_t * val, pt::TextStream & stream, const FT void BaseExpression::esc(const std::string & val, pt::TextStream & stream, const FT & field_type) { - for(size_t i = 0 ; i < val.size() ; ++i) - { - esc(val[i], stream, field_type); - } + esc(val.c_str(), true, val.size(), stream, field_type); } void BaseExpression::esc(const char * val, pt::TextStream & stream, const FT & field_type) { - for(size_t i = 0 ; val[i] != 0 ; ++i) - { - esc(val[i], stream, field_type); - } + esc(val, false, 0, stream, field_type); } diff --git a/src/baseexpression.h b/src/baseexpression.h index 5bdfb3d..fe119d3 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -275,9 +275,11 @@ public: * esc for: signed char, wchar_t, char16_t, char32_t * */ + virtual bool esc_char(char val, pt::TextStream & stream); + virtual bool esc_char(wchar_t val, pt::TextStream & stream); + virtual void esc(char val, pt::TextStream & stream, const FT & field_type = FT::default_type); virtual void esc(unsigned char val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(wchar_t val, pt::TextStream & stream, const FT & field_type = FT::default_type); virtual void esc(const std::wstring & val, pt::TextStream & stream, const FT & field_type = FT::default_type); @@ -298,7 +300,6 @@ public: virtual void esc(float val, pt::TextStream & stream, const FT & field_type = FT::default_type); virtual void esc(double val, pt::TextStream & stream, const FT & field_type = FT::default_type); virtual void esc(long double val, pt::TextStream & stream, const FT & field_type = FT::default_type); - //virtual void esc(void* val, pt::TextStream & stream); virtual void esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type = FT::default_type); virtual void esc(const pt::TextStream & val,pt::TextStream & stream, const FT & field_type = FT::default_type); @@ -628,8 +629,10 @@ protected: char char_to_hex_part(char c); void char_to_hex(char c, pt::TextStream & stream); + void char_to_hex(wchar_t c, pt::TextStream & stream); - void esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type = FT::default_type); + void esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type); + void esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type); bool is_empty_field(const wchar_t * value); }; diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index bc1169d..1cbeb27 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -313,7 +313,7 @@ void DbConnector::allocate_default_expression_if_needed() } -char DbConnector::unescape_hex_char_part(char hex) +unsigned int DbConnector::unescape_hex_char_part(char hex) { if( hex>='0' && hex<='9' ) { @@ -348,43 +348,79 @@ char DbConnector::unescape_hex_char_part(char hex) } -char DbConnector::unescape_hex_char(char char1, char char2) -{ - int c1 = unescape_hex_char_part(char1); - int c2 = unescape_hex_char_part(char2); - return static_cast(((c1 << 4) | c2)); +const char * DbConnector::unescape_hex_char(const char * str, size_t len, unsigned int & res) +{ + unsigned int c; + res = 0; + + for(size_t i = 0 ; i < len ; ++i) + { + if( *str != 0 ) + { + c = unescape_hex_char_part(*str); + str += 1; + } + else + { + c = 0; + } + + res = (res << 4) | c; + } + + return str; +} + + +void DbConnector::unescape_hex_char(const char * str, char & c) +{ + unsigned int res = 0; + unescape_hex_char(str, sizeof(char) * 2, res); + c = (char)res; +} + + +void DbConnector::unescape_hex_char(const char * str, wchar_t & c) +{ + unsigned int res = 0; + unescape_hex_char(str, sizeof(wchar_t) * 2, res); + c = (wchar_t)res; +} + + +void DbConnector::unescape_bin_char(const char * str, char & c) +{ + unescape_hex_char(str, c); +} + + +void DbConnector::unescape_bin_char(const char * str, wchar_t & c) +{ + unescape_hex_char(str, c); } void DbConnector::unescape_hex_string(const char * str, std::string & out) { - for(size_t i=0 ; str[i] != 0 ; i+=2 ) + unsigned int c = 0; + + while( *str != 0 ) { - out += unescape_hex_char(str[i], str[i+1]); + str = unescape_hex_char(str, sizeof(char) * 2, c); + out += (char)c; } } -void DbConnector::unescape_hex_string(const char * str, std::wstring & out, const FT & field_type) +void DbConnector::unescape_hex_string(const char * str, std::wstring & out) { - if( field_type.use_utf8() ) - { - size_t len; - wchar_t c; + unsigned int c = 0; - while( *str != 0 && (len = unescape_hex_char(str, c, field_type)) > 0 ) - { - out += c; - str += len; - } - } - else + while( *str != 0 ) { - for(size_t i=0 ; str[i] != 0 ; i+=2 ) - { - out += static_cast(static_cast(unescape_hex_char(str[i], str[i+1]))); - } + str = unescape_hex_char(str, sizeof(wchar_t) * 2, c); + out += (wchar_t)c; } } @@ -395,151 +431,53 @@ void DbConnector::unescape_bin_string(const char * str, std::string & out) } -void DbConnector::unescape_bin_string(const char * str, std::wstring & out, const FT & field_type) +void DbConnector::unescape_bin_string(const char * str, std::wstring & out) { - unescape_hex_string(str, out, field_type); -} - - -// returns how many characters have been provided to utf8_str buffer -// min size of utf8_str should be 5 bytes (max 4 bytes for utf8 sequence + terminating null) -size_t DbConnector::unescape_hex_char(const char * value_str, char * utf8_str, size_t utf8_str_max_len) -{ - size_t value_str_index = 0; - size_t utf8_str_index = 0; - - utf8_str[0] = 0; - - while( utf8_str_index + 1 < utf8_str_max_len ) - { - if( value_str[value_str_index] != 0 && value_str[value_str_index+1] != 0 ) - { - utf8_str[utf8_str_index] = unescape_hex_char(value_str[value_str_index], value_str[value_str_index+1]); - utf8_str[utf8_str_index+1] = 0; - } - else - { - break; - } - - value_str_index += 2; - utf8_str_index += 1; - } - - return utf8_str_index; -} - - -// CHECKME need to be tested -// returns how many characters were used from value_str -size_t DbConnector::unescape_hex_char(const char * value_str, wchar_t & field_value, const FT & field_type) -{ - size_t len = 0; - - if( field_type.use_utf8() ) - { - char utf8_str[4 + 1]; // max utf8 sequence length + terminating zero - size_t utf8_str_len = unescape_hex_char(value_str, utf8_str, sizeof(utf8_str) / sizeof(char)); - - int value_int; - bool is_correct; - len = pt::utf8_to_int(utf8_str, utf8_str_len, value_int, is_correct); - len = len * 2; - - if( is_correct ) - { - field_value = static_cast(value_int); - } - else - { - if( log ) - { - (*log) << pt::Log::log2 << "Morm: incorrect utf-8 sequence (ignoring)" << pt::Log::logend; - } - } - } - else - { - if( value_str[0] != 0 && value_str[1] != 0 ) - { - field_value = static_cast(static_cast(unescape_hex_char(value_str[0], value_str[1]))); - len = 2; - } - else - { - if( log ) - { - (*log) << pt::Log::log2 << "Morm: unexpected end of string (ignoring)" << pt::Log::logend; - } - } - } - - return len; -} - - -size_t DbConnector::unescape_bin_char(const char * value_str, wchar_t & field_value, const FT & field_type) -{ - return unescape_hex_char(value_str, field_value, field_type); + unescape_hex_string(str, out); } -// CHECKME need to be tested void DbConnector::get_value(const char * value_str, char & field_value, const FT & field_type) { - wchar_t c; - - field_value = 0; - get_value(value_str, c, field_type); - - if( field_type.use_utf8() ) + if( field_type.is_hexadecimal() ) { - if( c <= 127 ) - { - field_value = static_cast(c); - } - else - { - if( log ) - { - (*log) << pt::Log::log2 << "Morm: a character greater than 127 cannot be stored in char type, code point: " - << (int)c << " '" << c << "'" << pt::Log::logend; - } - } + unescape_hex_char(value_str, field_value); + } + else + if( field_type.is_binary() ) + { + unescape_bin_char(value_str, field_value); } else { - field_value = static_cast(c); + field_value = *value_str; } } -// CHECKME need to be tested void DbConnector::get_value(const char * value_str, unsigned char & field_value, const FT & field_type) { char tmp_char; get_value(value_str, tmp_char, field_type); - field_value = static_cast(tmp_char); } -// CHECKME need to be tested void DbConnector::get_value(const char * value_str, wchar_t & field_value, const FT & field_type) { field_value = 0; - if( field_type.is_binary() ) - { - unescape_bin_char(value_str, field_value, field_type); - } - else if( field_type.is_hexadecimal() ) { - unescape_hex_char(value_str, field_value, field_type); + unescape_hex_char(value_str, field_value); + } + else + if( field_type.is_binary() ) + { + unescape_bin_char(value_str, field_value); } else { @@ -556,7 +494,7 @@ void DbConnector::get_value(const char * value_str, wchar_t & field_value, const } else { - // report an error? + field_value = 0xFFFD; // U+FFFD "replacement character"; } } else @@ -568,48 +506,18 @@ void DbConnector::get_value(const char * value_str, wchar_t & field_value, const -// CHECKME need to be tested -void DbConnector::get_value(const char * value_str, std::wstring & field_value, const FT & field_type) -{ - if( field_type.is_binary() ) - { - unescape_bin_string(value_str, field_value, field_type); - } - else - if( field_type.is_hexadecimal() ) - { - unescape_hex_string(value_str, field_value, field_type); - } - else - { - if( field_type.use_utf8() ) - { - pt::utf8_to_wide(value_str, field_value); - } - else - { - for(size_t i=0 ; value_str[i] != 0 ; ++i) - { - field_value += static_cast(value_str[i]); - } - } - } -} - - -// CHECKME need to be tested void DbConnector::get_value(const char * value_str, std::string & field_value, const FT & field_type) { - if( field_type.is_binary() ) - { - unescape_bin_string(value_str, field_value); - } - else if( field_type.is_hexadecimal() ) { unescape_hex_string(value_str, field_value); } else + if( field_type.is_binary() ) + { + unescape_bin_string(value_str, field_value); + } + else { field_value = value_str; } @@ -622,6 +530,34 @@ void DbConnector::get_value(const char * value_str, std::string_view & field_val } +void DbConnector::get_value(const char * value_str, std::wstring & field_value, const FT & field_type) +{ + if( field_type.is_hexadecimal() ) + { + unescape_hex_string(value_str, field_value); + } + else + if( field_type.is_binary() ) + { + unescape_bin_string(value_str, field_value); + } + else + { + if( field_type.use_utf8() ) + { + pt::utf8_to_wide(value_str, field_value); + } + else + { + for(size_t i=0 ; value_str[i] != 0 ; ++i) + { + field_value += static_cast((unsigned char)value_str[i]); + } + } + } +} + + void DbConnector::get_value(const char * value_str, bool & field_value, const FT & field_type) { // IMPROVE ME diff --git a/src/dbconnector.h b/src/dbconnector.h index e4ffffd..5d7807b 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,25 +92,25 @@ public: virtual bool query_remove(const pt::TextStream & stream, QueryResult & query_result); virtual void get_value(const char * value_str, char & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, unsigned char & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned char & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, wchar_t & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, std::wstring & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, std::string & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, std::string_view & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, bool & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, short & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, short & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, unsigned short & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, int & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, unsigned int & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, long & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, unsigned long & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, long long & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned long & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, long long & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, unsigned long long & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, float & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, float & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, double & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, long double & field_value, const FT & field_type = FT::default_type); virtual void get_value(const char * value_str, pt::Date & field_value, const FT & field_type = FT::default_type); - virtual void get_value(const char * value_str, pt::Space & field_value, const FT & field_type = FT::default_type); + virtual void get_value(const char * value_str, pt::Space & field_value, const FT & field_type = FT::default_type); // add get_value for pt::TextStream and pt::WTextStream @@ -149,20 +149,23 @@ protected: virtual const char * query_last_sequence(const wchar_t * sequence_table_name); + virtual void unescape_hex_char(const char * str, char & c); + virtual void unescape_hex_char(const char * str, wchar_t & c); + + virtual void unescape_bin_char(const char * str, char & c); + virtual void unescape_bin_char(const char * str, wchar_t & c); + virtual void unescape_hex_string(const char * str, std::string & out); - virtual void unescape_hex_string(const char * str, std::wstring & out, const FT & field_type); + virtual void unescape_hex_string(const char * str, std::wstring & out); virtual void unescape_bin_string(const char * str, std::string & out); - virtual void unescape_bin_string(const char * str, std::wstring & out, const FT & field_type); + virtual void unescape_bin_string(const char * str, std::wstring & out); - virtual size_t unescape_hex_char(const char * value_str, char * utf8_str, size_t utf8_str_max_len); - virtual size_t unescape_hex_char(const char * value_str, wchar_t & field_value, const FT & field_type); - virtual size_t unescape_bin_char(const char * value_str, wchar_t & field_value, const FT & field_type); private: - char unescape_hex_char_part(char hex); - char unescape_hex_char(char char1, char char2); + unsigned int unescape_hex_char_part(char hex); + const char * unescape_hex_char(const char * str, size_t len, unsigned int & res); diff --git a/src/ft.h b/src/ft.h index d725ea0..4afa38d 100644 --- a/src/ft.h +++ b/src/ft.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2021, Tomasz Sowa + * Copyright (c) 2021-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,7 +58,7 @@ public: no_fetchable = 32, /* not supported yet */ no_removable = 64, raw_field_name = 128, - dont_use_utf8 = 256, + dont_use_utf8 = 256, /* used only with wchar_t and std::wstring, ignored if binary or hexadecimal flags are used */ hexadecimal = 512, binary = 1024, json = 2048, diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index f2e67b2..bdc278d 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -135,19 +135,13 @@ void JSONExpression::after_field_value_list() } -void JSONExpression::esc(char val, pt::TextStream & stream, const FT & field_type) +bool JSONExpression::esc_char(wchar_t val, pt::TextStream & stream) { - if( field_type.is_hexadecimal() || field_type.is_binary() ) - { - char_to_hex(val, stream); - } - else - { - pt::esc_to_json(val, stream); - } + return pt::try_esc_to_json(val, stream); } + void JSONExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type) { bool pretty_print = field_type.is_pretty_print(); @@ -160,6 +154,7 @@ void JSONExpression::esc(const pt::Space & space, pt::TextStream & stream, const } else { + // when serializing as json put it directly without escaping space.serialize_to_json_stream(stream, pretty_print); } } diff --git a/src/jsonexpression.h b/src/jsonexpression.h index df91520..88407b0 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ protected: // 'morm::JSONExpression::esc' hides overloaded virtual function [-Woverloaded-virtual] using FlatExpression::esc; - void esc(char val, pt::TextStream & stream, const FT & field_type); + bool esc_char(wchar_t val, pt::TextStream & stream); private: diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index 1a6422b..dc9f2a0 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -559,17 +559,28 @@ void PostgreSQLConnector::log_unsupported_bin_format() } - -size_t PostgreSQLConnector::unescape_bin_char(const char * str, wchar_t & field_value, const FT & field_type) +void PostgreSQLConnector::unescape_bin_char(const char * str, char & field_value) { if( str[0]!='\\' || str[1]!='x' ) { log_unsupported_bin_format(); - return 0; } else { - return unescape_hex_char(str + 2, field_value, field_type); + DbConnector::unescape_bin_char(str + 2, field_value); + } +} + + +void PostgreSQLConnector::unescape_bin_char(const char * str, wchar_t & field_value) +{ + if( str[0]!='\\' || str[1]!='x' ) + { + log_unsupported_bin_format(); + } + else + { + DbConnector::unescape_bin_char(str + 2, field_value); } } @@ -583,12 +594,12 @@ void PostgreSQLConnector::unescape_bin_string(const char * str, std::string & ou } else { - unescape_hex_string(str + 2, out); + DbConnector::unescape_bin_string(str + 2, out); } } -void PostgreSQLConnector::unescape_bin_string(const char * str, std::wstring & out, const FT & field_type) +void PostgreSQLConnector::unescape_bin_string(const char * str, std::wstring & out) { if( str[0]!='\\' || str[1]!='x' ) { @@ -596,7 +607,7 @@ void PostgreSQLConnector::unescape_bin_string(const char * str, std::wstring & o } else { - unescape_hex_string(str + 2, out, field_type); + DbConnector::unescape_bin_string(str + 2, out); } } diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h index 9f21165..f15d4b5 100644 --- a/src/postgresqlconnector.h +++ b/src/postgresqlconnector.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -100,9 +100,11 @@ protected: void log_unsupported_bin_format(); - size_t unescape_bin_char(const char * str, wchar_t & field_value, const FT & field_type); + void unescape_bin_char(const char * str, char & field_value); + void unescape_bin_char(const char * str, wchar_t & field_value); + void unescape_bin_string(const char * str, std::string & out); - void unescape_bin_string(const char * str, std::wstring & out, const FT & field_type); + void unescape_bin_string(const char * str, std::wstring & out); }; diff --git a/src/postgresqlexpression.cpp b/src/postgresqlexpression.cpp index c9b4ccd..5167b9c 100644 --- a/src/postgresqlexpression.cpp +++ b/src/postgresqlexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,26 +63,27 @@ void PostgreSQLExpression::after_field_value_string(const FT & field_type) } - -void PostgreSQLExpression::esc(char val, pt::TextStream & stream, const FT & field_type) +bool PostgreSQLExpression::esc_char(wchar_t val, pt::TextStream & stream) { - if( field_type.is_hexadecimal() || field_type.is_binary() ) + if( val == '\\' ) { - char_to_hex(val, stream); + stream << "\\\\"; + return true; } else + if( val == '\'' ) { - switch( val ) - { - case '\\': stream << "\\\\"; break; - case '\'': stream << "\\\'"; break; // don't use "''" because we use the method for PQconnectdb too - default: - if( val != 0 ) - { - stream << val; - } - } + stream << "\\\'"; // don't use "''" because we use the method for PQconnectdb too + return true; } + else + if( val == 0 ) + { + // may put the replacement character to the stream? + return true; + } + + return false; } diff --git a/src/postgresqlexpression.h b/src/postgresqlexpression.h index d3c8346..568a14b 100644 --- a/src/postgresqlexpression.h +++ b/src/postgresqlexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2021, Tomasz Sowa + * Copyright (c) 2018-2022, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,6 @@ class PostgreSQLExpression : public DbExpression { public: - void esc(char val, pt::TextStream & stream, const FT & field_type); void esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type); DbExpression & page(pt::TextStream & stream, size_t page_number, size_t page_size); @@ -61,6 +60,7 @@ private: void before_field_value_string(const FT & field_type); void after_field_value_string(const FT & field_type); + bool esc_char(wchar_t val, pt::TextStream & stream); };