1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.layout;
18
19 import java.nio.ByteBuffer;
20 import java.nio.CharBuffer;
21 import java.nio.charset.CharacterCodingException;
22 import java.nio.charset.Charset;
23 import java.nio.charset.CharsetEncoder;
24 import java.nio.charset.CoderResult;
25
26
27
28
29
30
31 public class TextEncoderHelper {
32
33 private TextEncoderHelper() {
34 }
35
36 static void encodeTextFallBack(final Charset charset, final StringBuilder text,
37 final ByteBufferDestination destination) {
38 final byte[] bytes = text.toString().getBytes(charset);
39 synchronized (destination) {
40 ByteBuffer buffer = destination.getByteBuffer();
41 int offset = 0;
42 do {
43 final int length = Math.min(bytes.length - offset, buffer.remaining());
44 buffer.put(bytes, offset, length);
45 offset += length;
46 if (offset < bytes.length) {
47 buffer = destination.drain(buffer);
48 }
49 } while (offset < bytes.length);
50 }
51 }
52
53 static void encodeTextWithCopy(final CharsetEncoder charsetEncoder, final CharBuffer charBuf, final ByteBuffer temp,
54 final StringBuilder text, final ByteBufferDestination destination) {
55
56 encodeText(charsetEncoder, charBuf, temp, text, destination);
57 copyDataToDestination(temp, destination);
58 }
59
60 private static void copyDataToDestination(final ByteBuffer temp, final ByteBufferDestination destination) {
61 synchronized (destination) {
62 ByteBuffer destinationBuffer = destination.getByteBuffer();
63 if (destinationBuffer != temp) {
64 temp.flip();
65 if (temp.remaining() > destinationBuffer.remaining()) {
66 destinationBuffer = destination.drain(destinationBuffer);
67 }
68 destinationBuffer.put(temp);
69 temp.clear();
70 }
71 }
72 }
73
74 static void encodeText(final CharsetEncoder charsetEncoder, final CharBuffer charBuf, final ByteBuffer byteBuf,
75 final StringBuilder text, final ByteBufferDestination destination) {
76 charsetEncoder.reset();
77 ByteBuffer temp = byteBuf;
78 int start = 0;
79 int todoChars = text.length();
80 boolean endOfInput = true;
81 do {
82 charBuf.clear();
83 final int copied = copy(text, start, charBuf);
84 start += copied;
85 todoChars -= copied;
86 endOfInput = todoChars <= 0;
87
88 charBuf.flip();
89 temp = encode(charsetEncoder, charBuf, endOfInput, destination, temp);
90 } while (!endOfInput);
91 }
92
93
94
95
96 @Deprecated
97 public static void encodeText(final CharsetEncoder charsetEncoder, final CharBuffer charBuf,
98 final ByteBufferDestination destination) {
99 synchronized (destination) {
100 charsetEncoder.reset();
101 final ByteBuffer byteBuf = destination.getByteBuffer();
102 encode(charsetEncoder, charBuf, true, destination, byteBuf);
103 }
104 }
105
106 private static ByteBuffer encode(final CharsetEncoder charsetEncoder, final CharBuffer charBuf,
107 final boolean endOfInput, final ByteBufferDestination destination, ByteBuffer byteBuf) {
108 try {
109 byteBuf = encodeAsMuchAsPossible(charsetEncoder, charBuf, endOfInput, destination, byteBuf);
110 if (endOfInput) {
111 byteBuf = flushRemainingBytes(charsetEncoder, destination, byteBuf);
112 }
113 } catch (final CharacterCodingException ex) {
114 throw new IllegalStateException(ex);
115 }
116 return byteBuf;
117 }
118
119 private static ByteBuffer encodeAsMuchAsPossible(final CharsetEncoder charsetEncoder, final CharBuffer charBuf,
120 final boolean endOfInput, final ByteBufferDestination destination, ByteBuffer temp)
121 throws CharacterCodingException {
122 CoderResult result;
123 do {
124 result = charsetEncoder.encode(charBuf, temp, endOfInput);
125 temp = drainIfByteBufferFull(destination, temp, result);
126 } while (result.isOverflow());
127 if (!result.isUnderflow()) {
128 result.throwException();
129 }
130 return temp;
131 }
132
133 private static ByteBuffer drainIfByteBufferFull(final ByteBufferDestination destination, ByteBuffer temp, final CoderResult result) {
134 if (result.isOverflow()) {
135
136
137
138
139 ByteBuffer destinationBuffer = destination.getByteBuffer();
140 if (destinationBuffer != temp) {
141 temp.flip();
142 destinationBuffer.put(temp);
143 temp.clear();
144 }
145
146
147 destinationBuffer = destination.drain(destinationBuffer);
148 temp = destinationBuffer;
149 }
150 return temp;
151 }
152
153 private static ByteBuffer flushRemainingBytes(final CharsetEncoder charsetEncoder,
154 final ByteBufferDestination destination, ByteBuffer temp)
155 throws CharacterCodingException {
156 CoderResult result;
157 do {
158
159 result = charsetEncoder.flush(temp);
160 temp = drainIfByteBufferFull(destination, temp, result);
161 } while (result.isOverflow());
162 if (!result.isUnderflow()) {
163 result.throwException();
164 }
165 return temp;
166 }
167
168
169
170
171
172
173
174
175 static int copy(final StringBuilder source, final int offset, final CharBuffer destination) {
176 final int length = Math.min(source.length() - offset, destination.remaining());
177 final char[] array = destination.array();
178 final int start = destination.position();
179 source.getChars(offset, offset + length, array, start);
180 destination.position(start + length);
181 return length;
182 }
183 }