Coverage Report

Created: 2026-08-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/charsetencoder.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
#include <log4cxx/logstring.h>
18
#include <log4cxx/helpers/charsetencoder.h>
19
#include <log4cxx/helpers/bytebuffer.h>
20
#include <log4cxx/helpers/exception.h>
21
#include <apr_xlate.h>
22
#include <log4cxx/helpers/stringhelper.h>
23
#include <log4cxx/helpers/transcoder.h>
24
#include <algorithm>
25
26
#if !defined(LOG4CXX)
27
  #define LOG4CXX 1
28
#endif
29
30
#include <log4cxx/private/log4cxx_private.h>
31
#include <apr_portable.h>
32
#include <mutex>
33
34
#ifdef LOG4CXX_HAS_WCSTOMBS
35
  #include <stdlib.h>
36
#endif
37
38
#if 15 < LOG4CXX_ABI_VERSION
39
#define LOG4CXX_16_VIRTUAL_SPECIFIER override
40
#else
41
#define LOG4CXX_16_VIRTUAL_SPECIFIER
42
#endif
43
44
using namespace LOG4CXX_NS;
45
using namespace LOG4CXX_NS::helpers;
46
47
IMPLEMENT_LOG4CXX_OBJECT(CharsetEncoder)
48
49
namespace LOG4CXX_NS
50
{
51
52
namespace helpers
53
{
54
55
#if APR_HAS_XLATE
56
/**
57
* A character encoder implemented using apr_xlate.
58
*/
59
class APRCharsetEncoder : public CharsetEncoder
60
{
61
  public:
62
0
    APRCharsetEncoder(const LogString& topage) : pool()
63
0
    {
64
#if LOG4CXX_LOGCHAR_IS_WCHAR
65
      const char* frompage = "WCHAR_T";
66
#endif
67
0
#if LOG4CXX_LOGCHAR_IS_UTF8
68
0
      const char* frompage = "UTF-8";
69
0
#endif
70
#if LOG4CXX_LOGCHAR_IS_UNICHAR
71
      const char* frompage = "UTF-16";
72
#endif
73
0
      std::string tpage(Transcoder::encodeCharsetName(topage));
74
0
      apr_status_t stat = apr_xlate_open(&convset,
75
0
          tpage.c_str(),
76
0
          frompage,
77
0
          pool.getAPRPool());
78
79
0
      if (stat != APR_SUCCESS)
80
0
      {
81
0
        throw IllegalArgumentException(topage);
82
0
      }
83
0
    }
84
85
    virtual ~APRCharsetEncoder()
86
0
    {
87
0
    }
88
89
    virtual log4cxx_status_t encode(const LogString& in,
90
      LogString::const_iterator& iter,
91
      ByteBuffer& out) override
92
0
    {
93
0
      apr_status_t stat;
94
0
      size_t outbytes_left = out.remaining();
95
0
      size_t initial_outbytes_left = outbytes_left;
96
0
      size_t position = out.position();
97
98
0
      if (iter == in.end())
99
0
      {
100
0
        std::lock_guard<std::mutex> lock(mutex);
101
0
        stat = apr_xlate_conv_buffer(convset, NULL, NULL,
102
0
            out.data() + position, &outbytes_left);
103
0
      }
104
0
      else
105
0
      {
106
0
        LogString::size_type inOffset = (iter - in.begin());
107
0
        apr_size_t inbytes_left =
108
0
          (in.size() - inOffset) * sizeof(LogString::value_type);
109
0
        apr_size_t initial_inbytes_left = inbytes_left;
110
0
        {
111
0
          std::lock_guard<std::mutex> lock(mutex);
112
0
          stat = apr_xlate_conv_buffer(convset,
113
0
              (const char*) (in.data() + inOffset),
114
0
              &inbytes_left,
115
0
              out.data() + position,
116
0
              &outbytes_left);
117
0
        }
118
0
        iter += ((initial_inbytes_left - inbytes_left) / sizeof(LogString::value_type));
119
0
      }
120
121
0
      out.increment_position((initial_outbytes_left - outbytes_left));
122
0
      return stat;
123
0
    }
124
125
    /**
126
     * Add onto \c out an encoded equivalent of \c codePoint.
127
     */
128
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
129
0
    {
130
0
      apr_status_t result = APR_SUCCESS;
131
0
      if (codePoint <= 0x10FFFF)
132
0
        Transcoder::encodeUTF8(codePoint, out);
133
0
      else
134
0
        result = APR_BADARG;
135
0
      return result;
136
0
    }
137
138
  private:
139
    APRCharsetEncoder(const APRCharsetEncoder&);
140
    APRCharsetEncoder& operator=(const APRCharsetEncoder&);
141
    Pool pool;
142
    std::mutex mutex;
143
    apr_xlate_t* convset;
144
};
145
#endif
146
147
#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
148
/**
149
 *  A character encoder implemented using wcstombs.
150
*/
151
class WcstombsCharsetEncoder : public CharsetEncoder
152
{
153
  public:
154
    WcstombsCharsetEncoder()
155
    {
156
    }
157
158
    /**
159
     *   Converts a wchar_t to the default external multibyte encoding.
160
     */
161
    log4cxx_status_t encode(const LogString& in,
162
      LogString::const_iterator& iter,
163
      ByteBuffer& out) override
164
    {
165
      log4cxx_status_t stat = APR_SUCCESS;
166
167
      if (iter != in.end())
168
      {
169
        size_t outbytes_left = out.remaining();
170
        size_t position = out.position();
171
        std::wstring::size_type inOffset = (iter - in.begin());
172
        enum { BUFSIZE = 256 };
173
        wchar_t buf[BUFSIZE];
174
        size_t chunkSize = BUFSIZE - 1;
175
176
        if (chunkSize * MB_LEN_MAX > outbytes_left)
177
        {
178
          chunkSize = outbytes_left / MB_LEN_MAX;
179
        }
180
181
        if (chunkSize > in.length() - inOffset)
182
        {
183
          chunkSize = in.length() - inOffset;
184
        }
185
186
        memset(buf, 0, BUFSIZE * sizeof(wchar_t));
187
        memcpy(buf,
188
          in.data() + inOffset,
189
          chunkSize * sizeof(wchar_t));
190
        size_t converted = wcstombs(out.data() + position, buf, outbytes_left);
191
192
        if (converted == (size_t) -1)
193
        {
194
          stat = APR_BADARG;
195
196
          //
197
          //   if unconvertable character was encountered
198
          //       repeatedly halve source to get fragment that
199
          //       can be converted
200
          for (chunkSize /= 2;
201
            chunkSize > 0;
202
            chunkSize /= 2)
203
          {
204
            buf[chunkSize] = 0;
205
            converted = wcstombs(out.data() + position, buf, outbytes_left);
206
207
            if (converted != (size_t) -1)
208
            {
209
              iter += chunkSize;
210
              out.increment_position(converted);
211
              break;
212
            }
213
          }
214
        }
215
        else
216
        {
217
          iter += chunkSize;
218
          out.increment_position(converted);
219
        }
220
      }
221
222
      return stat;
223
    }
224
225
    /**
226
     * Add onto \c out an encoded equivalent of \c codePoint.
227
     */
228
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
229
    {
230
      apr_status_t result = APR_SUCCESS;
231
      if (codePoint <= 0x10FFFF && MB_LEN_MAX <= out.remaining())
232
      {
233
        auto ch = static_cast<wchar_t>(codePoint);
234
        auto converted = wcstombs(out.current(), &ch, 1);
235
        if (static_cast<std::size_t>(-1) == converted)
236
          result = APR_BADARG;
237
        else
238
          out.increment_position(converted);
239
      }
240
      else
241
        result = APR_BADARG;
242
      return result;
243
    }
244
245
  private:
246
    WcstombsCharsetEncoder(const WcstombsCharsetEncoder&);
247
    WcstombsCharsetEncoder& operator=(const WcstombsCharsetEncoder&);
248
};
249
#endif
250
251
252
/**
253
*   Encodes a LogString to US-ASCII.
254
*/
255
class USASCIICharsetEncoder : public CharsetEncoder
256
{
257
  public:
258
    USASCIICharsetEncoder()
259
0
    {
260
0
    }
261
262
    virtual log4cxx_status_t encode(const LogString& in,
263
      LogString::const_iterator& iter,
264
      ByteBuffer& out) override
265
0
    {
266
0
      log4cxx_status_t stat = APR_SUCCESS;
267
268
0
      if (iter != in.end())
269
0
      {
270
0
        while (out.remaining() > 0 && iter != in.end())
271
0
        {
272
0
          LogString::const_iterator prev(iter);
273
0
          unsigned int sv = Transcoder::decode(in, iter);
274
275
0
          if (sv <= 0x7F)
276
0
          {
277
0
            out.put((char) sv);
278
0
          }
279
0
          else
280
0
          {
281
0
            iter = prev;
282
0
            stat = APR_BADARG;
283
0
            break;
284
0
          }
285
0
        }
286
0
      }
287
288
0
      return stat;
289
0
    }
290
291
    /**
292
     * Add onto \c out an encoded equivalent of \c codePoint.
293
     */
294
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
295
0
    {
296
0
      apr_status_t result = APR_SUCCESS;
297
0
      if (out.remaining() < 1)
298
0
        result = APR_BADARG;
299
0
      else if (codePoint <= 0x7F)
300
0
        out.put(static_cast<char>(codePoint));
301
0
      else if (Transcoder::LOSSCHAR == codePoint)
302
0
        out.put('?');
303
0
      else
304
0
        result = APR_BADARG;
305
0
      return result;
306
0
    }
307
308
  private:
309
    USASCIICharsetEncoder(const USASCIICharsetEncoder&);
310
    USASCIICharsetEncoder& operator=(const USASCIICharsetEncoder&);
311
};
312
313
/**
314
*   Converts a LogString to ISO-8859-1.
315
*/
316
class ISOLatinCharsetEncoder : public CharsetEncoder
317
{
318
  public:
319
    ISOLatinCharsetEncoder()
320
0
    {
321
0
    }
322
323
    virtual log4cxx_status_t encode(const LogString& in,
324
      LogString::const_iterator& iter,
325
      ByteBuffer& out) override
326
0
    {
327
0
      log4cxx_status_t stat = APR_SUCCESS;
328
329
0
      while (out.remaining() > 0 && iter != in.end())
330
0
      {
331
0
        LogString::const_iterator prev(iter);
332
0
        unsigned int sv = Transcoder::decode(in, iter);
333
0
        if (sv <= 0xFF)
334
0
          out.put(static_cast<char>(sv));
335
0
        else
336
0
        {
337
0
          iter = prev;
338
0
          stat = APR_BADARG;
339
0
          break;
340
0
        }
341
0
      }
342
0
      return stat;
343
0
    }
344
345
    /**
346
     * Add onto \c out an encoded equivalent of \c codePoint.
347
     */
348
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
349
0
    {
350
0
      apr_status_t result = APR_SUCCESS;
351
0
      if (out.remaining() < 1)
352
0
        result = APR_BADARG;
353
0
      else if (codePoint <= 0xFF)
354
0
        out.put(static_cast<char>(codePoint));
355
0
      else if (Transcoder::LOSSCHAR == codePoint)
356
0
        out.put('?');
357
0
      else
358
0
        result = APR_BADARG;
359
0
      return result;
360
0
    }
361
362
  private:
363
    ISOLatinCharsetEncoder(const ISOLatinCharsetEncoder&);
364
    ISOLatinCharsetEncoder& operator=(const ISOLatinCharsetEncoder&);
365
};
366
367
/**
368
*   Encodes a LogString to a byte array when the encodings are identical.
369
*/
370
class TrivialCharsetEncoder : public CharsetEncoder
371
{
372
  public:
373
    TrivialCharsetEncoder()
374
1
    {
375
1
    }
376
377
378
    virtual log4cxx_status_t encode(const LogString& in,
379
      LogString::const_iterator& iter,
380
      ByteBuffer& out) override
381
0
    {
382
0
      if (iter != in.end())
383
0
      {
384
0
        size_t requested = in.length() - (iter - in.begin());
385
386
0
        if (requested > out.remaining() / sizeof(logchar))
387
0
        {
388
0
          requested = out.remaining() / sizeof(logchar);
389
0
        }
390
391
0
        memcpy(out.current(),
392
0
          (const char*) in.data() + (iter - in.begin()),
393
0
          requested * sizeof(logchar));
394
0
        iter += requested;
395
0
        out.increment_position(requested * sizeof(logchar));
396
0
      }
397
398
0
      return APR_SUCCESS;
399
0
    }
400
401
    /**
402
     * Add onto \c out an encoded equivalent of \c codePoint.
403
     */
404
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
405
0
    {
406
0
      apr_status_t result = APR_SUCCESS;
407
0
      if (out.remaining() < 1)
408
0
        result = APR_BADARG;
409
0
      else if (codePoint <= 0xFF)
410
0
        out.put(static_cast<char>(codePoint));
411
0
      else if (Transcoder::LOSSCHAR == codePoint)
412
0
        out.put('?');
413
0
      else
414
0
        result = APR_BADARG;
415
0
      return result;
416
0
    }
417
418
  private:
419
    TrivialCharsetEncoder(const TrivialCharsetEncoder&);
420
    TrivialCharsetEncoder& operator=(const TrivialCharsetEncoder&);
421
};
422
423
/**
424
 *  Converts a LogString to UTF-8.
425
 */
426
class UTF8CharsetEncoder : public CharsetEncoder
427
{
428
  public:
429
    UTF8CharsetEncoder()
430
0
    {
431
0
    }
432
433
    virtual log4cxx_status_t encode(const LogString& in,
434
      LogString::const_iterator& iter,
435
      ByteBuffer& out) override
436
0
    {
437
0
      while (iter != in.end() && out.remaining() >= 8)
438
0
      {
439
0
        auto sv = Transcoder::getCodePoint(in, iter);
440
0
        Transcoder::encodeUTF8(sv, out);
441
0
      }
442
443
0
      return APR_SUCCESS;
444
0
    }
445
446
    /**
447
     * Add onto \c out an encoded equivalent of \c codePoint.
448
     */
449
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
450
0
    {
451
0
      apr_status_t result = APR_SUCCESS;
452
0
      if (codePoint <= 0x10FFFF)
453
0
        Transcoder::encodeUTF8(codePoint, out);
454
0
      else
455
0
        result = APR_BADARG;
456
0
      return result;
457
0
    }
458
459
  private:
460
    UTF8CharsetEncoder(const UTF8CharsetEncoder&);
461
    UTF8CharsetEncoder& operator=(const UTF8CharsetEncoder&);
462
};
463
464
/**
465
 *   Encodes a LogString to UTF16-BE.
466
 */
467
class UTF16BECharsetEncoder : public CharsetEncoder
468
{
469
  public:
470
    UTF16BECharsetEncoder()
471
0
    {
472
0
    }
473
474
    virtual log4cxx_status_t encode(const LogString& in,
475
      LogString::const_iterator& iter,
476
      ByteBuffer& out) override
477
0
    {
478
0
      while (iter != in.end() && out.remaining() >= 4)
479
0
      {
480
0
        auto sv = Transcoder::getCodePoint(in, iter);
481
0
        Transcoder::encodeUTF16BE(sv, out);
482
0
      }
483
484
0
      return APR_SUCCESS;
485
0
    }
486
487
    /**
488
     * Add onto \c out an encoded equivalent of \c codePoint.
489
     */
490
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
491
0
    {
492
0
      apr_status_t result = APR_SUCCESS;
493
0
      if (codePoint <= 0x10FFFF)
494
0
        Transcoder::encodeUTF16BE(codePoint, out);
495
0
      else
496
0
        result = APR_BADARG;
497
0
      return result;
498
0
    }
499
500
  private:
501
    UTF16BECharsetEncoder(const UTF16BECharsetEncoder&);
502
    UTF16BECharsetEncoder& operator=(const UTF16BECharsetEncoder&);
503
};
504
505
/**
506
 *   Encodes a LogString to UTF16-LE.
507
 */
508
class UTF16LECharsetEncoder : public CharsetEncoder
509
{
510
  public:
511
    UTF16LECharsetEncoder()
512
0
    {
513
0
    }
514
515
516
    virtual log4cxx_status_t encode(const LogString& in,
517
      LogString::const_iterator& iter,
518
      ByteBuffer& out) override
519
0
    {
520
0
      while (iter != in.end() && out.remaining() >= 4)
521
0
      {
522
0
        auto sv = Transcoder::getCodePoint(in, iter);
523
0
        Transcoder::encodeUTF16LE(sv, out);
524
0
      }
525
526
0
      return APR_SUCCESS;
527
0
    }
528
529
    /**
530
     * Add onto \c out an encoded equivalent of \c codePoint.
531
     */
532
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
533
0
    {
534
0
      apr_status_t result = APR_SUCCESS;
535
0
      if (codePoint <= 0x10FFFF)
536
0
        Transcoder::encodeUTF16LE(codePoint, out);
537
0
      else
538
0
        result = APR_BADARG;
539
0
      return result;
540
0
    }
541
  private:
542
    UTF16LECharsetEncoder(const UTF16LECharsetEncoder&);
543
    UTF16LECharsetEncoder& operator=(const UTF16LECharsetEncoder&);
544
};
545
546
/**
547
 *    Charset encoder that uses current locale settings.
548
 */
549
class LocaleCharsetEncoder : public CharsetEncoder
550
{
551
  public:
552
0
    LocaleCharsetEncoder() : state()
553
0
    {
554
0
    }
555
    log4cxx_status_t encode
556
      ( const LogString&           in
557
      , LogString::const_iterator& nextCodePoint
558
      , ByteBuffer&                out
559
      ) override
560
0
    {
561
0
      log4cxx_status_t result = APR_SUCCESS;
562
0
#if !LOG4CXX_CHARSET_EBCDIC
563
0
      char* current = out.current();
564
0
      size_t availableByteCount = out.remaining();
565
0
      size_t byteCount = 0;
566
0
      if (std::mbsinit(&this->state)) // ByteBuffer not partially encoded?
567
0
      {
568
        // Copy single byte characters
569
0
        for (;
570
0
          nextCodePoint != in.end() && byteCount < availableByteCount && static_cast<unsigned int>(*nextCodePoint) < 0x80;
571
0
          ++nextCodePoint, ++byteCount, ++current)
572
0
        {
573
0
          *current = static_cast<char>(*nextCodePoint);
574
0
        }
575
0
      }
576
0
#endif
577
      // Encode characters that may require multiple bytes
578
0
      while (nextCodePoint != in.end() && byteCount < availableByteCount && MB_CUR_MAX <= (availableByteCount - byteCount))
579
0
      {
580
0
        auto ch = Transcoder::getCodePoint(in, nextCodePoint);
581
0
        auto n = std::wcrtomb(current, ch, &this->state);
582
0
        if (static_cast<std::size_t>(-1) == n) // not a valid wide character?
583
0
        {
584
0
          result = APR_BADARG;
585
0
          break;
586
0
        }
587
0
        byteCount += n;
588
0
        current += n;
589
0
      }
590
0
      out.increment_position(byteCount);
591
0
      return result;
592
0
    }
593
594
    /**
595
     * Add onto \c out an encoded equivalent of \c codePoint.
596
     */
597
    log4cxx_status_t encode(unsigned int codePoint, ByteBuffer& out) LOG4CXX_16_VIRTUAL_SPECIFIER
598
0
    {
599
0
      apr_status_t result = APR_SUCCESS;
600
0
      if (MB_CUR_MAX <= out.remaining())
601
0
      {
602
0
        auto n = std::wcrtomb(out.current(), codePoint, &this->state);
603
0
        if (static_cast<std::size_t>(-1) == n) // not a valid wide character?
604
0
          result = APR_BADARG;
605
0
        else
606
0
          out.increment_position(n);
607
0
      }
608
0
      else
609
0
        result = APR_BADARG;
610
0
      return result;
611
0
    }
612
613
  private:
614
    std::mbstate_t state;
615
};
616
617
618
} // namespace helpers
619
620
}  //namespace log4cxx
621
622
623
624
CharsetEncoder::CharsetEncoder()
625
1
{
626
1
}
627
628
CharsetEncoder::~CharsetEncoder()
629
1
{
630
1
}
631
632
CharsetEncoderPtr CharsetEncoder::getDefaultEncoder()
633
923
{
634
923
  static WideLife<CharsetEncoderPtr> encoder(createDefaultEncoder());
635
636
  //
637
  //  if invoked after static variable destruction
638
  //     (if logging is called in the destructor of a static object)
639
  //     then create a new decoder.
640
  //
641
923
  if (encoder.value() == 0)
642
0
  {
643
0
    return CharsetEncoderPtr( createDefaultEncoder() );
644
0
  }
645
646
923
  return encoder;
647
923
}
648
649
CharsetEncoder* CharsetEncoder::createDefaultEncoder()
650
1
{
651
1
#if LOG4CXX_CHARSET_UTF8
652
1
#if LOG4CXX_LOGCHAR_IS_UTF8
653
1
  return new TrivialCharsetEncoder();
654
#else
655
  return new UTF8CharsetEncoder();
656
#endif
657
#elif LOG4CXX_CHARSET_ISO88591
658
  return new ISOLatinCharsetEncoder();
659
#elif LOG4CXX_CHARSET_USASCII
660
  return new USASCIICharsetEncoder();
661
#elif LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
662
  return new WcstombsCharsetEncoder();
663
#else
664
  return new LocaleCharsetEncoder();
665
#endif
666
1
}
667
668
669
CharsetEncoderPtr CharsetEncoder::getUTF8Encoder()
670
0
{
671
0
  return std::make_shared<UTF8CharsetEncoder>();
672
0
}
673
674
675
676
CharsetEncoderPtr CharsetEncoder::getEncoder(const LogString& charset)
677
0
{
678
0
  if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-8"), LOG4CXX_STR("utf-8"))
679
0
    || StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP65001"), LOG4CXX_STR("cp65001")))
680
0
  {
681
0
    return std::make_shared<UTF8CharsetEncoder>();
682
0
  }
683
0
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("C"), LOG4CXX_STR("c")) ||
684
0
    charset == LOG4CXX_STR("646") ||
685
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("US-ASCII"), LOG4CXX_STR("us-ascii")) ||
686
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO646-US"), LOG4CXX_STR("iso646-US")) ||
687
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ANSI_X3.4-1968"), LOG4CXX_STR("ansi_x3.4-1968")) ||
688
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP20127"), LOG4CXX_STR("cp20127")))
689
0
  {
690
0
    return std::make_shared<USASCIICharsetEncoder>();
691
0
  }
692
0
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-8859-1"), LOG4CXX_STR("iso-8859-1")) ||
693
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("ISO-LATIN-1"), LOG4CXX_STR("iso-latin-1")) ||
694
0
    StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1252"), LOG4CXX_STR("cp1252")))
695
0
  {
696
0
    return std::make_shared<ISOLatinCharsetEncoder>();
697
0
  }
698
0
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16BE"), LOG4CXX_STR("utf-16be"))
699
0
    || StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16"), LOG4CXX_STR("utf-16"))
700
0
    || StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("CP1200"), LOG4CXX_STR("cp1200")))
701
0
  {
702
0
    return std::make_shared<UTF16BECharsetEncoder>();
703
0
  }
704
0
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("UTF-16LE"), LOG4CXX_STR("utf-16le")))
705
0
  {
706
0
    return std::make_shared<UTF16LECharsetEncoder>();
707
0
  }
708
0
  else if (StringHelper::equalsIgnoreCase(charset, LOG4CXX_STR("LOCALE"), LOG4CXX_STR("locale")))
709
0
  {
710
0
    return std::make_shared<LocaleCharsetEncoder>();
711
0
  }
712
713
0
#if APR_HAS_XLATE
714
0
  return std::make_shared<APRCharsetEncoder>(charset);
715
#else
716
  throw IllegalArgumentException(charset);
717
#endif
718
0
}
719
720
721
void CharsetEncoder::reset()
722
0
{
723
0
}
724
725
#if LOG4CXX_ABI_VERSION <= 15
726
void CharsetEncoder::flush(ByteBuffer& /* out */ )
727
0
{
728
0
}
729
#endif
730
731
void CharsetEncoder::encode(CharsetEncoderPtr& enc,
732
  const LogString& src,
733
  LogString::const_iterator& iter,
734
  ByteBuffer& dst)
735
0
{
736
0
  log4cxx_status_t stat = enc->encode(src, iter, dst);
737
738
0
  if (stat != APR_SUCCESS && iter != src.end())
739
0
  {
740
#if LOG4CXX_LOGCHAR_IS_WCHAR || LOG4CXX_LOGCHAR_IS_UNICHAR
741
    iter++;
742
#elif LOG4CXX_LOGCHAR_IS_UTF8
743
744
    //  advance past this character and all continuation characters
745
0
    do
746
0
    {
747
0
      ++iter;
748
0
    }
749
0
    while (iter != src.end() &&
750
0
         (*iter & 0xC0) == 0x80);
751
752
#else
753
#error logchar is unrecognized
754
#endif
755
#if 15 < LOG4CXX_ABI_VERSION
756
    enc->encode(Transcoder::LOSSCHAR, dst);
757
#else // LOG4CXX_ABI_VERSION <= 15
758
0
    if (auto p = dynamic_cast<TrivialCharsetEncoder*>(enc.get()))
759
0
      p->encode(Transcoder::LOSSCHAR, dst);
760
0
    else if (auto p = dynamic_cast<UTF8CharsetEncoder*>(enc.get()))
761
0
      p->encode(Transcoder::LOSSCHAR, dst);
762
0
    else if (auto p = dynamic_cast<LocaleCharsetEncoder*>(enc.get()))
763
0
      p->encode(Transcoder::LOSSCHAR, dst);
764
0
    else if (auto p = dynamic_cast<USASCIICharsetEncoder*>(enc.get()))
765
0
      p->encode(Transcoder::LOSSCHAR, dst);
766
0
    else if (auto p = dynamic_cast<ISOLatinCharsetEncoder*>(enc.get()))
767
0
      p->encode(Transcoder::LOSSCHAR, dst);
768
0
    else if (auto p = dynamic_cast<UTF16BECharsetEncoder*>(enc.get()))
769
0
      p->encode(Transcoder::LOSSCHAR, dst);
770
0
    else if (auto p = dynamic_cast<UTF16LECharsetEncoder*>(enc.get()))
771
0
      p->encode(Transcoder::LOSSCHAR, dst);
772
#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
773
    else if (auto p = dynamic_cast<WcstombsCharsetEncoder*>(enc.get()))
774
      p->encode(Transcoder::LOSSCHAR, dst);
775
#endif //  LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_WCSTOMBS
776
0
#if APR_HAS_XLATE
777
0
    else if (auto p = dynamic_cast<APRCharsetEncoder*>(enc.get()))
778
0
      p->encode(Transcoder::LOSSCHAR, dst);
779
0
#endif //  APR_HAS_XLATE
780
0
#endif // LOG4CXX_ABI_VERSION <= 15
781
0
  }
782
0
}
783
784
bool CharsetEncoder::isTriviallyCopyable(const LogString& src, const CharsetEncoderPtr& enc)
785
4.61k
{
786
4.61k
  bool result;
787
4.61k
#if !LOG4CXX_CHARSET_EBCDIC
788
4.61k
  if (dynamic_cast<LocaleCharsetEncoder*>(enc.get()))
789
0
  {
790
0
    result = src.end() == std::find_if(src.begin(), src.end()
791
0
      , [](const logchar& ch) -> bool { return 0x80 <= (unsigned int)ch; });
792
0
  }
793
4.61k
  else
794
4.61k
#endif
795
4.61k
    result = !!dynamic_cast<TrivialCharsetEncoder*>(enc.get());
796
4.61k
  return result;
797
4.61k
}