diff options
author | Marc Mutz <marc.mutz@qt.io> | 2023-01-24 14:29:27 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-01-25 06:37:22 +0000 |
commit | 66767eea46bea0f19f8ae5ad6ebc641d86867701 (patch) | |
tree | ebfa3dfc3150a988dbf87cfe619824bc59b1f21e /src/plugins/sqldrivers/odbc/qsql_odbc.cpp | |
parent | 05e7d09eb373454c67219cc8f7e4b7226ec7f52e (diff) |
ODBC SQL driver: deal with different sizes of SQLTCHAR correctly
Neither the UTF-32, nor the UTF-8 recoding of a UTF-16 string is
necessarily of the same length as the input. The UTF-32 version may
be shorter, if surrogate pairs were encountered. The UTF-8 version
will be longer whenever the string contains non-US-ASCII characters.
Split toSQLTCHAR() into three functions, templated on sizeof(SQLTCHAR),
and use QVLA's range-append instead of manual memcpy()s.
This patch specifically doesn't use constexpr-if, as that's not
available until C++17, which Qt 5 doesn't require.
Pick-to: 6.5 6.4 6.2 5.15
Change-Id: I0bfcb66eb321598908ef00ac34c888fdbccf9316
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/plugins/sqldrivers/odbc/qsql_odbc.cpp')
-rw-r--r-- | src/plugins/sqldrivers/odbc/qsql_odbc.cpp | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp index 386ffccf36..5c05b5df27 100644 --- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp +++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp @@ -58,23 +58,39 @@ inline static QString fromSQLTCHAR(const QVarLengthArray<SQLTCHAR>& input, qsize return result; } +template <size_t SizeOfChar = sizeof(SQLTCHAR)> +void toSQLTCHARImpl(QVarLengthArray<SQLTCHAR> &result, const QString &input); // primary template undefined + +template <typename Container> +void do_append(QVarLengthArray<SQLTCHAR> &result, const Container &c) +{ + result.append(reinterpret_cast<const SQLTCHAR *>(c.data()), c.size()); +} + +template <> +void toSQLTCHARImpl<1>(QVarLengthArray<SQLTCHAR> &result, const QString &input) +{ + const auto u8 = input.toUtf8(); + do_append(result, u8); +} + +template <> +void toSQLTCHARImpl<2>(QVarLengthArray<SQLTCHAR> &result, const QString &input) +{ + do_append(result, input); +} + +template <> +void toSQLTCHARImpl<4>(QVarLengthArray<SQLTCHAR> &result, const QString &input) +{ + const auto u32 = input.toUcs4(); + do_append(result, u32); +} + inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input) { QVarLengthArray<SQLTCHAR> result; - result.resize(input.size()); - switch(sizeof(SQLTCHAR)) { - case 1: - memcpy(result.data(), input.toUtf8().data(), input.size()); - break; - case 2: - memcpy(result.data(), input.unicode(), input.size() * 2); - break; - case 4: - memcpy(result.data(), input.toUcs4().data(), input.size() * 4); - break; - default: - qCritical("sizeof(SQLTCHAR) is %d. Don't know how to handle this.", int(sizeof(SQLTCHAR))); - } + toSQLTCHARImpl(result, input); result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't. return result; } |