Skip to content

Commit d94eea3

Browse files
committed
Support windows-1252 when ICU is disabled
Mostly for testing purposes.
1 parent 1aeebc1 commit d94eea3

4 files changed

Lines changed: 77 additions & 12 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ project(liblcf VERSION 0.8 LANGUAGES CXX)
88

99
# Compilation options
1010
option(BUILD_SHARED_LIBS "Build shared library, disable for building the static library (default: ON)" ON)
11-
option(LIBLCF_WITH_ICU "ICU encoding handling (disable only for testing purposes, default: ON)" ON)
11+
option(LIBLCF_WITH_ICU "ICU encoding handling (when disabled only windows-1252 is supported, default: ON)" ON)
1212
option(LIBLCF_WITH_XML "XML reading support (expat, default: ON)" ON)
1313
option(LIBLCF_UPDATE_MIMEDB "Whether to run update-mime-database after install (default: ON)" ON)
1414
option(LIBLCF_ENABLE_TOOLS "Whether to build the tools (default: ON)" ON)

‎configure.ac‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ AM_CONDITIONAL(CROSS_COMPILING,[test "x$cross_compiling" = "xyes"])
2222

2323
# Checks for libraries.
2424
AC_SUBST([LCF_SUPPORT_ICU],[0])
25-
AC_ARG_ENABLE([icu],[AS_HELP_STRING([--disable-icu],[Disable ICU encoding detection (only for testing purposes) [default=no]])])
25+
AC_ARG_ENABLE([icu],[AS_HELP_STRING([--disable-icu],[Disable ICU encoding handling (only windows-1252 supported) [default=no]])])
2626
AS_IF([test "x$enable_icu" != "xno"],[
2727
AX_PKG_CHECK_MODULES([ICU],[],[icu-i18n],[LCF_SUPPORT_ICU=1])
2828
])

‎src/encoder.cpp‎

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818
# include <unicode/ucsdet.h>
1919
# include <unicode/ucnv.h>
2020
#else
21-
# ifdef _MSC_VER
22-
# error MSVC builds require ICU
23-
# endif
21+
# include <cstdint>
2422
#endif
2523

2624
#ifdef _WIN32
@@ -73,7 +71,6 @@ void Encoder::Decode(std::string& str) {
7371
Convert(str, _conv_storage, _conv_runtime);
7472
}
7573

76-
#if LCF_SUPPORT_ICU
7774
void Encoder::Init() {
7875
if (_encoding.empty()) {
7976
return;
@@ -84,6 +81,7 @@ void Encoder::Init() {
8481
? ReaderUtil::CodepageToEncoding(code_page)
8582
: _encoding;
8683

84+
#if LCF_SUPPORT_ICU
8785
auto status = U_ZERO_ERROR;
8886
constexpr auto runtime_encoding = "UTF-8";
8987
auto conv_runtime = ucnv_open(runtime_encoding, &status);
@@ -106,8 +104,17 @@ void Encoder::Init() {
106104

107105
_conv_runtime = conv_runtime;
108106
_conv_storage = conv_storage;
107+
#else
108+
if (storage_encoding != "windows-1252") {
109+
return;
110+
}
111+
112+
_conv_runtime = 65001;
113+
_conv_storage = 1252;
114+
#endif
109115
}
110116

117+
#if LCF_SUPPORT_ICU
111118
void Encoder::Reset() {
112119
if (_conv_runtime) {
113120
ucnv_close(_conv_runtime);
@@ -143,7 +150,64 @@ void Encoder::Convert(std::string& str, UConverter* conv_dst, UConverter* conv_s
143150

144151
str.assign(_buffer.data(), dst_p);
145152
}
153+
#else
154+
void Encoder::Convert(std::string& str, int conv_dst, int) {
155+
if (str.empty()) {
156+
return;
157+
}
158+
159+
size_t buf_idx = 0;
160+
161+
if (conv_dst == 65001) {
162+
// From 1252 to UTF-8
163+
// Based on https://stackoverflow.com/q/4059775/
164+
_buffer.resize(str.size() * 2 + 1);
165+
166+
for (unsigned char ch: str) {
167+
if (ch < 0x80) {
168+
_buffer[buf_idx] = static_cast<char>(ch);
169+
} else {
170+
_buffer[buf_idx] = static_cast<char>(0xC0 | (ch >> 6));
171+
++buf_idx;
172+
_buffer[buf_idx] = static_cast<char>(0x80 | (ch & 0x3F));
173+
}
174+
175+
++buf_idx;
176+
}
177+
} else {
178+
// From UTF-8 to 1252
179+
// Based on https://stackoverflow.com/q/23689733/
180+
_buffer.resize(str.size() + 1);
181+
uint32_t codepoint;
182+
183+
for (size_t str_idx = 0; str_idx < str.size(); ++str_idx) {
184+
unsigned char ch = str[str_idx];
185+
if (ch <= 0x7F) {
186+
codepoint = ch;
187+
} else if (ch <= 0xBF) {
188+
codepoint = (codepoint << 6) | (ch & 0x3F);
189+
} else if (ch <= 0xDF) {
190+
codepoint = ch & 0x1F;
191+
} else if (ch <= 0xEF) {
192+
codepoint = ch & 0x0F;
193+
} else {
194+
codepoint = ch & 0x07;
195+
}
196+
++str_idx;
197+
ch = str[str_idx];
198+
if (((ch & 0xC0) != 0x80) && (codepoint <= 0x10ffff)) {
199+
if (codepoint <= 255) {
200+
_buffer[buf_idx] = static_cast<char>(codepoint);
201+
} else {
202+
_buffer[buf_idx] = '?';
203+
}
204+
}
205+
++buf_idx;
206+
}
207+
}
208+
209+
str.assign(_buffer.data(), buf_idx);
210+
}
146211
#endif
147212

148213
} //namespace lcf
149-

‎src/lcf/encoder.h‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ class Encoder {
5252

5353
UConverter* _conv_storage = nullptr;
5454
UConverter* _conv_runtime = nullptr;
55-
std::vector<char> _buffer;
5655
#else
57-
void Init() {}
56+
void Init();
5857
void Reset() {}
59-
void Convert(std::string&, void*, void*) {}
60-
void* _conv_storage = nullptr;
61-
void* _conv_runtime = nullptr;
58+
void Convert(std::string& str, int conv_dst, int conv_src);
59+
60+
int _conv_storage = 0;
61+
int _conv_runtime = 0;
6262
#endif
63+
std::vector<char> _buffer;
6364
std::string _encoding;
6465
};
6566

0 commit comments

Comments
 (0)