tôi rảnh ngồi viết hàm chuyển mấy chữ tiếng Việt trong QString sang CP1258 đây. Ko biết xài trình dịch nào nên viết theo C++11 cho tương thích với mấy trình dịch cũ. Cách xài là:
#include "utf16tocp1258.h"
...
const std::string kVietCode = "\x1B\x74\x23";
QString text = "HÓA ĐƠN BÁN HÀNG";
std::string textToPrint = kVietCode + wsToCp1258(text);
printer->sendData(textToPrint.data(), textToPrint.size());
thêm 2 file này vào executable nữa là được:
utf16tocp1258.h
#pragma once
#include <sstream>
#include <type_traits>
#include <cstdint>
auto findVnUtf16ToCp1258Char(char16_t wch) -> uint16_t;
template <class...>
using void_t = void;
template <typename, typename = void>
struct has_unicode_memfn : std::false_type {};
template <typename T>
struct has_unicode_memfn<T, void_t<decltype(std::declval<T>().unicode())>> : std::true_type {};
template <class WideChar>
typename std::enable_if<has_unicode_memfn<WideChar>::value, char16_t>::type toChar16(WideChar wc) {
return static_cast<char16_t>(wc.unicode());
}
template <class WideChar>
typename std::enable_if<std::is_integral<WideChar>::value, char16_t>::type toChar16(WideChar wc) {
return static_cast<char16_t>(wc);
}
template <class WideString>
void printWsToCp1258(std::ostream& os, const WideString& ws) {
for (auto wc : ws) {
const char16_t ch = toChar16(wc);
auto ch1258 = findVnUtf16ToCp1258Char(ch);
if (ch1258 != 0) {
for (; ch1258; ch1258 >>= 8) os << static_cast<char>(ch1258 % 256);
} else {
os << static_cast<char>(ch);
}
}
}
template <class WideString>
auto wsToCp1258(const WideString& ws) -> std::string {
std::ostringstream oss;
printWsToCp1258(oss, ws);
return oss.str();
}
và utf16tocp1258.cpp
#include "utf16tocp1258.h"
#include <array>
#include <utility>
auto vnUtf16ToCp1258PerfHash(char16_t wch) -> uint32_t {
static const std::array<uint8_t, 21> assoValues{24, 71, 38, 1, 0, 22, 48, 95, 97, 96, 137,
118, 81, 111, 121, 3, 20, 12, 16, 8, 47};
return assoValues[wch % 16] + assoValues[(wch >> 4) % 16 + 5] + assoValues[(wch >> 12) % 16 + 3]; // NOLINT
}
auto findVnUtf16ToCp1258Char(char16_t wch) -> uint16_t {
static const std::array<std::pair<char16_t, uint16_t>, 217> vnUtf16ToCp1258Mapping{{
{0, 0}, {0, 0}, {0, 0}, {7844, 60610}, {7843, 53857}, {0, 0}, {7855, 60643},
{431, 221}, {7908, 62037}, {7907, 62197}, {227, 56929}, {7919, 57085}, {7876, 57034}, {7875, 53994},
{195, 56897}, {7887, 53871}, {7892, 53972}, {7891, 52468}, {0, 0}, {7903, 54005}, {7860, 57027},
{7859, 53987}, {0, 0}, {7871, 60650}, {259, 227}, {7845, 60642}, {0, 0}, {7840, 62017},
{416, 213}, {0, 0}, {7909, 62069}, {0, 0}, {7904, 57045}, {0, 0}, {7877, 57066},
{0, 0}, {7872, 52426}, {0, 0}, {7893, 54004}, {213, 56911}, {7888, 60628}, {7842, 53825},
{7861, 57059}, {0, 0}, {7856, 52419}, {432, 253}, {7906, 62165}, {7924, 62041}, {7923, 52345},
{0, 0}, {7874, 53962}, {7846, 52418}, {0, 0}, {0, 0}, {7890, 52436}, {210, 52303},
{7910, 53845}, {0, 0}, {7858, 53955}, {0, 0}, {7878, 62154}, {258, 195}, {0, 0},
{0, 0}, {7894, 57044}, {0, 0}, {0, 0}, {0, 0}, {7862, 62147}, {7925, 62073},
{245, 56943}, {7920, 62173}, {0, 0}, {272, 208}, {7841, 62049}, {417, 245}, {0, 0},
{0, 0}, {0, 0}, {7905, 57077}, {0, 0}, {0, 0}, {0, 0}, {7873, 52458},
{7852, 62146}, {7922, 52313}, {242, 52335}, {7889, 60660}, {0, 0}, {7916, 53981}, {236, 52329},
{7857, 52451}, {0, 0}, {7884, 62031}, {204, 52297}, {7926, 53849}, {0, 0}, {7900, 52437},
{7847, 52450}, {7849, 53986}, {7848, 53954}, {7868, 56901}, {0, 0}, {7911, 53877}, {7913, 60669},
{7912, 60637}, {0, 0}, {7879, 62186}, {7881, 53865}, {7880, 53833}, {0, 0}, {7895, 57076},
{7897, 62196}, {7896, 62164}, {7853, 62178}, {7863, 62179}, {7865, 62053}, {7864, 62021}, {7921, 62205},
{7917, 54013}, {273, 240}, {7851, 57058}, {0, 0}, {7885, 62063}, {7854, 60611}, {0, 0},
{7915, 52477}, {7901, 52469}, {221, 60505}, {7918, 57053}, {7883, 62057}, {7869, 56933}, {0, 0},
{7886, 53839}, {7899, 60661}, {0, 0}, {0, 0}, {7902, 53973}, {7867, 53861}, {0, 0},
{7850, 57026}, {7870, 60618}, {7927, 53881}, {7929, 56953}, {7928, 56921}, {7914, 52445}, {0, 0},
{0, 0}, {0, 0}, {7882, 62025}, {0, 0}, {0, 0}, {0, 0}, {7898, 60629},
{0, 0}, {0, 0}, {0, 0}, {7866, 53829}, {0, 0}, {253, 60537}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {119, 117}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {297, 56937}, {296, 56905}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {361, 56949}, {360, 56917},
}};
constexpr char16_t kMinVnUtf16 = 119;
constexpr char16_t kMaxVnUtf16 = 7929;
if (wch > kMaxVnUtf16 || wch < kMinVnUtf16) return 0;
const auto key = vnUtf16ToCp1258PerfHash(wch);
if (key >= vnUtf16ToCp1258Mapping.size()) return 0;
const auto& u16_cp1258 = vnUtf16ToCp1258Mapping[key]; // NOLINT
return wch == u16_cp1258.first ? u16_cp1258.second : 0;
}
(cái hàm findVnUtf16ToCp1258Char
đáng lẽ xài std::unordered_map
chứa cái bảng mapping kia được rồi toy rảnh nên xài gperf
tìm perfect hash cho cái bảng này)