This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
The following commit(s) were added to refs/heads/master by this push:
new 2c6c4f40 Fix performance regression with JSON & XML output (#757)
2c6c4f40 is described below
commit 2c6c4f40f71f7681233c40c43df4faa143bc48b5
Author: Stephen Webb <[email protected]>
AuthorDate: Sat Sep 5 14:01:59 2026 +1000
Fix performance regression with JSON & XML output (#757)
* Avoid dynamic memory allocation in Transcoder::decode
* Use inlined ByteBuffer methods when encoding
* Check for ASCII before using Transcoder::getCodePoint
---
src/main/cpp/bytebuffer.cpp | 55 +++-----
src/main/cpp/charsetdecoder.cpp | 25 ++--
src/main/cpp/charsetencoder.cpp | 141 +++++++++++++++++----
src/main/cpp/jsonlayout.cpp | 6 +-
src/main/cpp/transcoder.cpp | 106 +---------------
src/main/cpp/transform.cpp | 6 +-
src/main/include/log4cxx/helpers/bytebuffer.h | 6 +-
src/main/include/log4cxx/helpers/charsetdecoder.h | 4 +-
src/main/include/log4cxx/helpers/charsetencoder.h | 22 ++++
src/main/include/log4cxx/helpers/transcoder.h | 10 +-
src/main/include/log4cxx/private/bytebuffer_priv.h | 131 +++++++++++++++++++
11 files changed, 331 insertions(+), 181 deletions(-)
diff --git a/src/main/cpp/bytebuffer.cpp b/src/main/cpp/bytebuffer.cpp
index 62a3e770..8890dd45 100644
--- a/src/main/cpp/bytebuffer.cpp
+++ b/src/main/cpp/bytebuffer.cpp
@@ -15,7 +15,7 @@
* limitations under the License.
*/
#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/private/bytebuffer_priv.h>
#if LOG4CXX_ABI_VERSION <= 15
#include <log4cxx/helpers/exception.h>
#endif
@@ -24,17 +24,6 @@
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
-struct ByteBuffer::ByteBufferPriv
-{
- ByteBufferPriv(char* data1, size_t capacity) :
- base(data1), pos(0), lim(capacity), cap(capacity) {}
-
- char* base;
- size_t pos;
- size_t lim;
- size_t cap;
-};
-
ByteBuffer::ByteBuffer(char* data1, size_t capacity)
: m_priv(std::make_unique<ByteBufferPriv>(data1, capacity))
{
@@ -44,24 +33,24 @@ ByteBuffer::~ByteBuffer()
{
}
+ByteBufferPriv& ByteBuffer::impl()
+{
+ return *m_priv;
+}
+
void ByteBuffer::clear()
{
- m_priv->lim = m_priv->cap;
- m_priv->pos = 0;
+ m_priv->clear();
}
void ByteBuffer::carry()
{
- auto available = remaining();
- memmove(m_priv->base, current(), available);
- m_priv->lim = m_priv->cap;
- m_priv->pos = available;
+ m_priv->carry();
}
void ByteBuffer::flip()
{
- m_priv->lim = m_priv->pos;
- m_priv->pos = 0;
+ m_priv->flip();
}
#if LOG4CXX_ABI_VERSION <= 15
@@ -95,53 +84,45 @@ void ByteBuffer::limit(size_t newLimit)
bool ByteBuffer::put(char byte)
{
- if (m_priv->pos < m_priv->lim)
- {
- m_priv->base[m_priv->pos++] = byte;
- return true;
- }
-
- return false;
+ return m_priv->put(byte);
}
char* ByteBuffer::data()
{
- return m_priv->base;
+ return m_priv->data();
}
const char* ByteBuffer::data() const
{
- return m_priv->base;
+ return m_priv->data();
}
char* ByteBuffer::current()
{
- return m_priv->base + m_priv->pos;
+ return m_priv->current();
}
const char* ByteBuffer::current() const
{
- return m_priv->base + m_priv->pos;
+ return m_priv->current();
}
size_t ByteBuffer::limit() const
{
- return m_priv->lim;
+ return m_priv->limit();
}
size_t ByteBuffer::position() const
{
- return m_priv->pos;
+ return m_priv->position();
}
size_t ByteBuffer::remaining() const
{
- return m_priv->lim - m_priv->pos;
+ return m_priv->remaining();
}
size_t ByteBuffer::increment_position(size_t byteCount)
{
- auto available = remaining();
- m_priv->pos += byteCount < available ? byteCount : available;
- return remaining();
+ return m_priv->increment_position(byteCount);
}
diff --git a/src/main/cpp/charsetdecoder.cpp b/src/main/cpp/charsetdecoder.cpp
index fc9ce181..3c2541e5 100644
--- a/src/main/cpp/charsetdecoder.cpp
+++ b/src/main/cpp/charsetdecoder.cpp
@@ -18,7 +18,7 @@
#include <log4cxx/private/string_c11.h>
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/charsetdecoder.h>
-#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/private/bytebuffer_priv.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/loglog.h>
@@ -87,9 +87,10 @@ class APRCharsetDecoder : public CharsetDecoder
{
}
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
enum { BUFSIZE = 256 };
logchar buf[BUFSIZE];
const apr_size_t initial_outbytes_left = BUFSIZE *
sizeof(logchar);
@@ -167,9 +168,10 @@ class MbstowcsCharsetDecoder : public CharsetDecoder
return APR_SUCCESS;
}
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
log4cxx_status_t stat = APR_SUCCESS;
enum { BUFSIZE = 256 };
wchar_t wbuf[BUFSIZE];
@@ -276,9 +278,10 @@ class TrivialCharsetDecoder : public CharsetDecoder
{
}
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
size_t remaining = in.remaining();
if ( remaining > 0)
@@ -315,9 +318,10 @@ class UTF8CharsetDecoder : public CharsetDecoder
}
private:
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
auto availableByteCount = in.remaining();
while (0 < availableByteCount)
{
@@ -352,9 +356,10 @@ class ISOLatinCharsetDecoder : public CharsetDecoder
}
private:
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
auto availableByteCount = in.remaining();
auto src = in.current();
auto srcEnd = src + availableByteCount;
@@ -394,9 +399,10 @@ class USASCIICharsetDecoder : public CharsetDecoder
private:
- virtual log4cxx_status_t decode(ByteBuffer& in,
+ virtual log4cxx_status_t decode(ByteBuffer& in_param,
LogString& out)
{
+ auto& in = in_param.impl();
log4cxx_status_t stat = APR_SUCCESS;
auto availableByteCount = in.remaining();
@@ -439,8 +445,9 @@ class LocaleCharsetDecoder : public CharsetDecoder
LocaleCharsetDecoder() : state()
{
}
- log4cxx_status_t decode(ByteBuffer& in, LogString& out) override
+ log4cxx_status_t decode(ByteBuffer& in_param, LogString& out)
override
{
+ auto& in = in_param.impl();
log4cxx_status_t result = APR_SUCCESS;
auto p = in.current();
auto availableByteCount = in.remaining();
@@ -594,7 +601,7 @@ log4cxx_status_t CharsetDecoder::decode(const char* in,
size_t maxByteCount, Log
return decode(buf, out);
}
-unsigned int CharsetDecoder::getUTF8CodePoint(ByteBuffer& in)
+unsigned int CharsetDecoder::getUTF8CodePoint(ByteBufferPriv& in)
{
auto availableByteCount = in.remaining();
if (0 == availableByteCount)
diff --git a/src/main/cpp/charsetencoder.cpp b/src/main/cpp/charsetencoder.cpp
index eb789a2d..ea09b86c 100644
--- a/src/main/cpp/charsetencoder.cpp
+++ b/src/main/cpp/charsetencoder.cpp
@@ -16,7 +16,7 @@
*/
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/charsetencoder.h>
-#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/private/bytebuffer_priv.h>
#include <log4cxx/helpers/exception.h>
#include <apr_xlate.h>
#include <log4cxx/helpers/stringhelper.h>
@@ -88,8 +88,9 @@ class APRCharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
+ auto& out = out_param.impl();
apr_status_t stat;
size_t outbytes_left = out.remaining();
size_t initial_outbytes_left = outbytes_left;
@@ -128,8 +129,8 @@ class APRCharsetEncoder : public CharsetEncoder
log4cxx_status_t encode(unsigned int codePoint, ByteBuffer&
out) LOG4CXX_16_VIRTUAL_SPECIFIER
{
apr_status_t result = APR_SUCCESS;
- if (codePoint <= 0x10FFFF)
- Transcoder::encodeUTF8(codePoint, out);
+ if (codePoint <= 0x10FFFF && 4 <= out.remaining())
+
out.increment_position(putUTF8CodePoint(codePoint, out.current()));
else
result = APR_BADARG;
return result;
@@ -160,8 +161,9 @@ class WcstombsCharsetEncoder : public CharsetEncoder
*/
log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
+ auto& out = out_param.impl();
log4cxx_status_t stat = APR_SUCCESS;
if (iter != in.end())
@@ -261,8 +263,9 @@ class USASCIICharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
+ auto& out = out_param.impl();
log4cxx_status_t stat = APR_SUCCESS;
if (iter != in.end())
@@ -322,8 +325,9 @@ class ISOLatinCharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
+ auto& out = out_param.impl();
log4cxx_status_t stat = APR_SUCCESS;
while (out.remaining() > 0 && iter != in.end())
@@ -377,8 +381,9 @@ class TrivialCharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
+ auto& out = out_param.impl();
if (iter != in.end())
{
size_t requested = in.length() - (iter -
in.begin());
@@ -432,12 +437,13 @@ class UTF8CharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
- while (iter != in.end() && out.remaining() >= 8)
+ auto& out = out_param.impl();
+ while (iter != in.end() && 4 <= out.remaining())
{
auto sv = Transcoder::getCodePoint(in, iter);
- Transcoder::encodeUTF8(sv, out);
+ out.increment_position(putUTF8CodePoint(sv,
out.current()));
}
return APR_SUCCESS;
@@ -449,8 +455,8 @@ class UTF8CharsetEncoder : public CharsetEncoder
log4cxx_status_t encode(unsigned int codePoint, ByteBuffer&
out) LOG4CXX_16_VIRTUAL_SPECIFIER
{
apr_status_t result = APR_SUCCESS;
- if (codePoint <= 0x10FFFF)
- Transcoder::encodeUTF8(codePoint, out);
+ if (codePoint <= 0x10FFFF && 4 <= out.remaining())
+
out.increment_position(putUTF8CodePoint(codePoint, out.current()));
else
result = APR_BADARG;
return result;
@@ -473,12 +479,13 @@ class UTF16BECharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
- while (iter != in.end() && out.remaining() >= 4)
+ auto& out = out_param.impl();
+ while (iter != in.end() && 4 <= out.remaining())
{
auto sv = Transcoder::getCodePoint(in, iter);
- Transcoder::encodeUTF16BE(sv, out);
+ out.increment_position(putUTF16BECodePoint(sv,
out.current()));
}
return APR_SUCCESS;
@@ -490,7 +497,7 @@ class UTF16BECharsetEncoder : public CharsetEncoder
log4cxx_status_t encode(unsigned int codePoint, ByteBuffer&
out) LOG4CXX_16_VIRTUAL_SPECIFIER
{
apr_status_t result = APR_SUCCESS;
- if (codePoint <= 0x10FFFF)
+ if (codePoint <= 0x10FFFF && 4 <= out.remaining())
Transcoder::encodeUTF16BE(codePoint, out);
else
result = APR_BADARG;
@@ -515,12 +522,13 @@ class UTF16LECharsetEncoder : public CharsetEncoder
virtual log4cxx_status_t encode(const LogString& in,
LogString::const_iterator& iter,
- ByteBuffer& out) override
+ ByteBuffer& out_param) override
{
- while (iter != in.end() && out.remaining() >= 4)
+ auto& out = out_param.impl();
+ while (iter != in.end() && 4 <= out.remaining())
{
auto sv = Transcoder::getCodePoint(in, iter);
- Transcoder::encodeUTF16LE(sv, out);
+ out.increment_position(putUTF16LECodePoint(sv,
out.current()));
}
return APR_SUCCESS;
@@ -532,8 +540,8 @@ class UTF16LECharsetEncoder : public CharsetEncoder
log4cxx_status_t encode(unsigned int codePoint, ByteBuffer&
out) LOG4CXX_16_VIRTUAL_SPECIFIER
{
apr_status_t result = APR_SUCCESS;
- if (codePoint <= 0x10FFFF)
- Transcoder::encodeUTF16LE(codePoint, out);
+ if (codePoint <= 0x10FFFF && 4 <= out.remaining())
+
out.increment_position(putUTF16LECodePoint(codePoint, out.current()));
else
result = APR_BADARG;
return result;
@@ -555,9 +563,10 @@ class LocaleCharsetEncoder : public CharsetEncoder
log4cxx_status_t encode
( const LogString& in
, LogString::const_iterator& nextCodePoint
- , ByteBuffer& out
+ , ByteBuffer& out_param
) override
{
+ auto& out = out_param.impl();
log4cxx_status_t result = APR_SUCCESS;
#if !LOG4CXX_CHARSET_EBCDIC
char* current = out.current();
@@ -795,3 +804,89 @@ bool CharsetEncoder::isTriviallyCopyable(const LogString&
src, const CharsetEnco
result = !!dynamic_cast<TrivialCharsetEncoder*>(enc.get());
return result;
}
+
+size_t CharsetEncoder::putUTF8CodePoint(unsigned int ch, char* dst)
+{
+ if (ch < 0x80)
+ {
+ dst[0] = (char) ch;
+ return 1;
+ }
+ else if (ch < 0x800)
+ {
+ dst[0] = (char) (0xC0 + (ch >> 6));
+ dst[1] = (char) (0x80 + (ch & 0x3F));
+ return 2;
+ }
+ else if (ch < 0x10000)
+ {
+ dst[0] = (char) (0xE0 + (ch >> 12));
+ dst[1] = (char) (0x80 + ((ch >> 6) & 0x3F));
+ dst[2] = (char) (0x80 + (ch & 0x3F));
+ return 3;
+ }
+ else if (ch <= 0x10FFFF)
+ {
+ dst[0] = (char) (0xF0 + (ch >> 18));
+ dst[1] = (char) (0x80 + ((ch >> 12) & 0x3F));
+ dst[2] = (char) (0x80 + ((ch >> 6) & 0x3F));
+ dst[3] = (char) (0x80 + (ch & 0x3F));
+ return 4;
+ }
+ else
+ {
+ //
+ // output UTF-8 encoding of 0xFFFF
+ //
+ dst[0] = (char) 0xEF;
+ dst[1] = (char) 0xBF;
+ dst[2] = (char) 0xBF;
+ return 3;
+ }
+}
+
+size_t CharsetEncoder::putUTF16BECodePoint(unsigned int ch, char* dst)
+{
+ if (ch <= 0xFFFF)
+ {
+ dst[0] = (char) (ch >> 8);
+ dst[1] = (char) (ch & 0xFF);
+ return 2;
+ }
+
+ if (ch <= 0x10FFFF)
+ {
+ unsigned char w = (unsigned char) ((ch >> 16) - 1);
+ dst[0] = (char) (0xD8 + (w >> 2));
+ dst[1] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
+ dst[2] = (char) (0xDC + ((ch >> 8) & 0x03));
+ dst[3] = (char) (ch & 0xFF);
+ return 4;
+ }
+
+ dst[0] = dst[1] = (char) 0xFF;
+ return 2;
+}
+
+size_t CharsetEncoder::putUTF16LECodePoint(unsigned int ch, char* dst)
+{
+ if (ch <= 0xFFFF)
+ {
+ dst[1] = (char) (ch >> 8);
+ dst[0] = (char) (ch & 0xFF);
+ return 2;
+ }
+
+ if (ch <= 0x10FFFF)
+ {
+ unsigned char w = (unsigned char) ((ch >> 16) - 1);
+ dst[1] = (char) (0xD8 + (w >> 2));
+ dst[0] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
+ dst[3] = (char) (0xDC + ((ch >> 8) & 0x03));
+ dst[2] = (char) (ch & 0xFF);
+ return 4;
+ }
+
+ dst[0] = dst[1] = (char) 0xFF;
+ return 2;
+}
\ No newline at end of file
diff --git a/src/main/cpp/jsonlayout.cpp b/src/main/cpp/jsonlayout.cpp
index a66c8a77..9de7705e 100644
--- a/src/main/cpp/jsonlayout.cpp
+++ b/src/main/cpp/jsonlayout.cpp
@@ -223,7 +223,11 @@ void JSONLayout::appendItem(const LogString& input,
LogString& buf)
for (auto nextCodePoint = start; input.end() != nextCodePoint; )
{
auto lastCodePoint = nextCodePoint;
- auto ch = Transcoder::getCodePoint(input, nextCodePoint);
+ auto ch = static_cast<unsigned int>(*nextCodePoint);
+ if (ch <= 0x7f)
+ ++nextCodePoint;
+ else
+ ch = Transcoder::getCodePoint(input, nextCodePoint);
if (0x22 == ch || 0x5c == ch) // double quote or backslash?
;
else if (0x20 <= ch && 0xFFFD != ch) // not a control character
or the replacement character?
diff --git a/src/main/cpp/transcoder.cpp b/src/main/cpp/transcoder.cpp
index bf71a302..4efd9da6 100644
--- a/src/main/cpp/transcoder.cpp
+++ b/src/main/cpp/transcoder.cpp
@@ -20,7 +20,7 @@
#include <log4cxx/helpers/pool.h>
#include <stdlib.h>
#include <log4cxx/helpers/exception.h>
-#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/private/bytebuffer_priv.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/helpers/charsetencoder.h>
#include <log4cxx/helpers/stringhelper.h>
@@ -81,117 +81,25 @@ char* Transcoder::encodeUTF8(const LogString& src, Pool& p)
void Transcoder::encodeUTF8(unsigned int sv, ByteBuffer& dst)
{
- size_t bytes = encodeUTF8(sv, dst.current());
- dst.increment_position(bytes);
-}
-
-
-size_t Transcoder::encodeUTF8(unsigned int ch, char* dst)
-{
- if (ch < 0x80)
- {
- dst[0] = (char) ch;
- return 1;
- }
- else if (ch < 0x800)
- {
- dst[0] = (char) (0xC0 + (ch >> 6));
- dst[1] = (char) (0x80 + (ch & 0x3F));
- return 2;
- }
- else if (ch < 0x10000)
- {
- dst[0] = (char) (0xE0 + (ch >> 12));
- dst[1] = (char) (0x80 + ((ch >> 6) & 0x3F));
- dst[2] = (char) (0x80 + (ch & 0x3F));
- return 3;
- }
- else if (ch <= 0x10FFFF)
- {
- dst[0] = (char) (0xF0 + (ch >> 18));
- dst[1] = (char) (0x80 + ((ch >> 12) & 0x3F));
- dst[2] = (char) (0x80 + ((ch >> 6) & 0x3F));
- dst[3] = (char) (0x80 + (ch & 0x3F));
- return 4;
- }
- else
- {
- //
- // output UTF-8 encoding of 0xFFFF
- //
- dst[0] = (char) 0xEF;
- dst[1] = (char) 0xBF;
- dst[2] = (char) 0xBF;
- return 3;
- }
+ dst.increment_position(CharsetEncoder::putUTF8CodePoint(sv,
dst.current()));
}
void Transcoder::encodeUTF16BE(unsigned int sv, ByteBuffer& dst)
{
- size_t bytes = encodeUTF16BE(sv, dst.current());
- dst.increment_position(bytes);
-}
-
-
-size_t Transcoder::encodeUTF16BE(unsigned int ch, char* dst)
-{
- if (ch <= 0xFFFF)
- {
- dst[0] = (char) (ch >> 8);
- dst[1] = (char) (ch & 0xFF);
- return 2;
- }
-
- if (ch <= 0x10FFFF)
- {
- unsigned char w = (unsigned char) ((ch >> 16) - 1);
- dst[0] = (char) (0xD8 + (w >> 2));
- dst[1] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
- dst[2] = (char) (0xDC + ((ch >> 8) & 0x03));
- dst[3] = (char) (ch & 0xFF);
- return 4;
- }
-
- dst[0] = dst[1] = (char) 0xFF;
- return 2;
+ dst.increment_position(CharsetEncoder::putUTF16BECodePoint(sv,
dst.current()));
}
void Transcoder::encodeUTF16LE(unsigned int sv, ByteBuffer& dst)
{
- size_t bytes = encodeUTF16LE(sv, dst.current());
- dst.increment_position(bytes);
+ dst.increment_position(CharsetEncoder::putUTF16LECodePoint(sv,
dst.current()));
}
-size_t Transcoder::encodeUTF16LE(unsigned int ch, char* dst)
-{
- if (ch <= 0xFFFF)
- {
- dst[1] = (char) (ch >> 8);
- dst[0] = (char) (ch & 0xFF);
- return 2;
- }
-
- if (ch <= 0x10FFFF)
- {
- unsigned char w = (unsigned char) ((ch >> 16) - 1);
- dst[1] = (char) (0xD8 + (w >> 2));
- dst[0] = (char) (((w & 0x03) << 6) + ((ch >> 10) & 0x3F));
- dst[3] = (char) (0xDC + ((ch >> 8) & 0x03));
- dst[2] = (char) (ch & 0xFF);
- return 4;
- }
-
- dst[0] = dst[1] = (char) 0xFF;
- return 2;
-}
-
-
unsigned int Transcoder::decode(const std::string& src,
std::string::const_iterator& iter)
{
auto offset = iter - src.begin();
auto remaining = src.size() - offset;
- ByteBuffer buf(const_cast<char*>(src.data() + offset), remaining);
+ ByteBufferPriv buf(const_cast<char*>(src.data() + offset), remaining);
auto result = CharsetDecoder::getUTF8CodePoint(buf);
iter += remaining - buf.remaining();
return result;
@@ -231,7 +139,7 @@ unsigned int Transcoder::getCodePoint(const std::string&
str, std::string::const
void Transcoder::encode(unsigned int sv, std::string& dst)
{
char tmp[8];
- size_t bytes = encodeUTF8(sv, tmp);
+ size_t bytes = CharsetEncoder::putUTF8CodePoint(sv, tmp);
dst.append(tmp, bytes);
}
@@ -314,9 +222,9 @@ void Transcoder::encode(const LogString& src, std::string&
dst)
}
#endif
-
if (iter != src.end())
{
+ static const int BUFSIZE = 256;
char buf[BUFSIZE];
ByteBuffer out(buf, BUFSIZE);
diff --git a/src/main/cpp/transform.cpp b/src/main/cpp/transform.cpp
index 7ede9a6f..ee1ee457 100644
--- a/src/main/cpp/transform.cpp
+++ b/src/main/cpp/transform.cpp
@@ -43,7 +43,11 @@ void appendValidCharacters(LogString& buf, const LogString&
input, CharProcessor
for (auto nextCodePoint = start; input.end() != nextCodePoint; )
{
auto lastCodePoint = nextCodePoint;
- auto ch = Transcoder::getCodePoint(input, nextCodePoint);
+ auto ch = static_cast<unsigned int>(*nextCodePoint);
+ if (ch <= 0x7f)
+ ++nextCodePoint;
+ else
+ ch = Transcoder::getCodePoint(input, nextCodePoint);
if (((0x20 <= ch && ch <= 0xD7FF) &&
specials[0] != ch &&
specials[1] != ch &&
diff --git a/src/main/include/log4cxx/helpers/bytebuffer.h
b/src/main/include/log4cxx/helpers/bytebuffer.h
index f2fe0c3e..670c47c2 100644
--- a/src/main/include/log4cxx/helpers/bytebuffer.h
+++ b/src/main/include/log4cxx/helpers/bytebuffer.h
@@ -26,6 +26,7 @@ namespace LOG4CXX_NS
namespace helpers
{
+struct ByteBufferPriv;
/**
* An area of memory and a cursor into that memory.
@@ -40,7 +41,7 @@ namespace helpers
class LOG4CXX_EXPORT ByteBuffer
{
private:
- LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(ByteBufferPriv, m_priv)
+ LOG4CXX_DECLARE_PRIVATE_MEMBER(std::unique_ptr<ByteBufferPriv>,
m_priv);
public:
/// A \c capacity sized area of memory at \c data.
@@ -110,7 +111,8 @@ class LOG4CXX_EXPORT ByteBuffer
/// @returns true if \c byteValue was stored in the buffer.
bool put(char byteValue);
-
+ /// Internal use only
+ ByteBufferPriv& impl();
private:
ByteBuffer(const ByteBuffer&);
ByteBuffer& operator=(const ByteBuffer&);
diff --git a/src/main/include/log4cxx/helpers/charsetdecoder.h
b/src/main/include/log4cxx/helpers/charsetdecoder.h
index 71938e84..5a9af190 100644
--- a/src/main/include/log4cxx/helpers/charsetdecoder.h
+++ b/src/main/include/log4cxx/helpers/charsetdecoder.h
@@ -27,7 +27,7 @@ namespace helpers
class CharsetDecoder;
LOG4CXX_PTR_DEF(CharsetDecoder);
class ByteBuffer;
-
+struct ByteBufferPriv;
/**
* An abstract engine to transform a sequences of bytes in a specific charset
@@ -109,7 +109,7 @@ class LOG4CXX_EXPORT CharsetDecoder : public Object
* @param buf the bytes to decode.
* @return the code point value, if successful, otherwise
0xFFFF. The \c buf cursor position is only incremented if successful.
*/
- static unsigned int getUTF8CodePoint(ByteBuffer& buf);
+ static unsigned int getUTF8CodePoint(ByteBufferPriv& buf);
private:
/**
diff --git a/src/main/include/log4cxx/helpers/charsetencoder.h
b/src/main/include/log4cxx/helpers/charsetencoder.h
index 44b7b5dd..4e971cb2 100644
--- a/src/main/include/log4cxx/helpers/charsetencoder.h
+++ b/src/main/include/log4cxx/helpers/charsetencoder.h
@@ -131,7 +131,29 @@ class LOG4CXX_EXPORT CharsetEncoder : public Object
*/
static bool isTriviallyCopyable(const LogString& src, const
CharsetEncoderPtr& enc);
+ /**
+ * Add UTF-8 bytes to \c dst corresponding to \c ch.
+ * @pre dst is a writable address for 4 consecutive bytes
+ * @param ch the code point value.
+ * @param dst storage for upto 4 bytes.
+ */
+ static size_t putUTF8CodePoint(unsigned int ch, char* dst);
+ /**
+ * Add UTF-16 big-endian bytes to \c dst corresponding to \c
ch.
+ * @pre dst is a writable address for 4 consecutive bytes
+ * @param ch the code point value.
+ * @param dst storage for upto 4 bytes.
+ */
+ static size_t putUTF16BECodePoint(unsigned int ch, char* dst);
+
+ /**
+ * Add UTF-16 little-endian bytes to \c dst corresponding to
\c ch.
+ * @pre dst is a writable address for 4 consecutive bytes
+ * @param ch the code point value.
+ * @param dst storage for upto 4 bytes.
+ */
+ static size_t putUTF16LECodePoint(unsigned int ch, char* dst);
private:
/**
* Private copy constructor.
diff --git a/src/main/include/log4cxx/helpers/transcoder.h
b/src/main/include/log4cxx/helpers/transcoder.h
index 51ed6b96..28f3255c 100644
--- a/src/main/include/log4cxx/helpers/transcoder.h
+++ b/src/main/include/log4cxx/helpers/transcoder.h
@@ -51,14 +51,17 @@ class LOG4CXX_EXPORT Transcoder
#endif
/**
* Append the code point \c sv to \c dst as UTF-8.
+ * @pre 4 <= dst.remaining()
*/
static void encodeUTF8(unsigned int sv, ByteBuffer& dst);
/**
* Append the code point \c sv to \c dst as UTF-16LE.
+ * @pre 4 <= dst.remaining()
*/
static void encodeUTF16LE(unsigned int sv, ByteBuffer& dst);
/**
* Append the code point \c sv to \c dst as UTF-16BE.
+ * @pre 4 <= dst.remaining()
*/
static void encodeUTF16BE(unsigned int sv, ByteBuffer& dst);
@@ -230,17 +233,10 @@ class LOG4CXX_EXPORT Transcoder
*/
static std::string encodeCharsetName(const LogString&
charsetName);
- private:
-
private:
Transcoder();
Transcoder(const Transcoder&);
Transcoder& operator=(const Transcoder&);
- enum { BUFSIZE = 256 };
- static size_t encodeUTF8(unsigned int ch, char* dst);
- static size_t encodeUTF16BE(unsigned int ch, char* dst);
- static size_t encodeUTF16LE(unsigned int ch, char* dst);
-
};
}
}
diff --git a/src/main/include/log4cxx/private/bytebuffer_priv.h
b/src/main/include/log4cxx/private/bytebuffer_priv.h
new file mode 100644
index 00000000..93ec2a1e
--- /dev/null
+++ b/src/main/include/log4cxx/private/bytebuffer_priv.h
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <log4cxx/helpers/bytebuffer.h>
+#include <cstring> // memmove
+
+using namespace LOG4CXX_NS;
+using namespace LOG4CXX_NS::helpers;
+
+struct LOG4CXX_NS::helpers::ByteBufferPriv
+{
+private: // Attributes
+ char* base;
+ size_t pos;
+ size_t lim;
+ size_t cap;
+
+public: // ...structor
+ ByteBufferPriv(char* data, size_t capacity)
+ : base(data)
+ , pos(0)
+ , lim(capacity)
+ , cap(capacity)
+ {}
+
+public: // Accessors
+ inline char* data();
+ inline const char* data() const;
+ inline char* current();
+ inline const char* current() const;
+ inline size_t limit() const;
+ inline size_t position() const;
+ inline size_t remaining() const;
+
+public: // Modifiers
+ inline void carry();
+ inline void clear();
+ inline void flip();
+ inline size_t increment_position(size_t byteCount);
+ inline bool put(char byteValue);
+
+#if LOG4CXX_ABI_VERSION <= 15
+ friend class ByteBuffer;
+#endif
+};
+
+void ByteBufferPriv::clear()
+{
+ this->lim = this->cap;
+ this->pos = 0;
+}
+
+void ByteBufferPriv::carry()
+{
+ auto available = remaining();
+ memmove(this->base, current(), available);
+ this->lim = this->cap;
+ this->pos = available;
+}
+
+void ByteBufferPriv::flip()
+{
+ this->lim = this->pos;
+ this->pos = 0;
+}
+
+bool ByteBufferPriv::put(char byte)
+{
+ if (this->pos < this->lim)
+ {
+ this->base[this->pos++] = byte;
+ return true;
+ }
+
+ return false;
+}
+
+char* ByteBufferPriv::data()
+{
+ return this->base;
+}
+
+const char* ByteBufferPriv::data() const
+{
+ return this->base;
+}
+
+char* ByteBufferPriv::current()
+{
+ return this->base + this->pos;
+}
+
+const char* ByteBufferPriv::current() const
+{
+ return this->base + this->pos;
+}
+
+size_t ByteBufferPriv::limit() const
+{
+ return this->lim;
+}
+
+size_t ByteBufferPriv::position() const
+{
+ return this->pos;
+}
+
+size_t ByteBufferPriv::remaining() const
+{
+ return this->lim - this->pos;
+}
+
+size_t ByteBufferPriv::increment_position(size_t byteCount)
+{
+ auto available = remaining();
+ this->pos += byteCount < available ? byteCount : available;
+ return remaining();
+}