diff --git a/src/Makefile.dep b/src/Makefile.dep index 9a673e1..6940b12 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,174 +1,49 @@ # DO NOT DELETE -baseexpression.o: baseexpression.h ../../pikotools/textstream/textstream.h -baseexpression.o: ../../pikotools/space/space.h -baseexpression.o: ../../pikotools/textstream/types.h -baseexpression.o: ../../pikotools/convert/inttostr.h -baseexpression.o: ../../pikotools/date/date.h -baseexpression.o: ../../pikotools/membuffer/membuffer.h -baseexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h -baseexpression.o: modeldata.h cursorhelper.h queryresult.h -baseexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -baseexpression.o: finderhelper.h fieldvaluehelper.h ft.h model.h -baseexpression.o: modelconnector.h clearer.h dbconnector.h flatconnector.h -baseexpression.o: dbexpression.h flatexpression.h ../../pikotools/utf8/utf8.h -baseexpression.o: ../../pikotools/utf8/utf8_templates.h -baseexpression.o: ../../pikotools/utf8/utf8_private.h -clearer.o: clearer.h ../../pikotools/date/date.h -clearer.o: ../../pikotools/convert/inttostr.h ../../pikotools/space/space.h -clearer.o: ../../pikotools/textstream/types.h model.h -clearer.o: ../../pikotools/textstream/textstream.h -clearer.o: ../../pikotools/membuffer/membuffer.h -clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h -clearer.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -clearer.o: queryresult.h flatconnector.h dbexpression.h baseexpression.h -clearer.o: morm_types.h modelenv.h modeldata.h cursorhelper.h finderhelper.h -clearer.o: fieldvaluehelper.h ft.h flatexpression.h -dbconnector.o: ../../pikotools/space/spaceparser.h -dbconnector.o: ../../pikotools/space/space.h -dbconnector.o: ../../pikotools/textstream/types.h -dbconnector.o: ../../pikotools/convert/inttostr.h dbconnector.h -dbconnector.o: ../../pikotools/textstream/textstream.h -dbconnector.o: ../../pikotools/space/space.h ../../pikotools/date/date.h -dbconnector.o: ../../pikotools/membuffer/membuffer.h -dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/log/log.h -dbconnector.o: ../../pikotools/log/filelog.h queryresult.h dbexpression.h +baseexpression.o: baseexpression.h morm_types.h modelenv.h modeldata.h +baseexpression.o: cursorhelper.h queryresult.h finderhelper.h +baseexpression.o: fieldvaluehelper.h ft.h model.h modelconnector.h clearer.h +baseexpression.o: dbconnector.h flatconnector.h dbexpression.h +baseexpression.o: flatexpression.h +clearer.o: clearer.h model.h modelconnector.h dbconnector.h queryresult.h +clearer.o: ft.h flatconnector.h dbexpression.h baseexpression.h morm_types.h +clearer.o: modelenv.h modeldata.h cursorhelper.h finderhelper.h +clearer.o: fieldvaluehelper.h flatexpression.h +dbconnector.o: dbconnector.h queryresult.h ft.h dbexpression.h dbconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h -dbconnector.o: cursorhelper.h finderhelper.h fieldvaluehelper.h ft.h model.h +dbconnector.o: cursorhelper.h finderhelper.h fieldvaluehelper.h model.h dbconnector.o: modelconnector.h clearer.h flatconnector.h flatexpression.h -dbconnector.o: ../../pikotools/utf8/utf8.h -dbconnector.o: ../../pikotools/utf8/utf8_templates.h -dbconnector.o: ../../pikotools/utf8/utf8_private.h -dbconnector.o: ../../pikotools/convert/convert.h -dbconnector.o: ../../pikotools/convert/inttostr.h -dbconnector.o: ../../pikotools/convert/patternreplacer.h -dbconnector.o: ../../pikotools/convert/strtoint.h -dbconnector.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h -dbexpression.o: dbexpression.h baseexpression.h -dbexpression.o: ../../pikotools/textstream/textstream.h -dbexpression.o: ../../pikotools/space/space.h -dbexpression.o: ../../pikotools/textstream/types.h -dbexpression.o: ../../pikotools/convert/inttostr.h -dbexpression.o: ../../pikotools/date/date.h -dbexpression.o: ../../pikotools/membuffer/membuffer.h -dbexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h -dbexpression.o: modeldata.h cursorhelper.h queryresult.h -dbexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -dbexpression.o: finderhelper.h fieldvaluehelper.h ft.h -flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h -flatconnector.o: ../../pikotools/space/space.h -flatconnector.o: ../../pikotools/textstream/types.h -flatconnector.o: ../../pikotools/convert/inttostr.h -flatconnector.o: ../../pikotools/date/date.h -flatconnector.o: ../../pikotools/membuffer/membuffer.h -flatconnector.o: ../../pikotools/textstream/types.h flatexpression.h -flatconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h -flatconnector.o: cursorhelper.h queryresult.h ../../pikotools/log/log.h -flatconnector.o: ../../pikotools/log/filelog.h finderhelper.h -flatconnector.o: fieldvaluehelper.h ft.h model.h modelconnector.h clearer.h -flatconnector.o: dbconnector.h dbexpression.h -flatexpression.o: flatexpression.h baseexpression.h -flatexpression.o: ../../pikotools/textstream/textstream.h -flatexpression.o: ../../pikotools/space/space.h -flatexpression.o: ../../pikotools/textstream/types.h -flatexpression.o: ../../pikotools/convert/inttostr.h -flatexpression.o: ../../pikotools/date/date.h -flatexpression.o: ../../pikotools/membuffer/membuffer.h -flatexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h -flatexpression.o: modeldata.h cursorhelper.h queryresult.h -flatexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -flatexpression.o: finderhelper.h fieldvaluehelper.h ft.h -jsonconnector.o: jsonconnector.h flatconnector.h -jsonconnector.o: ../../pikotools/textstream/textstream.h -jsonconnector.o: ../../pikotools/space/space.h -jsonconnector.o: ../../pikotools/textstream/types.h -jsonconnector.o: ../../pikotools/convert/inttostr.h -jsonconnector.o: ../../pikotools/date/date.h -jsonconnector.o: ../../pikotools/membuffer/membuffer.h -jsonconnector.o: ../../pikotools/textstream/types.h jsonexpression.h +dbexpression.o: dbexpression.h baseexpression.h morm_types.h modelenv.h +dbexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h +dbexpression.o: fieldvaluehelper.h ft.h +flatconnector.o: flatconnector.h flatexpression.h baseexpression.h +flatconnector.o: morm_types.h modelenv.h modeldata.h cursorhelper.h +flatconnector.o: queryresult.h finderhelper.h fieldvaluehelper.h ft.h model.h +flatconnector.o: modelconnector.h clearer.h dbconnector.h dbexpression.h +flatexpression.o: flatexpression.h baseexpression.h morm_types.h modelenv.h +flatexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h +flatexpression.o: fieldvaluehelper.h ft.h +jsonconnector.o: jsonconnector.h flatconnector.h jsonexpression.h jsonconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h -jsonconnector.o: modeldata.h cursorhelper.h queryresult.h -jsonconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -jsonconnector.o: finderhelper.h fieldvaluehelper.h ft.h +jsonconnector.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h +jsonconnector.o: fieldvaluehelper.h ft.h jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h -jsonexpression.o: ../../pikotools/textstream/textstream.h -jsonexpression.o: ../../pikotools/space/space.h -jsonexpression.o: ../../pikotools/textstream/types.h -jsonexpression.o: ../../pikotools/convert/inttostr.h -jsonexpression.o: ../../pikotools/date/date.h -jsonexpression.o: ../../pikotools/membuffer/membuffer.h -jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h -jsonexpression.o: modeldata.h cursorhelper.h queryresult.h -jsonexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -jsonexpression.o: finderhelper.h fieldvaluehelper.h ft.h -model.o: model.h ../../pikotools/textstream/textstream.h -model.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h -model.o: ../../pikotools/convert/inttostr.h ../../pikotools/date/date.h -model.o: ../../pikotools/membuffer/membuffer.h -model.o: ../../pikotools/textstream/types.h modelconnector.h clearer.h -model.o: dbconnector.h ../../pikotools/log/log.h -model.o: ../../pikotools/log/filelog.h queryresult.h flatconnector.h -model.o: dbexpression.h baseexpression.h morm_types.h modelenv.h modeldata.h -model.o: cursorhelper.h finderhelper.h fieldvaluehelper.h ft.h -model.o: flatexpression.h -modelconnector.o: modelconnector.h clearer.h ../../pikotools/date/date.h -modelconnector.o: ../../pikotools/convert/inttostr.h -modelconnector.o: ../../pikotools/space/space.h -modelconnector.o: ../../pikotools/textstream/types.h dbconnector.h -modelconnector.o: ../../pikotools/textstream/textstream.h -modelconnector.o: ../../pikotools/membuffer/membuffer.h -modelconnector.o: ../../pikotools/textstream/types.h -modelconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -modelconnector.o: queryresult.h flatconnector.h -postgresqlconnector.o: postgresqlconnector.h dbconnector.h -postgresqlconnector.o: ../../pikotools/textstream/textstream.h -postgresqlconnector.o: ../../pikotools/space/space.h -postgresqlconnector.o: ../../pikotools/textstream/types.h -postgresqlconnector.o: ../../pikotools/convert/inttostr.h -postgresqlconnector.o: ../../pikotools/date/date.h -postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h -postgresqlconnector.o: ../../pikotools/textstream/types.h -postgresqlconnector.o: ../../pikotools/log/log.h -postgresqlconnector.o: ../../pikotools/log/filelog.h queryresult.h -postgresqlconnector.o: postgresqlqueryresult.h ../../pikotools/utf8/utf8.h -postgresqlconnector.o: ../../pikotools/utf8/utf8_templates.h -postgresqlconnector.o: ../../pikotools/utf8/utf8_private.h -postgresqlconnector.o: postgresqlexpression.h dbexpression.h baseexpression.h -postgresqlconnector.o: morm_types.h modelenv.h modeldata.h cursorhelper.h -postgresqlconnector.o: finderhelper.h fieldvaluehelper.h ft.h -postgresqlconnector.o: ../../pikotools/convert/strtoint.h -postgresqlconnector.o: ../../pikotools/convert/text.h -postgresqlconnector.o: ../../pikotools/convert/misc.h +jsonexpression.o: morm_types.h modelenv.h modeldata.h cursorhelper.h +jsonexpression.o: queryresult.h finderhelper.h fieldvaluehelper.h ft.h +model.o: model.h modelconnector.h clearer.h dbconnector.h queryresult.h ft.h +model.o: flatconnector.h dbexpression.h baseexpression.h morm_types.h +model.o: modelenv.h modeldata.h cursorhelper.h finderhelper.h +model.o: fieldvaluehelper.h flatexpression.h +modelconnector.o: modelconnector.h clearer.h dbconnector.h queryresult.h ft.h +modelconnector.o: flatconnector.h +postgresqlconnector.o: postgresqlconnector.h dbconnector.h queryresult.h ft.h +postgresqlconnector.o: postgresqlqueryresult.h postgresqlexpression.h +postgresqlconnector.o: dbexpression.h baseexpression.h morm_types.h +postgresqlconnector.o: modelenv.h modeldata.h cursorhelper.h finderhelper.h +postgresqlconnector.o: fieldvaluehelper.h postgresqlexpression.o: postgresqlexpression.h dbexpression.h -postgresqlexpression.o: baseexpression.h -postgresqlexpression.o: ../../pikotools/textstream/textstream.h -postgresqlexpression.o: ../../pikotools/space/space.h -postgresqlexpression.o: ../../pikotools/textstream/types.h -postgresqlexpression.o: ../../pikotools/convert/inttostr.h -postgresqlexpression.o: ../../pikotools/date/date.h -postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h -postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h -postgresqlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h -postgresqlexpression.o: ../../pikotools/log/log.h -postgresqlexpression.o: ../../pikotools/log/filelog.h finderhelper.h +postgresqlexpression.o: baseexpression.h morm_types.h modelenv.h modeldata.h +postgresqlexpression.o: cursorhelper.h queryresult.h finderhelper.h postgresqlexpression.o: fieldvaluehelper.h ft.h postgresqlqueryresult.o: postgresqlqueryresult.h queryresult.h -postgresqlqueryresult.o: ../../pikotools/log/log.h -postgresqlqueryresult.o: ../../pikotools/textstream/textstream.h -postgresqlqueryresult.o: ../../pikotools/space/space.h -postgresqlqueryresult.o: ../../pikotools/textstream/types.h -postgresqlqueryresult.o: ../../pikotools/convert/inttostr.h -postgresqlqueryresult.o: ../../pikotools/date/date.h -postgresqlqueryresult.o: ../../pikotools/membuffer/membuffer.h -postgresqlqueryresult.o: ../../pikotools/textstream/types.h -postgresqlqueryresult.o: ../../pikotools/log/filelog.h -queryresult.o: queryresult.h ../../pikotools/log/log.h -queryresult.o: ../../pikotools/textstream/textstream.h -queryresult.o: ../../pikotools/space/space.h -queryresult.o: ../../pikotools/textstream/types.h -queryresult.o: ../../pikotools/convert/inttostr.h ../../pikotools/date/date.h -queryresult.o: ../../pikotools/membuffer/membuffer.h -queryresult.o: ../../pikotools/textstream/types.h -queryresult.o: ../../pikotools/log/filelog.h ../../pikotools/utf8/utf8.h -queryresult.o: ../../pikotools/utf8/utf8_templates.h -queryresult.o: ../../pikotools/utf8/utf8_private.h +queryresult.o: queryresult.h diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index d741c87..0c56c0f 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -318,71 +318,95 @@ void BaseExpression::after_second_part_long_field_name() -void BaseExpression::before_field_value(const std::wstring &) +void BaseExpression::before_field_value(const std::wstring &, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::before_field_value(const std::string &) +void BaseExpression::before_field_value(const std::string &, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::after_field_value(const std::wstring &) +void BaseExpression::after_field_value(const std::wstring &, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); } -void BaseExpression::after_field_value(const std::string &) +void BaseExpression::after_field_value(const std::string &, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); } -void BaseExpression::before_field_value(const wchar_t *) +void BaseExpression::before_field_value(const wchar_t *, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::after_field_value(const wchar_t *) +void BaseExpression::after_field_value(const wchar_t *, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); } -void BaseExpression::before_field_value(const char *) +void BaseExpression::before_field_value(const char *, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::after_field_value(const char *) +void BaseExpression::after_field_value(const char *, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); } -void BaseExpression::before_field_value(const PT::Date &) + +void BaseExpression::before_field_value(wchar_t, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::after_field_value(const PT::Date &) + +void BaseExpression::after_field_value(wchar_t, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); } -void BaseExpression::before_field_value(const PT::Space &) + +void BaseExpression::before_field_value(char, FT field_type) { - before_field_value_string(); + before_field_value_string(field_type); } -void BaseExpression::after_field_value(const PT::Space &) + +void BaseExpression::after_field_value(char, FT field_type) { - after_field_value_string(); + after_field_value_string(field_type); +} + +void BaseExpression::before_field_value(const PT::Date &, FT field_type) +{ + before_field_value_string(field_type); +} + +void BaseExpression::after_field_value(const PT::Date &, FT field_type) +{ + after_field_value_string(field_type); +} + +void BaseExpression::before_field_value(const PT::Space &, FT field_type) +{ + before_field_value_string(field_type); +} + +void BaseExpression::after_field_value(const PT::Space &, FT field_type) +{ + after_field_value_string(field_type); } @@ -392,82 +416,120 @@ void BaseExpression::put_name_value_separator() } -void BaseExpression::esc(char val, PT::TextStream & stream) +char BaseExpression::char_to_hex_part(char c) { - stream << val; + if( c < 10 ) + return c + '0'; + + return c - 10 + 'A'; } -void BaseExpression::esc(unsigned char val, PT::TextStream & stream) +void BaseExpression::char_to_hex(char c, PT::TextStream & stream) { - esc(static_cast(val), stream); + stream << char_to_hex_part(((unsigned char)c) >> 4); + stream << char_to_hex_part(((unsigned char)c) & 0x0f); } -void BaseExpression::esc(wchar_t val, PT::TextStream & stream) + + +void BaseExpression::esc(char val, PT::TextStream & stream, FT field_type) { - char utf8_buf[10]; - - size_t utf8_len = PT::IntToUTF8((int)val, utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) + if( field_type.is_binary() || field_type.is_hexadecimal() ) { - esc(utf8_buf[a], stream); + char_to_hex(val, stream); + } + else + { + stream << val; } } -void BaseExpression::esc(const std::wstring & val, PT::TextStream & stream) +void BaseExpression::esc(unsigned char val, PT::TextStream & stream, FT field_type) { - char utf8_buf[10]; + esc(static_cast(val), stream, field_type); +} - for(size_t i = 0 ; i < val.size() ; ++i) + +void BaseExpression::esc(wchar_t val, PT::TextStream & stream, FT field_type) +{ + if( field_type.use_utf8() ) { - size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); + char utf8_buf[10]; + + size_t utf8_len = PT::IntToUTF8((int)val, utf8_buf, sizeof(utf8_buf)); for(size_t a = 0 ; a < utf8_len ; ++a) { - esc(utf8_buf[a], stream); + esc(utf8_buf[a], stream, field_type); + } + } + else + { + esc(static_cast(val), stream, field_type); + } +} + + +void BaseExpression::esc(const wchar_t * val, bool has_known_length, size_t len, PT::TextStream & stream, FT field_type) +{ + if( field_type.use_utf8() ) + { + char utf8_buf[10]; + + for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) + { + size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); + + for(size_t a = 0 ; a < utf8_len ; ++a) + { + esc(utf8_buf[a], stream, field_type); + } + } + } + else + { + for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) + { + esc(static_cast(val[i]), stream, field_type); } } } -void BaseExpression::esc(const wchar_t * val, PT::TextStream & stream) +void BaseExpression::esc(const std::wstring & val, PT::TextStream & stream, FT field_type) { - char utf8_buf[10]; - - for(size_t i = 0 ; val[i] != 0 ; ++i) - { - size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) - { - esc(utf8_buf[a], stream); - } - } + esc(val.c_str(), true, val.size(), stream, field_type); } -void BaseExpression::esc(const std::string & val, PT::TextStream & stream) +void BaseExpression::esc(const wchar_t * val, PT::TextStream & stream, FT field_type) +{ + esc(val, false, 0, stream, field_type); +} + + +void BaseExpression::esc(const std::string & val, PT::TextStream & stream, FT field_type) { for(size_t i = 0 ; i < val.size() ; ++i) { - esc(val[i], stream); + esc(val[i], stream, field_type); } } -void BaseExpression::esc(const char * val, PT::TextStream & stream) +void BaseExpression::esc(const char * val, PT::TextStream & stream, FT field_type) { for(size_t i = 0 ; val[i] != 0 ; ++i) { - esc(val[i], stream); + esc(val[i], stream, field_type); } } -void BaseExpression::esc(bool val, PT::TextStream & stream) +void BaseExpression::esc(bool val, PT::TextStream & stream, FT field_type) { if( val ) stream << "true"; @@ -476,105 +538,105 @@ void BaseExpression::esc(bool val, PT::TextStream & stream) } -void BaseExpression::esc(short val, PT::TextStream & stream) +void BaseExpression::esc(short val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(unsigned short val, PT::TextStream & stream) +void BaseExpression::esc(unsigned short val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(int val, PT::TextStream & stream) +void BaseExpression::esc(int val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(unsigned int val, PT::TextStream & stream) +void BaseExpression::esc(unsigned int val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(long val, PT::TextStream & stream) +void BaseExpression::esc(long val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(unsigned long val, PT::TextStream & stream) +void BaseExpression::esc(unsigned long val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(long long val, PT::TextStream & stream) +void BaseExpression::esc(long long val, PT::TextStream & stream, FT field_type) { // not implemented in PT::TextStream yet //stream << val; } -void BaseExpression::esc(unsigned long long val, PT::TextStream & stream) +void BaseExpression::esc(unsigned long long val, PT::TextStream & stream, FT field_type) { //stream << val; } -void BaseExpression::esc(float val, PT::TextStream & stream) +void BaseExpression::esc(float val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(double val, PT::TextStream & stream) +void BaseExpression::esc(double val, PT::TextStream & stream, FT field_type) { stream << val; } -void BaseExpression::esc(long double val, PT::TextStream & stream) +void BaseExpression::esc(long double val, PT::TextStream & stream, FT field_type) { // IMPLEMENT ME in PT::TextStream //stream << val; } -void BaseExpression::esc(const PT::Date & date, PT::TextStream & stream) +void BaseExpression::esc(const PT::Date & date, PT::TextStream & stream, FT field_type) { stream << date; } -void BaseExpression::esc(const PT::TextStream & val, PT::TextStream & stream) +void BaseExpression::esc(const PT::TextStream & val, PT::TextStream & stream, FT field_type) { PT::TextStream::const_iterator i = val.begin(); for(; i != val.end() ; ++i) { - esc(*i, stream); + esc(*i, stream, field_type); } } -void BaseExpression::esc(const PT::WTextStream & val, PT::TextStream & stream) +void BaseExpression::esc(const PT::WTextStream & val, PT::TextStream & stream, FT field_type) { PT::WTextStream::const_iterator i = val.begin(); for(; i != val.end() ; ++i) { - esc(*i, stream); + esc(*i, stream, field_type); } } -void BaseExpression::esc(const PT::Space & space, PT::TextStream & stream) +void BaseExpression::esc(const PT::Space & space, PT::TextStream & stream, FT field_type) { PT::WTextStream tmp_stream; space.serialize_to_space_stream(tmp_stream, true); - esc(tmp_stream, stream); + esc(tmp_stream, stream, field_type); } @@ -687,11 +749,11 @@ void BaseExpression::esc(const PT::Space & space, PT::TextStream & stream) //} -void BaseExpression::before_field_value_string() +void BaseExpression::before_field_value_string(FT field_type) { } -void BaseExpression::after_field_value_string() +void BaseExpression::after_field_value_string(FT field_type) { } diff --git a/src/baseexpression.h b/src/baseexpression.h index c5e00c0..e06758c 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -129,13 +129,13 @@ public: if( field_type.is_primary_key() ) { if( model_env && model_env->has_primary_key_set ) - put_field_value(field_value); + put_field_value(field_value, field_type); else put_null_value(); } else { - put_field_value(field_value); + put_field_value(field_value, field_type); } } @@ -288,35 +288,35 @@ public: * esc for: signed char, wchar_t, char16_t, char32_t * */ - virtual void esc(char val, PT::TextStream & stream); - virtual void esc(unsigned char val, PT::TextStream & stream); + virtual void esc(char val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(unsigned char val, PT::TextStream & stream, FT field_type = FT::default_type); - virtual void esc(wchar_t val, PT::TextStream & stream); + virtual void esc(wchar_t val, PT::TextStream & stream, FT field_type = FT::default_type); - virtual void esc(const std::wstring & val, PT::TextStream & stream); - virtual void esc(const wchar_t * val, PT::TextStream & stream); + virtual void esc(const std::wstring & val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(const wchar_t * val, PT::TextStream & stream, FT field_type = FT::default_type); - virtual void esc(const std::string & val, PT::TextStream & stream); - virtual void esc(const char * val, PT::TextStream & stream); + virtual void esc(const std::string & val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(const char * val, PT::TextStream & stream, FT field_type = FT::default_type); - virtual void esc(bool val, PT::TextStream & stream); - virtual void esc(short val, PT::TextStream & stream); - virtual void esc(unsigned short val, PT::TextStream & stream); - virtual void esc(int val, PT::TextStream & stream); - virtual void esc(unsigned int val, PT::TextStream & stream); - virtual void esc(long val, PT::TextStream & stream); - virtual void esc(unsigned long val, PT::TextStream & stream); - virtual void esc(long long val, PT::TextStream & stream); - virtual void esc(unsigned long long val, PT::TextStream & stream); - virtual void esc(float val, PT::TextStream & stream); - virtual void esc(double val, PT::TextStream & stream); - virtual void esc(long double val, PT::TextStream & stream); + virtual void esc(bool val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(short val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(unsigned short val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(int val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(unsigned int val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(long val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(unsigned long val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(long long val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(unsigned long long val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(float val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(double val, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(long double val, PT::TextStream & stream, FT field_type = FT::default_type); //virtual void esc(void* val, PT::TextStream & stream); - virtual void esc(const PT::Date & date, PT::TextStream & stream); - virtual void esc(const PT::TextStream & val,PT::TextStream & stream); - virtual void esc(const PT::WTextStream & val,PT::TextStream & stream); - virtual void esc(const PT::Space & space, PT::TextStream & stream); + virtual void esc(const PT::Date & date, PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(const PT::TextStream & val,PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(const PT::WTextStream & val,PT::TextStream & stream, FT field_type = FT::default_type); + virtual void esc(const PT::Space & space, PT::TextStream & stream, FT field_type = FT::default_type); virtual bool is_long_field_name(const wchar_t * field_name); virtual bool is_long_field_name(const PT::TextStream & table_name); @@ -344,13 +344,13 @@ protected: virtual void dump_additional_info(Model & model); template - void put_field_value(const FieldValue & field_value) + void put_field_value(const FieldValue & field_value, FT field_type) { if( out_stream ) { - before_field_value(field_value); - esc(field_value, *out_stream); - after_field_value(field_value); + before_field_value(field_value, field_type); + esc(field_value, *out_stream, field_type); + after_field_value(field_value, field_type); } } @@ -402,7 +402,7 @@ protected: field_value_list_separator(); } - put_field_value(m); + put_field_value(m, FT::default_type); is_first = false; } @@ -641,7 +641,7 @@ protected: field_value_list_separator(); } - put_field_value(v); + put_field_value(v, FT::default_type); is_first = false; } @@ -672,31 +672,37 @@ protected: virtual void put_long_field_name(const wchar_t * field_name); virtual void put_short_field_name(const wchar_t * field_name, ModelEnv * model_env); - virtual void before_field_value(const std::wstring &); - virtual void after_field_value(const std::wstring &); + virtual void before_field_value(const std::wstring &, FT field_type); + virtual void after_field_value(const std::wstring &, FT field_type); - virtual void before_field_value(const std::string &); - virtual void after_field_value(const std::string &); + virtual void before_field_value(const std::string &, FT field_type); + virtual void after_field_value(const std::string &, FT field_type); - virtual void before_field_value(const wchar_t *); - virtual void after_field_value(const wchar_t *); + virtual void before_field_value(const wchar_t *, FT field_type); + virtual void after_field_value(const wchar_t *, FT field_type); - virtual void before_field_value(const char *); - virtual void after_field_value(const char *); + virtual void before_field_value(const char *, FT field_type); + virtual void after_field_value(const char *, FT field_type); - virtual void before_field_value(const PT::Date &); - virtual void after_field_value(const PT::Date &); + virtual void before_field_value(wchar_t, FT field_type); + virtual void after_field_value(wchar_t, FT field_type); - virtual void before_field_value(const PT::Space &); - virtual void after_field_value(const PT::Space &); + virtual void before_field_value(char, FT field_type); + virtual void after_field_value(char, FT field_type); + + virtual void before_field_value(const PT::Date &, FT field_type); + virtual void after_field_value(const PT::Date &, FT field_type); + + virtual void before_field_value(const PT::Space &, FT field_type); + virtual void after_field_value(const PT::Space &, FT field_type); template - void before_field_value(const FieldValue &) + void before_field_value(const FieldValue &, FT field_type) { } template - void after_field_value(const FieldValue &) + void after_field_value(const FieldValue &, FT field_type) { } @@ -747,12 +753,14 @@ protected: // } -private: - virtual void before_field_value_string(); - virtual void after_field_value_string(); + virtual void before_field_value_string(FT field_type); + virtual void after_field_value_string(FT field_type); + char char_to_hex_part(char c); + void char_to_hex(char c, PT::TextStream & stream); + void esc(const wchar_t * val, bool has_known_length, size_t len, PT::TextStream & stream, FT field_type = FT::default_type); }; diff --git a/src/clearer.cpp b/src/clearer.cpp index a50c02e..53b2381 100644 --- a/src/clearer.cpp +++ b/src/clearer.cpp @@ -61,6 +61,10 @@ void Clearer::clear_value(unsigned char & field_value) field_value = 0; } +void Clearer::clear_value(wchar_t & field_value) +{ + field_value = 0; +} void Clearer::clear_value(std::wstring & field_value) { diff --git a/src/clearer.h b/src/clearer.h index 94f9de3..d6ab824 100644 --- a/src/clearer.h +++ b/src/clearer.h @@ -54,6 +54,7 @@ public: virtual void clear_value(char & field_value); virtual void clear_value(unsigned char & field_value); + virtual void clear_value(wchar_t & field_value); virtual void clear_value(std::wstring & field_value); virtual void clear_value(std::string & field_value); virtual void clear_value(bool & field_value); diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 5ac3d06..4b3a4c3 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -291,52 +291,310 @@ void DbConnector::allocate_default_expression_if_needed() } - - - - - -void DbConnector::get_value(const char * value_str, char & field_value) +char DbConnector::unescape_hex_char_part(char hex) { - field_value = *value_str; - value_str += 1; - - if( *value_str != 0 ) + if( hex>='0' && hex<='9' ) { - // value has more than one charater, put some error? + return hex - '0'; + } + else + if( hex>='a' && hex<='f' ) + { + return hex - 'a' + 10; + } + else + if( hex>='A' && hex<='F' ) + { + return hex - 'A' + 10; + } + else + { + if( log ) + { + (*log) << PT::Log::log2 << "Morm: incorrect character when reading a hex string, char code: " << (int)(unsigned char)hex; + + if( hex >= 32 ) + { + (*log) << " '" << hex << "'"; + } + + (*log) << PT::Log::logend; + } + } + + return 0; +} + + +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)); +} + + +void DbConnector::unescape_hex_string(const char * str, std::string & out) +{ + for(size_t i=0 ; str[i] != 0 ; i+=2 ) + { + out += unescape_hex_char(str[i], str[i+1]); + } +} + + +void DbConnector::unescape_hex_string(const char * str, std::wstring & out, FT field_type) +{ + if( field_type.use_utf8() ) + { + size_t len; + wchar_t c; + + while( *str != 0 && (len = unescape_hex_char(str, c, field_type)) > 0 ) + { + out += c; + str += len; + } + } + else + { + for(size_t i=0 ; str[i] != 0 ; i+=2 ) + { + out += static_cast(static_cast(unescape_hex_char(str[i], str[i+1]))); + } + } +} + + +void DbConnector::unescape_bin_string(const char * str, std::string & out) +{ + unescape_hex_string(str, out); +} + + +void DbConnector::unescape_bin_string(const char * str, std::wstring & out, FT field_type) +{ + 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, 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::UTF8ToInt(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, FT field_type) +{ + return unescape_hex_char(value_str, field_value, field_type); +} + + + +// CHECKME need to be tested +void DbConnector::get_value(const char * value_str, char & field_value, FT field_type) +{ + wchar_t c; + + field_value = 0; + get_value(value_str, c, field_type); + + if( field_type.use_utf8() ) + { + 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; + } + } + } + else + { + field_value = static_cast(c); } } -void DbConnector::get_value(const char * value_str, unsigned char & field_value) +// CHECKME need to be tested +void DbConnector::get_value(const char * value_str, unsigned char & field_value, FT field_type) { - field_value = *(const unsigned char*)value_str; - value_str += 1; + char tmp_char; + get_value(value_str, tmp_char, field_type); - if( *value_str != 0 ) + field_value = static_cast(tmp_char); +} + + + +// CHECKME need to be tested +void DbConnector::get_value(const char * value_str, wchar_t & field_value, FT field_type) +{ + field_value = 0; + + if( field_type.is_binary() ) { - // value has more than one charater, put some error? + unescape_bin_char(value_str, field_value, field_type); + } + else + if( field_type.is_hexadecimal() ) + { + unescape_hex_char(value_str, field_value, field_type); + } + else + { + if( field_type.use_utf8() ) + { + int value_int; + bool is_correct; + + PT::UTF8ToInt(value_str, value_int, is_correct); + + if( is_correct ) + { + field_value = static_cast(value_int); + } + else + { + // report an error? + } + } + else + { + field_value = static_cast((unsigned char)*value_str); + } } } -void DbConnector::get_value(const char * value_str, std::wstring & field_value) + +// CHECKME need to be tested +void DbConnector::get_value(const char * value_str, std::wstring & field_value, FT field_type) { - // CHECKME - // what about \0 in val_str? - // it is escaped somehow? - PT::UTF8ToWide(value_str, field_value); + 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::UTF8ToWide(value_str, field_value); + } + else + { + for(size_t i=0 ; value_str[i] != 0 ; ++i) + { + field_value += static_cast(value_str[i]); + } + } + } } -void DbConnector::get_value(const char * value_str, std::string & field_value) +// CHECKME need to be tested +void DbConnector::get_value(const char * value_str, std::string & field_value, FT field_type) { - field_value = value_str; + 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 + { + field_value = value_str; + } } -void DbConnector::get_value(const char * value_str, bool & field_value) +void DbConnector::get_value(const char * value_str, bool & field_value, FT field_type) { // IMPROVE ME // this 't' is locale dependent @@ -344,91 +602,91 @@ void DbConnector::get_value(const char * value_str, bool & field_value) } -void DbConnector::get_value(const char * value_str, short & field_value) +void DbConnector::get_value(const char * value_str, short & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = (short)PT::Toi(value_str, 10); } -void DbConnector::get_value(const char * value_str, unsigned short & field_value) +void DbConnector::get_value(const char * value_str, unsigned short & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = (unsigned short)PT::Toui(value_str, 10); } -void DbConnector::get_value(const char * value_str, int & field_value) +void DbConnector::get_value(const char * value_str, int & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Toi(value_str, 10); } -void DbConnector::get_value(const char * value_str, unsigned int & field_value) +void DbConnector::get_value(const char * value_str, unsigned int & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Toui(value_str, 10); } -void DbConnector::get_value(const char * value_str, long & field_value) +void DbConnector::get_value(const char * value_str, long & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Tol(value_str, 10); } -void DbConnector::get_value(const char * value_str, unsigned long & field_value) +void DbConnector::get_value(const char * value_str, unsigned long & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Toul(value_str, 10); } -void DbConnector::get_value(const char * value_str, long long & field_value) +void DbConnector::get_value(const char * value_str, long long & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Toll(value_str, 10); } -void DbConnector::get_value(const char * value_str, unsigned long long & field_value) +void DbConnector::get_value(const char * value_str, unsigned long long & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = PT::Toull(value_str, 10); } -void DbConnector::get_value(const char * value_str, float & field_value) +void DbConnector::get_value(const char * value_str, float & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = strtof(value_str, 0); } -void DbConnector::get_value(const char * value_str, double & field_value) +void DbConnector::get_value(const char * value_str, double & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = strtod(value_str, 0); } -void DbConnector::get_value(const char * value_str, long double & field_value) +void DbConnector::get_value(const char * value_str, long double & field_value, FT field_type) { // IMPROVE ME give some overflow checking field_value = strtold(value_str, 0); } -void DbConnector::get_value(const char * value_str, PT::Date & field_value) +void DbConnector::get_value(const char * value_str, PT::Date & field_value, FT field_type) { // IMPROVE ME give some log if parsing failed field_value.Parse(value_str); } -void DbConnector::get_value(const char * value_str, PT::Space & field_value) +void DbConnector::get_value(const char * value_str, PT::Space & field_value, FT field_type) { field_value.clear(); @@ -443,7 +701,7 @@ void DbConnector::get_value(const char * value_str, PT::Space & field_value) if( log ) { - (*log) << PT::Log::log1 << "Morm: I cannot correctly parse the Space struct from the datebase" + (*log) << PT::Log::log2 << "Morm: I cannot correctly parse the Space struct from the datebase" << ", the raw string is: " << value_str << PT::Log::logend; } } diff --git a/src/dbconnector.h b/src/dbconnector.h index f86e90c..d7e3b2e 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.h @@ -38,6 +38,7 @@ #include "textstream/textstream.h" #include "log/log.h" #include "queryresult.h" +#include "ft.h" namespace morm @@ -90,25 +91,27 @@ public: virtual bool query_insert(const PT::TextStream & stream, QueryResult & query_result); virtual bool query_remove(const PT::TextStream & stream, QueryResult & query_result); - virtual void get_value(const char * value_str, char & field_value); - virtual void get_value(const char * value_str, unsigned char & field_value); - virtual void get_value(const char * value_str, std::wstring & field_value); - virtual void get_value(const char * value_str, std::string & field_value); - virtual void get_value(const char * value_str, bool & field_value); - virtual void get_value(const char * value_str, short & field_value); - virtual void get_value(const char * value_str, unsigned short & field_value); - virtual void get_value(const char * value_str, int & field_value); - virtual void get_value(const char * value_str, unsigned int & field_value); - virtual void get_value(const char * value_str, long & field_value); - virtual void get_value(const char * value_str, unsigned long & field_value); - virtual void get_value(const char * value_str, long long & field_value); - virtual void get_value(const char * value_str, unsigned long long & field_value); - virtual void get_value(const char * value_str, float & field_value); - virtual void get_value(const char * value_str, double & field_value); - virtual void get_value(const char * value_str, long double & field_value); - virtual void get_value(const char * value_str, PT::Date & field_value); - virtual void get_value(const char * value_str, PT::Space & field_value); + virtual void get_value(const char * value_str, char & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned char & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, wchar_t & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, std::wstring & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, std::string & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, bool & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, short & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned short & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, int & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned int & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, long & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned long & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, long long & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, unsigned long long & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, float & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, double & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, long double & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, PT::Date & field_value, FT field_type = FT::default_type); + virtual void get_value(const char * value_str, PT::Space & field_value, FT field_type = FT::default_type); + // add get_value for PT::TextStream and PT::WTextStream template bool get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value) @@ -145,6 +148,23 @@ protected: virtual const char * query_last_sequence(const wchar_t * sequence_table_name); + virtual void unescape_hex_string(const char * str, std::string & out); + virtual void unescape_hex_string(const char * str, std::wstring & out, FT field_type); + + virtual void unescape_bin_string(const char * str, std::string & out); + virtual void unescape_bin_string(const char * str, std::wstring & out, FT field_type); + + 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, FT field_type); + virtual size_t unescape_bin_char(const char * value_str, wchar_t & field_value, FT field_type); + +private: + + char unescape_hex_char_part(char hex); + char unescape_hex_char(char char1, char char2); + + + }; diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index a0af7ef..5bf82d4 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -183,13 +183,13 @@ void DbExpression::put_name_value_separator() -void DbExpression::before_field_value_string() +void DbExpression::before_field_value_string(FT field_type) { (*out_stream) << "'"; } -void DbExpression::after_field_value_string() +void DbExpression::after_field_value_string(FT field_type) { (*out_stream) << "'"; } diff --git a/src/dbexpression.h b/src/dbexpression.h index 1e6385e..5c4cbdb 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -81,18 +81,15 @@ protected: int output_type; std::vector conjunctions; - bool can_field_be_generated(FT field_type); - void field_before(); - void put_name_value_separator(); private: - void before_field_value_string(); - void after_field_value_string(); + void before_field_value_string(FT field_type); + void after_field_value_string(FT field_type); }; diff --git a/src/flatexpression.cpp b/src/flatexpression.cpp index 4252d47..0a31f52 100644 --- a/src/flatexpression.cpp +++ b/src/flatexpression.cpp @@ -39,7 +39,7 @@ namespace morm { -void FlatExpression::esc(const PT::Date & date, PT::TextStream & stream) +void FlatExpression::esc(const PT::Date & date, PT::TextStream & stream, FT field_type) { date.SerializeISO(stream); } diff --git a/src/flatexpression.h b/src/flatexpression.h index b928607..fc45823 100644 --- a/src/flatexpression.h +++ b/src/flatexpression.h @@ -45,7 +45,7 @@ class FlatExpression : public BaseExpression { public: - void esc(const PT::Date & date, PT::TextStream & stream); + void esc(const PT::Date & date, PT::TextStream & stream, FT field_type); diff --git a/src/ft.h b/src/ft.h index 1d884e9..0344af1 100644 --- a/src/ft.h +++ b/src/ft.h @@ -57,6 +57,9 @@ public: no_updatable = 16, no_fetchable = 32, /* not supported yet */ raw_field_name = 64, + dont_use_utf8 = 128, + hexadecimal = 256, + binary = 512, }; /* @@ -137,6 +140,22 @@ public: return is_flag_set(raw_field_name); } + bool use_utf8() const + { + return !is_flag_set(dont_use_utf8); + } + + bool is_hexadecimal() const + { + return is_flag_set(hexadecimal); + } + + bool is_binary() const + { + return is_flag_set(binary); + } + + }; } diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index f9cd103..a2d18dd 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -105,12 +105,12 @@ void JSONExpression::after_second_part_long_field_name() } -void JSONExpression::before_field_value_string() +void JSONExpression::before_field_value_string(FT field_type) { (*out_stream) << "\""; } -void JSONExpression::after_field_value_string() +void JSONExpression::after_field_value_string(FT field_type) { (*out_stream) << "\""; } @@ -134,20 +134,48 @@ void JSONExpression::after_field_value_list() } -void JSONExpression::esc(char val, PT::TextStream & stream) +void JSONExpression::esc(char val, PT::TextStream & stream, FT field_type) { - switch( val ) + if( field_type.is_hexadecimal() || field_type.is_binary() ) { - case 0: stream << '\\'; stream << '0'; break; // may to skip this character is better? - case '\r': stream << '\\'; stream << 'r'; break; - case '\n': stream << '\\'; stream << 'n'; break; - case '\t': stream << '\\'; stream << 't'; break; - case 0x08: stream << '\\'; stream << 'b'; break; - case 0x0c: stream << '\\'; stream << 'f'; break; - case '\\': stream << '\\'; stream << '\\'; break; - case '"': stream << '\\'; stream << '\"'; break; - default: - stream << val; + char_to_hex(val, stream); + } + else + { + if( (unsigned char)val < 32 ) + { + char buf[10]; + size_t len; + PT::Toa((unsigned char)val, buf, sizeof(buf)/sizeof(char), 16, &len); + + stream << "\\u"; + + if( len < 4 ) + { + for(size_t i=0 ; i < (4-len) ; ++i) + { + stream << '0'; + } + } + + stream << buf; + } + else + { + switch( val ) + { + case 0: stream << '\\'; stream << '0'; break; // may to skip this character is better? + case '\r': stream << '\\'; stream << 'r'; break; + case '\n': stream << '\\'; stream << 'n'; break; + case '\t': stream << '\\'; stream << 't'; break; + case 0x08: stream << '\\'; stream << 'b'; break; + case 0x0c: stream << '\\'; stream << 'f'; break; + case '\\': stream << '\\'; stream << '\\'; break; + case '"': stream << '\\'; stream << '\"'; break; + default: + stream << val; + } + } } } diff --git a/src/jsonexpression.h b/src/jsonexpression.h index f2091c5..a9f39bf 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -70,13 +70,13 @@ protected: // 'morm::JSONExpression::esc' hides overloaded virtual function [-Woverloaded-virtual] using FlatExpression::esc; - void esc(char val, PT::TextStream & stream); + void esc(char val, PT::TextStream & stream, FT field_type); private: - void before_field_value_string(); - void after_field_value_string(); + void before_field_value_string(FT field_type); + void after_field_value_string(FT field_type); }; diff --git a/src/model.h b/src/model.h index 25d95b1..ebb4c7a 100644 --- a/src/model.h +++ b/src/model.h @@ -232,6 +232,11 @@ protected: field_generic(field_name, field_name, field_value, field_type); } + void field(const wchar_t * field_name, wchar_t & field_value, FT field_type = FT::default_type) + { + field_generic(field_name, field_name, field_value, field_type); + } + void field(const wchar_t * field_name, std::wstring & field_value, FT field_type = FT::default_type) { field_generic(field_name, field_name, field_value, field_type); @@ -347,6 +352,11 @@ protected: field_generic(db_field_name, flat_field_name, field_value, field_type); } + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, wchar_t & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value, FT field_type = FT::default_type) { field_generic(db_field_name, flat_field_name, field_value, field_type); @@ -1224,7 +1234,7 @@ protected: if( val_str ) { - db_connector->get_value(val_str, field_value); + db_connector->get_value(val_str, field_value, field_type); } } else @@ -1271,7 +1281,7 @@ protected: if( val_str ) { - db_connector->get_value(val_str, field_value); + db_connector->get_value(val_str, field_value, field_type); } } else diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index bad375d..37acfac 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2019, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -392,128 +392,6 @@ bool PostgreSQLConnector::query_remove(const PT::TextStream & stream, QueryResul - - - -/* - converting from a bytea - the old way (escape format) -*/ -/* -int PostgreSQLConnector::CharToInt(char c) -{ - return (int)(unsigned char)(c-'0'); -} - -bool PostgreSQLConnector::IsCorrectOctalDigit(char c) -{ - return c>='0' && c<='7'; -} - -// moves 'i' at least once -// return -1 if there is en error -int PostgreSQLConnector::UnescapeBin(const char * str, size_t & i, size_t len) -{ - if( str[i] != '\\' ) - return str[i++]; - - i += 1; - - if( i >= len ) - return -1; - - if( str[i] == '\\' ) - return str[i++]; - - if( i+2 >= len ) - { - i = len; - return -1; - } - - if( !IsCorrectOctalDigit(str[i]) || - !IsCorrectOctalDigit(str[i+1]) || - !IsCorrectOctalDigit(str[i+2]) ) - { - i += 3; - return -1; - } - - int c = 8*8*CharToInt(str[i]) + 8*CharToInt(str[i+1]) + CharToInt(str[i+2]); - - i += 3; - - if( c<0 || c>255 ) - return -1; - -return c; -} - -void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out) -{ -int c; -size_t i = 0; - - if( clear_out ) - out.clear(); - - while( i < len ) - { - c = UnescapeBin(str, i, len); - - if( c != -1 ) - out += c; - } -} -*/ - - - - - -/* - converting from a bytea - the new way (hex format) -*/ - - -//char PostgreSQLConnector::UnescapeBinHexToDigit(char hex) -//{ -// if( hex>='0' && hex<='9' ) -// return hex - '0'; -// -// if( hex>='a' && hex<='z' ) -// return hex - 'a' + 10; -// -// if( hex>='A' && hex<='Z' ) -// return hex - 'A' + 10; -// -//return 0; -//} -// -// -//void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out) -//{ -// if( clear_out ) -// out.clear(); -// -// if( len < 2 || str[0]!='\\' || str[1]!='x' ) -// { -// log << log1 << "Morm: unsupported binary format (skipping)" << logend; -// return; -// } -// -// for(size_t i=2 ; i + 1 < len ; i+=2 ) -// { -// int c1 = UnescapeBinHexToDigit(str[i]); -// int c2 = UnescapeBinHexToDigit(str[i+1]); -// -// out += ((c1 << 4) | c2); -// } -//} - - - void PostgreSQLConnector::set_conn_param(const std::wstring & database_name, const std::wstring & user, const std::wstring & pass) { db_database = database_name; @@ -672,8 +550,55 @@ void PostgreSQLConnector::set_db_parameters() } +void PostgreSQLConnector::log_unsupported_bin_format() +{ + if( log ) + { + (*log) << PT::Log::log1 << "Morm: unsupported binary format (skipping)" << PT::Log::logend; + } +} +size_t PostgreSQLConnector::unescape_bin_char(const char * str, wchar_t & field_value, FT field_type) +{ + if( str[0]!='\\' || str[1]!='x' ) + { + log_unsupported_bin_format(); + return 0; + } + else + { + return unescape_hex_char(str + 2, field_value, field_type); + } +} + + + +void PostgreSQLConnector::unescape_bin_string(const char * str, std::string & out) +{ + if( str[0]!='\\' || str[1]!='x' ) + { + log_unsupported_bin_format(); + } + else + { + unescape_hex_string(str + 2, out); + } +} + + +void PostgreSQLConnector::unescape_bin_string(const char * str, std::wstring & out, FT field_type) +{ + if( str[0]!='\\' || str[1]!='x' ) + { + log_unsupported_bin_format(); + } + else + { + unescape_hex_string(str + 2, out, field_type); + } +} + } diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h index 27e4f1a..9403d9f 100644 --- a/src/postgresqlconnector.h +++ b/src/postgresqlconnector.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2019, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,6 +98,11 @@ protected: virtual const char * query_last_sequence(const wchar_t * sequence_table_name); virtual QueryResult * create_query_result(); + void log_unsupported_bin_format(); + + size_t unescape_bin_char(const char * str, wchar_t & field_value, FT field_type); + void unescape_bin_string(const char * str, std::string & out); + void unescape_bin_string(const char * str, std::wstring & out, FT field_type); }; diff --git a/src/postgresqlexpression.cpp b/src/postgresqlexpression.cpp index 4da9ef6..392c0b7 100644 --- a/src/postgresqlexpression.cpp +++ b/src/postgresqlexpression.cpp @@ -77,34 +77,53 @@ void PostgreSQLExpression::after_second_part_long_field_name() -void PostgreSQLExpression::before_field_value_string() +void PostgreSQLExpression::before_field_value_string(FT field_type) { - (*out_stream) << "E'"; + if( field_type.is_binary() ) + { + (*out_stream) << "'\\x"; + } + else + if( field_type.is_hexadecimal() ) + { + (*out_stream) << "'"; + } + else + { + (*out_stream) << "E'"; + } } -void PostgreSQLExpression::after_field_value_string() +void PostgreSQLExpression::after_field_value_string(FT field_type) { (*out_stream) << "'"; } -void PostgreSQLExpression::esc(char val, PT::TextStream & stream) +void PostgreSQLExpression::esc(char val, PT::TextStream & stream, FT field_type) { - switch( val ) + if( field_type.is_hexadecimal() || field_type.is_binary() ) { - case '\\': stream << "\\\\"; break; - case '\'': stream << "\\\'"; break; // don't use "''" because we use the method for PQconnectdb too - default: - if( val != 0 ) + char_to_hex(val, stream); + } + else + { + switch( val ) { - stream << val; + case '\\': stream << "\\\\"; break; + case '\'': stream << "\\\'"; break; // don't use "''" because we use the method for PQconnectdb too + default: + if( val != 0 ) + { + stream << val; + } } } } -void PostgreSQLExpression::esc(const PT::Date & date, PT::TextStream & stream) +void PostgreSQLExpression::esc(const PT::Date & date, PT::TextStream & stream, FT field_type) { stream << date << "+00"; } diff --git a/src/postgresqlexpression.h b/src/postgresqlexpression.h index 873247d..3be9a23 100644 --- a/src/postgresqlexpression.h +++ b/src/postgresqlexpression.h @@ -45,8 +45,8 @@ class PostgreSQLExpression : public DbExpression { public: - void esc(char val, PT::TextStream & stream); - void esc(const PT::Date & date, PT::TextStream & stream); + void esc(char val, PT::TextStream & stream, FT field_type); + void esc(const PT::Date & date, PT::TextStream & stream, FT field_type); DbExpression & page(PT::TextStream & stream, size_t page_number, size_t page_size); @@ -64,10 +64,8 @@ protected: private: - void before_field_value_string(); - void after_field_value_string(); - - + void before_field_value_string(FT field_type); + void after_field_value_string(FT field_type); };