BibleTime
cp1252.cpp
Go to the documentation of this file.
1/*********
2*
3* In the name of the Father, and of the Son, and of the Holy Spirit.
4*
5* This file is part of BibleTime's source code, https://bibletime.info/
6*
7* Copyright 1999-2026 by the BibleTime developers.
8* The BibleTime source code is licensed under the GNU General Public License
9* version 2.0.
10*
11**********/
12
13#include "cp1252.h"
14
15#ifdef BT_CP1252_USE_QT
16#include <QStringDecoder>
17#include <QStringEncoder>
18#else
19#include <QDebug>
20#include <optional>
21#include <unicode/ucnv.h>
22#include "btassert.h"
23#endif
24
25
26namespace util {
27namespace cp1252 {
28
29#ifdef BT_CP1252_USE_QT
30
31QString toUnicode(QByteArray const & data, bool & error) {
32 QStringDecoder decoder("Windows-1252", QStringDecoder::Flag::Stateless);
33 // Do not use auto here due to QTBUG-117705/QTBUG-117902:
34 QString result = decoder(data);
35 error = decoder.hasError();
36 return result;
37}
38
39QByteArray fromUnicode(QString const & str, bool & error) {
40 QStringEncoder encoder("Windows-1252", QStringEncoder::Flag::Stateless);
41 // Do not use auto here due to QTBUG-117705/QTBUG-117902:
42 QByteArray result = encoder(str);
43 error = encoder.hasError();
44 return result;
45}
46
47#else
48
49namespace {
50
51class Converter final {
52
53public: // Methods:
54
56 : m_converter([]{
57 ::UErrorCode err = ::U_ZERO_ERROR;
58 auto const r = ::ucnv_open("cp1252", &err);
59 if (::U_FAILURE(err))
60 qFatal() << "Failed to initialize CP1252 converter:"
61 << ::u_errorName(err);
62 return r;
63 }())
64 { BT_ASSERT(m_converter); }
65
66 Converter(Converter &&) = delete;
67 Converter(Converter const &) = delete;
68
69 ~Converter() { ::ucnv_close(m_converter); }
70
72 Converter & operator=(Converter const &) = delete;
73
74 QString toUnicode(QByteArray const & data, bool & error) {
75 ::UErrorCode err = ::U_ZERO_ERROR;
76 auto const length =
77 ::ucnv_toUChars(
78 m_converter,
79 nullptr,
80 0,
81 data.constData(),
82 data.size(),
83 &err);
84 QString result;
85 if (err == ::U_BUFFER_OVERFLOW_ERROR) {
86 result.resize(length, '?');
87 err = ::U_ZERO_ERROR;
88 ::ucnv_toUChars(
89 m_converter,
90 reinterpret_cast<::UChar *>(result.data()),
91 length,
92 data.constData(),
93 data.size(),
94 &err);
95 }
96 error = ::U_FAILURE(err);
97 return result;
98 }
99
100 QByteArray fromUnicode(QString const & str, bool & error) {
101 ::UErrorCode err = ::U_ZERO_ERROR;
102 auto const length =
103 ucnv_fromUChars(
104 m_converter,
105 nullptr,
106 0,
107 reinterpret_cast<::UChar const *>(str.constData()),
108 str.size(),
109 &err);
110 QByteArray result;
111 if (err == ::U_BUFFER_OVERFLOW_ERROR) {
112 result.resize(length, '?');
113 err = ::U_ZERO_ERROR;
114 ::ucnv_fromUChars(
115 m_converter,
116 result.data(),
117 length,
118 reinterpret_cast<::UChar const *>(str.constData()),
119 str.size(),
120 &err);
121 }
122 error = ::U_FAILURE(err);
123 return result;
124 }
125
126private: // Fields:
127
128 UConverter * const m_converter;
129
130};
131
132thread_local std::optional<Converter> tl_converter;
133
135 if (!tl_converter.has_value())
136 tl_converter.emplace();
137 return *tl_converter;
138}
139
140} // anonymous namespace
141
142QString toUnicode(QByteArray const & data, bool & error)
143{ return getConverter().toUnicode(data, error); }
144
145QByteArray fromUnicode(QString const & str, bool & error)
146{ return getConverter().fromUnicode(str, error); }
147
148#endif
149
150} /* namespace cp1252 { */
151} /* namespace util { */
#define BT_ASSERT(...)
Definition btassert.h:17
QByteArray fromUnicode(QString const &str, bool &error)
Definition cp1252.cpp:100
Converter & operator=(Converter const &)=delete
QString toUnicode(QByteArray const &data, bool &error)
Definition cp1252.cpp:74
QStringList r(content.left(bodyIndex))
thread_local std::optional< Converter > tl_converter
Definition cp1252.cpp:132
QByteArray fromUnicode(QString const &str, bool &error)
Definition cp1252.cpp:145
QString toUnicode(QByteArray const &data, bool &error)
Definition cp1252.cpp:142