/src/logging-log4cxx/src/main/cpp/transcoder.cpp
Line | Count | Source |
1 | | /* |
2 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
3 | | * contributor license agreements. See the NOTICE file distributed with |
4 | | * this work for additional information regarding copyright ownership. |
5 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
6 | | * (the "License"); you may not use this file except in compliance with |
7 | | * the License. You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | */ |
17 | | |
18 | | #include <log4cxx/logstring.h> |
19 | | #include <log4cxx/helpers/transcoder.h> |
20 | | #include <log4cxx/helpers/pool.h> |
21 | | #include <stdlib.h> |
22 | | #include <log4cxx/helpers/exception.h> |
23 | | #include <log4cxx/helpers/bytebuffer.h> |
24 | | #include <log4cxx/helpers/charsetdecoder.h> |
25 | | #include <log4cxx/helpers/charsetencoder.h> |
26 | | #include <log4cxx/helpers/stringhelper.h> |
27 | | #include <log4cxx/helpers/loglog.h> |
28 | | #include <vector> |
29 | | #include <cstring> |
30 | | #if !defined(LOG4CXX) |
31 | | #define LOG4CXX 1 |
32 | | #endif |
33 | | #include <log4cxx/private/log4cxx_private.h> |
34 | | |
35 | | #if LOG4CXX_CFSTRING_API |
36 | | #include <CoreFoundation/CFString.h> |
37 | | #endif |
38 | | |
39 | | using namespace LOG4CXX_NS; |
40 | | using namespace LOG4CXX_NS::helpers; |
41 | | |
42 | | void Transcoder::decodeUTF8(const std::string& src, LogString& dst) |
43 | 0 | { |
44 | 0 | std::string::const_iterator iter = src.begin(); |
45 | |
|
46 | 0 | while (iter != src.end()) |
47 | 0 | { |
48 | 0 | auto sv = getCodePoint(src, iter); |
49 | 0 | encode(sv, dst); |
50 | 0 | } |
51 | 0 | } |
52 | | |
53 | | void Transcoder::encodeUTF8(const LogString& src, std::string& dst) |
54 | 0 | { |
55 | 0 | #if LOG4CXX_LOGCHAR_IS_UTF8 |
56 | 0 | dst.append(src); |
57 | | #else |
58 | | LogString::const_iterator iter = src.begin(); |
59 | | |
60 | | while (iter != src.end()) |
61 | | { |
62 | | unsigned int sv = getCodePoint(src, iter); |
63 | | encode(sv, dst); |
64 | | } |
65 | | |
66 | | #endif |
67 | 0 | } |
68 | | |
69 | | #if LOG4CXX_ABI_VERSION <= 15 |
70 | | char* Transcoder::encodeUTF8(const LogString& src, Pool& p) |
71 | 0 | { |
72 | 0 | #if LOG4CXX_LOGCHAR_IS_UTF8 |
73 | 0 | return p.pstrdup(src); |
74 | | #else |
75 | | std::string tmp; |
76 | | encodeUTF8(src, tmp); |
77 | | return p.pstrdup(tmp); |
78 | | #endif |
79 | 0 | } |
80 | | #endif |
81 | | |
82 | | void Transcoder::encodeUTF8(unsigned int sv, ByteBuffer& dst) |
83 | 0 | { |
84 | 0 | size_t bytes = encodeUTF8(sv, dst.current()); |
85 | 0 | dst.increment_position(bytes); |
86 | 0 | } |
87 | | |
88 | | |
89 | | size_t Transcoder::encodeUTF8(unsigned int ch, char* dst) |
90 | 0 | { |
91 | 0 | if (ch < 0x80) |
92 | 0 | { |
93 | 0 | dst[0] = (char) ch; |
94 | 0 | return 1; |
95 | 0 | } |
96 | 0 | else if (ch < 0x800) |
97 | 0 | { |
98 | 0 | dst[0] = (char) (0xC0 + (ch >> 6)); |
99 | 0 | dst[1] = (char) (0x80 + (ch & 0x3F)); |
100 | 0 | return 2; |
101 | 0 | } |
102 | 0 | else if (ch < 0x10000) |
103 | 0 | { |
104 | 0 | dst[0] = (char) (0xE0 + (ch >> 12)); |
105 | 0 | dst[1] = (char) (0x80 + ((ch >> 6) & 0x3F)); |
106 | 0 | dst[2] = (char) (0x80 + (ch & 0x3F)); |
107 | 0 | return 3; |
108 | 0 | } |
109 | 0 | else if (ch <= 0x10FFFF) |
110 | 0 | { |
111 | 0 | dst[0] = (char) (0xF0 + (ch >> 18)); |
112 | 0 | dst[1] = (char) (0x80 + ((ch >> 12) & 0x3F)); |
113 | 0 | dst[2] = (char) (0x80 + ((ch >> 6) & 0x3F)); |
114 | 0 | dst[3] = (char) (0x80 + (ch & 0x3F)); |
115 | 0 | return 4; |
116 | 0 | } |
117 | 0 | else |
118 | 0 | { |
119 | | // |
120 | | // output UTF-8 encoding of 0xFFFF |
121 | | // |
122 | 0 | dst[0] = (char) 0xEF; |
123 | 0 | dst[1] = (char) 0xBF; |
124 | 0 | dst[2] = (char) 0xBF; |
125 | 0 | return 3; |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | | void Transcoder::encodeUTF16BE(unsigned int sv, ByteBuffer& dst) |
130 | 0 | { |
131 | 0 | size_t bytes = encodeUTF16BE(sv, dst.current()); |
132 | 0 | dst.increment_position(bytes); |
133 | 0 | } |
134 | | |
135 | | |
136 | | size_t Transcoder::encodeUTF16BE(unsigned int ch, char* dst) |
137 | 0 | { |
138 | 0 | if (ch <= 0xFFFF) |
139 | 0 | { |
140 | 0 | dst[0] = (char) (ch >> 8); |
141 | 0 | dst[1] = (char) (ch & 0xFF); |
142 | 0 | return 2; |
143 | 0 | } |
144 | | |
145 | 0 | if (ch <= 0x10FFFF) |
146 | 0 | { |
147 | 0 | unsigned char w = (unsigned char) ((ch >> 16) - 1); |
148 | 0 | dst[0] = (char) (0xD8 + (w >> 2)); |
149 | 0 | dst[1] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F)); |
150 | 0 | dst[2] = (char) (0xDC + ((ch >> 8) & 0x03)); |
151 | 0 | dst[3] = (char) (ch & 0xFF); |
152 | 0 | return 4; |
153 | 0 | } |
154 | | |
155 | 0 | dst[0] = dst[1] = (char) 0xFF; |
156 | 0 | return 2; |
157 | 0 | } |
158 | | |
159 | | void Transcoder::encodeUTF16LE(unsigned int sv, ByteBuffer& dst) |
160 | 0 | { |
161 | 0 | size_t bytes = encodeUTF16LE(sv, dst.current()); |
162 | 0 | dst.increment_position(bytes); |
163 | 0 | } |
164 | | |
165 | | size_t Transcoder::encodeUTF16LE(unsigned int ch, char* dst) |
166 | 0 | { |
167 | 0 | if (ch <= 0xFFFF) |
168 | 0 | { |
169 | 0 | dst[1] = (char) (ch >> 8); |
170 | 0 | dst[0] = (char) (ch & 0xFF); |
171 | 0 | return 2; |
172 | 0 | } |
173 | | |
174 | 0 | if (ch <= 0x10FFFF) |
175 | 0 | { |
176 | 0 | unsigned char w = (unsigned char) ((ch >> 16) - 1); |
177 | 0 | dst[1] = (char) (0xD8 + (w >> 2)); |
178 | 0 | dst[0] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F)); |
179 | 0 | dst[3] = (char) (0xDC + ((ch >> 8) & 0x03)); |
180 | 0 | dst[2] = (char) (ch & 0xFF); |
181 | 0 | return 4; |
182 | 0 | } |
183 | | |
184 | 0 | dst[0] = dst[1] = (char) 0xFF; |
185 | 0 | return 2; |
186 | 0 | } |
187 | | |
188 | | |
189 | | unsigned int Transcoder::decode(const std::string& src, |
190 | | std::string::const_iterator& iter) |
191 | 934k | { |
192 | 934k | auto offset = iter - src.begin(); |
193 | 934k | auto remaining = src.size() - offset; |
194 | 934k | ByteBuffer buf(const_cast<char*>(src.data() + offset), remaining); |
195 | 934k | auto result = CharsetDecoder::getUTF8CodePoint(buf); |
196 | 934k | iter += remaining - buf.remaining(); |
197 | 934k | return result; |
198 | 934k | } |
199 | | |
200 | | template <typename T> |
201 | | unsigned int decodeCodePoint(const typename std::basic_string<T>& str, typename std::basic_string<T>::const_iterator& nextCodePoint) |
202 | 823k | { |
203 | 823k | auto lastCodePoint = nextCodePoint; |
204 | 823k | auto ch = Transcoder::decode(str, nextCodePoint); |
205 | 823k | if (nextCodePoint == lastCodePoint) // failed to decode input? |
206 | 29.0k | { |
207 | | // Skip the undecodable run and keep escaping the remaining input |
208 | | // instead of discarding it; the run collapses to one replacement. |
209 | 111k | for (++nextCodePoint; nextCodePoint != str.end(); ++nextCodePoint) |
210 | 110k | { |
211 | 110k | auto probe = nextCodePoint; |
212 | 110k | Transcoder::decode(str, probe); |
213 | 110k | if (probe != nextCodePoint) // next unit starts a decodable sequence |
214 | 28.0k | break; |
215 | 110k | } |
216 | 29.0k | ch = 0xFFFD; // The Unicode replacement character |
217 | 29.0k | } |
218 | 794k | else if ( (0xD800 <= ch && ch <= 0xDFFF) // UTF-16 surrogate-range |
219 | 794k | || 0xFFFF == ch || 0x10FFFF < ch) |
220 | 401 | { |
221 | 401 | ch = 0xFFFD; // The Unicode replacement character |
222 | 401 | } |
223 | 823k | return ch; |
224 | 823k | } unsigned int decodeCodePoint<char>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::const_iterator&) Line | Count | Source | 202 | 823k | { | 203 | 823k | auto lastCodePoint = nextCodePoint; | 204 | 823k | auto ch = Transcoder::decode(str, nextCodePoint); | 205 | 823k | if (nextCodePoint == lastCodePoint) // failed to decode input? | 206 | 29.0k | { | 207 | | // Skip the undecodable run and keep escaping the remaining input | 208 | | // instead of discarding it; the run collapses to one replacement. | 209 | 111k | for (++nextCodePoint; nextCodePoint != str.end(); ++nextCodePoint) | 210 | 110k | { | 211 | 110k | auto probe = nextCodePoint; | 212 | 110k | Transcoder::decode(str, probe); | 213 | 110k | if (probe != nextCodePoint) // next unit starts a decodable sequence | 214 | 28.0k | break; | 215 | 110k | } | 216 | 29.0k | ch = 0xFFFD; // The Unicode replacement character | 217 | 29.0k | } | 218 | 794k | else if ( (0xD800 <= ch && ch <= 0xDFFF) // UTF-16 surrogate-range | 219 | 794k | || 0xFFFF == ch || 0x10FFFF < ch) | 220 | 401 | { | 221 | 401 | ch = 0xFFFD; // The Unicode replacement character | 222 | 401 | } | 223 | 823k | return ch; | 224 | 823k | } |
Unexecuted instantiation: unsigned int decodeCodePoint<wchar_t>(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >::const_iterator&) |
225 | | |
226 | | unsigned int Transcoder::getCodePoint(const std::string& str, std::string::const_iterator& nextCodePoint) |
227 | 823k | { |
228 | 823k | return decodeCodePoint<char>(str, nextCodePoint); |
229 | 823k | } |
230 | | |
231 | | void Transcoder::encode(unsigned int sv, std::string& dst) |
232 | 0 | { |
233 | 0 | char tmp[8]; |
234 | 0 | size_t bytes = encodeUTF8(sv, tmp); |
235 | 0 | dst.append(tmp, bytes); |
236 | 0 | } |
237 | | |
238 | | /// Does \c str contain the Unicode replacement character |
239 | | bool Transcoder::hasReplacementCharacter(const std::string& str) |
240 | 0 | { |
241 | 0 | return str.npos != str.find("\xEF\xBF\xBD"); |
242 | 0 | } |
243 | | |
244 | | void Transcoder::decode(const std::string& src, LogString& dst) |
245 | 38.8k | { |
246 | 38.8k | #if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8 |
247 | 38.8k | dst.append(src); |
248 | | #else |
249 | | static CharsetDecoderPtr decoder(CharsetDecoder::getDefaultDecoder()); |
250 | | dst.reserve(dst.size() + src.size()); |
251 | | std::string::const_iterator iter = src.begin(); |
252 | | #if !LOG4CXX_CHARSET_EBCDIC |
253 | | |
254 | | for (; |
255 | | iter != src.end() && ((unsigned char) *iter) < 0x80; |
256 | | iter++) |
257 | | { |
258 | | dst.append(1, *iter); |
259 | | } |
260 | | |
261 | | #endif |
262 | | |
263 | | if (iter != src.end()) |
264 | | { |
265 | | size_t offset = iter - src.begin(); |
266 | | ByteBuffer buf(const_cast<char*>(src.data() + offset), src.size() - offset); |
267 | | |
268 | | while (buf.remaining() > 0) |
269 | | { |
270 | | log4cxx_status_t stat = decoder->decode(buf, dst); |
271 | | |
272 | | if (CharsetDecoder::isError(stat)) |
273 | | { |
274 | | encode(LOSSCHAR, dst); |
275 | | buf.increment_position(1); |
276 | | } |
277 | | } |
278 | | |
279 | | decoder->decode(buf, dst); |
280 | | } |
281 | | |
282 | | #endif |
283 | 38.8k | } |
284 | | |
285 | | #if LOG4CXX_ABI_VERSION <= 15 |
286 | | char* Transcoder::encode(const LogString& src, Pool& p) |
287 | 0 | { |
288 | 0 | #if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8 |
289 | 0 | return p.pstrdup(src); |
290 | | #else |
291 | | std::string tmp; |
292 | | encode(src, tmp); |
293 | | return p.pstrdup(tmp); |
294 | | #endif |
295 | 0 | } |
296 | | #endif |
297 | | |
298 | | |
299 | | void Transcoder::encode(const LogString& src, std::string& dst) |
300 | 2.18k | { |
301 | 2.18k | #if LOG4CXX_CHARSET_UTF8 && LOG4CXX_LOGCHAR_IS_UTF8 |
302 | 2.18k | dst.append(src); |
303 | | #else |
304 | | static CharsetEncoderPtr encoder(CharsetEncoder::getDefaultEncoder()); |
305 | | dst.reserve(dst.size() + src.size()); |
306 | | LogString::const_iterator iter = src.begin(); |
307 | | #if !LOG4CXX_CHARSET_EBCDIC |
308 | | |
309 | | for (; |
310 | | iter != src.end() && ((unsigned int) *iter) < 0x80; |
311 | | iter++) |
312 | | { |
313 | | dst.append(1, static_cast<char>(*iter)); |
314 | | } |
315 | | |
316 | | #endif |
317 | | |
318 | | if (iter != src.end()) |
319 | | { |
320 | | char buf[BUFSIZE]; |
321 | | ByteBuffer out(buf, BUFSIZE); |
322 | | |
323 | | while (iter != src.end()) |
324 | | { |
325 | | log4cxx_status_t stat = encoder->encode(src, iter, out); |
326 | | out.flip(); |
327 | | dst.append(out.data(), out.limit()); |
328 | | out.clear(); |
329 | | |
330 | | if (CharsetEncoder::isError(stat)) |
331 | | { |
332 | | encode(LOSSCHAR, dst); |
333 | | iter++; |
334 | | } |
335 | | } |
336 | | |
337 | | encoder->encode(src, iter, out); |
338 | | } |
339 | | |
340 | | #endif |
341 | 2.18k | } |
342 | | |
343 | | |
344 | | template<class String, class Iterator> |
345 | | static unsigned int decodeUTF16(const String& in, Iterator& iter) |
346 | | { |
347 | | unsigned int ch1 = *iter; |
348 | | |
349 | | // |
350 | | // if not surrogate pair |
351 | | // |
352 | | if (ch1 < 0xD800 || ch1 > 0xDFFF) |
353 | | { |
354 | | // |
355 | | // then advance iterator and return wchar_t value |
356 | | // |
357 | | if (ch1 != 0xFFFF) |
358 | | { |
359 | | iter++; |
360 | | } |
361 | | |
362 | | return ch1; |
363 | | } |
364 | | else if (ch1 < 0xDC00) |
365 | | { |
366 | | // |
367 | | // started with high-surrogate value |
368 | | // if there is an additional wchar_t |
369 | | Iterator iter2 = iter + 1; |
370 | | |
371 | | if (iter2 != in.end()) |
372 | | { |
373 | | unsigned int ch2 = *iter2; |
374 | | |
375 | | // |
376 | | // if it is a matching low surrogate then |
377 | | // advance the iterator and return the scalar value |
378 | | if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) |
379 | | { |
380 | | iter += 2; |
381 | | return (ch1 - 0xD800) * 0x400 + (ch2 - 0xDC00) + 0x10000; |
382 | | } |
383 | | } |
384 | | } |
385 | | |
386 | | // |
387 | | // unrecognized value, do not advance iterator |
388 | | // |
389 | | return 0xFFFF; |
390 | | } |
391 | | |
392 | | template<class String> |
393 | | static void encodeUTF16(unsigned int sv, String& dst) |
394 | | { |
395 | | if (sv < 0x10000) |
396 | | { |
397 | | dst.append(1, sv); |
398 | | } |
399 | | else |
400 | | { |
401 | | unsigned char u = (unsigned char) (sv >> 16); |
402 | | unsigned char w = (unsigned char) (u - 1); |
403 | | unsigned short hs = (0xD800 + ((w & 0xF) << 6) + ((sv & 0xFFFF) >> 10)); |
404 | | unsigned short ls = (0xDC00 + (sv & 0x3FF)); |
405 | | dst.append(1, hs); |
406 | | dst.append(1, ls); |
407 | | } |
408 | | } |
409 | | |
410 | | |
411 | | |
412 | | #if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR || defined(WIN32) || defined(_WIN32) |
413 | | void Transcoder::decode(const std::wstring& src, LogString& dst) |
414 | 0 | { |
415 | | #if LOG4CXX_LOGCHAR_IS_WCHAR |
416 | | dst.append(src); |
417 | | #else |
418 | 0 | std::wstring::const_iterator i = src.begin(); |
419 | |
|
420 | 0 | while (i != src.end()) |
421 | 0 | { |
422 | 0 | auto cp = getCodePoint(src, i); |
423 | 0 | encode(cp, dst); |
424 | 0 | } |
425 | |
|
426 | 0 | #endif |
427 | 0 | } |
428 | | |
429 | | void Transcoder::encode(const LogString& src, std::wstring& dst) |
430 | 0 | { |
431 | | #if LOG4CXX_LOGCHAR_IS_WCHAR |
432 | | dst.append(src); |
433 | | #else |
434 | |
|
435 | 0 | for (LogString::const_iterator i = src.begin(); i != src.end();) |
436 | 0 | { |
437 | 0 | unsigned int cp = getCodePoint(src, i); |
438 | 0 | encode(cp, dst); |
439 | 0 | } |
440 | |
|
441 | 0 | #endif |
442 | 0 | } |
443 | | |
444 | | #if LOG4CXX_ABI_VERSION <= 15 |
445 | | wchar_t* Transcoder::wencode(const LogString& src, Pool& p) |
446 | 0 | { |
447 | | #if LOG4CXX_LOGCHAR_IS_WCHAR |
448 | | const std::wstring& tmp = src; |
449 | | #else |
450 | 0 | std::wstring tmp; |
451 | 0 | encode(src, tmp); |
452 | 0 | #endif |
453 | 0 | wchar_t* dst = (wchar_t*) p.palloc((tmp.length() + 1) * sizeof(wchar_t)); |
454 | 0 | dst[tmp.length()] = 0; |
455 | 0 | std::memcpy(dst, tmp.data(), tmp.length() * sizeof(wchar_t)); |
456 | 0 | return dst; |
457 | 0 | } |
458 | | #endif |
459 | | |
460 | | unsigned int Transcoder::decode(const std::wstring& in, |
461 | | std::wstring::const_iterator& iter) |
462 | 0 | { |
463 | 0 | #if defined(__STDC_ISO_10646__) |
464 | 0 | return *(iter++); |
465 | | #else |
466 | | return decodeUTF16(in, iter); |
467 | | #endif |
468 | 0 | } |
469 | | |
470 | | unsigned int Transcoder::getCodePoint(const std::wstring& str, std::wstring::const_iterator& nextCodePoint) |
471 | 0 | { |
472 | 0 | return decodeCodePoint<wchar_t>(str, nextCodePoint); |
473 | 0 | } |
474 | | |
475 | | void Transcoder::encode(unsigned int sv, std::wstring& dst) |
476 | 0 | { |
477 | 0 | #if defined(__STDC_ISO_10646__) |
478 | 0 | dst.append(1, sv); |
479 | | #else |
480 | | |
481 | | if (sizeof(wchar_t) == 4) |
482 | | { |
483 | | dst.append(1, sv); |
484 | | } |
485 | | else |
486 | | { |
487 | | encodeUTF16(sv, dst); |
488 | | } |
489 | | |
490 | | #endif |
491 | 0 | } |
492 | | |
493 | | /// Does \c str contain the Unicode replacement character |
494 | | bool Transcoder::hasReplacementCharacter(const std::wstring& str) |
495 | 0 | { |
496 | 0 | return str.npos != str.find(LOSSCHAR); |
497 | 0 | } |
498 | | #endif |
499 | | |
500 | | |
501 | | |
502 | | #if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR |
503 | | void Transcoder::decode(const std::basic_string<UniChar>& src, LogString& dst) |
504 | | { |
505 | | #if LOG4CXX_LOGCHAR_IS_UNICHAR |
506 | | dst.append(src); |
507 | | #else |
508 | | |
509 | | for (std::basic_string<UniChar>::const_iterator i = src.begin(); |
510 | | i != src.end();) |
511 | | { |
512 | | std::basic_string<UniChar>::const_iterator start = i; |
513 | | unsigned int cp = decode(src, i); |
514 | | |
515 | | if (cp != 0xFFFF) |
516 | | { |
517 | | encode(cp, dst); |
518 | | } |
519 | | else |
520 | | { |
521 | | encode(LOSSCHAR, dst); |
522 | | if (i == start) |
523 | | { |
524 | | i++; |
525 | | } |
526 | | } |
527 | | } |
528 | | |
529 | | #endif |
530 | | } |
531 | | |
532 | | void Transcoder::encode(const LogString& src, std::basic_string<UniChar>& dst) |
533 | | { |
534 | | #if LOG4CXX_LOGCHAR_IS_UNICHAR |
535 | | dst.append(src); |
536 | | #else |
537 | | |
538 | | for (LogString::const_iterator i = src.begin(); |
539 | | i != src.end();) |
540 | | { |
541 | | LogString::const_iterator start = i; |
542 | | unsigned int cp = decode(src, i); |
543 | | |
544 | | if (cp != 0xFFFF) |
545 | | { |
546 | | encode(cp, dst); |
547 | | } |
548 | | else |
549 | | { |
550 | | encode(LOSSCHAR, dst); |
551 | | if (i == start) |
552 | | { |
553 | | i++; |
554 | | } |
555 | | } |
556 | | } |
557 | | |
558 | | #endif |
559 | | } |
560 | | |
561 | | unsigned int Transcoder::decode(const std::basic_string<UniChar>& in, |
562 | | std::basic_string<UniChar>::const_iterator& iter) |
563 | | { |
564 | | return decodeUTF16(in, iter); |
565 | | } |
566 | | |
567 | | unsigned int Transcoder::getCodePoint(const std::basic_string<UniChar>& str, std::basic_string<UniChar>::const_iterator& nextCodePoint) |
568 | | { |
569 | | return decodeCodePoint<UniChar>(str, nextCodePoint); |
570 | | } |
571 | | |
572 | | void Transcoder::encode(unsigned int sv, std::basic_string<UniChar>& dst) |
573 | | { |
574 | | encodeUTF16(sv, dst); |
575 | | } |
576 | | |
577 | | /// Does \c str contain the Unicode replacement character |
578 | | bool Transcoder::hasReplacementCharacter(const std::basic_string<UniChar>& str) |
579 | | { |
580 | | return str.npos != str.find(LOSSCHAR); |
581 | | } |
582 | | #endif |
583 | | |
584 | | #if LOG4CXX_CFSTRING_API |
585 | | void Transcoder::decode(const CFStringRef& src, LogString& dst) |
586 | | { |
587 | | auto length = CFStringGetLength(src); |
588 | | #if defined(_DEBUG) |
589 | | if (LogLog::isDebugEnabled()) |
590 | | { |
591 | | LogString msg(LOG4CXX_STR("Transcoder::decodeCFString")); |
592 | | msg += LOG4CXX_STR(" length "); |
593 | | StringHelper::toString((size_t)length, msg); |
594 | | LogLog::debug(msg); |
595 | | } |
596 | | #endif |
597 | | |
598 | | if (length > 0) |
599 | | { |
600 | | std::vector<unsigned short> tmp(length); |
601 | | CFStringGetCharacters(src, CFRangeMake(0, length), &tmp[0]); |
602 | | for (auto i = tmp.begin(); i != tmp.end(); ) |
603 | | { |
604 | | auto start = i; |
605 | | unsigned int cp = decodeUTF16(tmp, i); |
606 | | if (cp != 0xFFFF) |
607 | | { |
608 | | encode(cp, dst); |
609 | | } |
610 | | else |
611 | | { |
612 | | encode(LOSSCHAR, dst); |
613 | | if (i == start) |
614 | | { |
615 | | i++; |
616 | | } |
617 | | } |
618 | | } |
619 | | } |
620 | | } |
621 | | |
622 | | CFStringRef Transcoder::encode(const LogString& src) |
623 | | { |
624 | | std::basic_string<unsigned short> tmp; |
625 | | for (auto ch : src) |
626 | | encodeUTF16(ch, tmp); |
627 | | return CFStringCreateWithCharacters(kCFAllocatorDefault, tmp.data(), tmp.size()); |
628 | | } |
629 | | #endif // #if LOG4CXX_CFSTRING_API |
630 | | |
631 | | |
632 | | logchar Transcoder::decode(char val) |
633 | 0 | { |
634 | | #if LOG4CXX_CHARSET_EBCDIC |
635 | | LogString dst; |
636 | | Transcoder::decode(std::string(1, val), dst); |
637 | | return dst[0]; |
638 | | #else |
639 | 0 | return val; |
640 | 0 | #endif |
641 | 0 | } |
642 | | |
643 | | LogString Transcoder::decode(const char* val) |
644 | 2 | { |
645 | 2 | #if LOG4CXX_LOGCHAR_IS_UTF8 && !LOG4CXX_CHARSET_EBCDIC |
646 | 2 | return val; |
647 | | #else |
648 | | LogString dst; |
649 | | Transcoder::decode(val, dst); |
650 | | return dst; |
651 | | #endif |
652 | 2 | } |
653 | | |
654 | | |
655 | | std::string Transcoder::encodeCharsetName(const LogString& val) |
656 | 0 | { |
657 | 0 | char asciiTable[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', |
658 | 0 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', |
659 | 0 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
660 | 0 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', |
661 | 0 | '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
662 | 0 | 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~' |
663 | 0 | }; |
664 | 0 | std::string out; |
665 | |
|
666 | 0 | for (auto& item : val) |
667 | 0 | { |
668 | 0 | if (item >= 0x20 && item < 0x7F) |
669 | 0 | { |
670 | 0 | out.append(1, asciiTable[item - 0x20]); |
671 | 0 | } |
672 | 0 | else |
673 | 0 | { |
674 | 0 | out.append(1, '?'); |
675 | 0 | } |
676 | 0 | } |
677 | |
|
678 | 0 | return out; |
679 | 0 | } |