|
3 | 3 | import java.io.*;
|
4 | 4 | import java.math.BigDecimal;
|
5 | 5 | import java.math.BigInteger;
|
| 6 | +import java.nio.charset.StandardCharsets; |
6 | 7 |
|
7 | 8 | import com.fasterxml.jackson.core.*;
|
8 | 9 | import com.fasterxml.jackson.core.io.CharTypes;
|
@@ -659,6 +660,10 @@ public void writeUTF8String(byte[] text, int offset, int len) throws IOException
|
659 | 660 | _outputBuffer[_outputTail++] = _quoteChar;
|
660 | 661 | }
|
661 | 662 |
|
| 663 | + private boolean isSurrogatePair(char ch) { |
| 664 | + return (ch & 0xD800) == 0xD800; |
| 665 | + } |
| 666 | + |
662 | 667 | /*
|
663 | 668 | /**********************************************************
|
664 | 669 | /* Output method implementations, unprocessed ("raw")
|
@@ -1510,7 +1515,14 @@ private final void _writeStringSegment2(final char[] cbuf, int offset, final int
|
1510 | 1515 | outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6));
|
1511 | 1516 | outputBuffer[outputPtr++] = (byte) (0x80 | (ch & 0x3f));
|
1512 | 1517 | } else {
|
1513 |
| - outputPtr = _outputMultiByteChar(ch, outputPtr); |
| 1518 | + // multibyte character |
| 1519 | + if (Feature.WRITE_UTF8_SURROGATES.enabledIn(_features) && isSurrogatePair((char) ch) && offset < end) { |
| 1520 | + char highSurrogate = (char) ch; |
| 1521 | + char lowSurrogate = cbuf[offset++]; |
| 1522 | + outputPtr = _outputSurrogatePair(highSurrogate, lowSurrogate, outputPtr); |
| 1523 | + } else { |
| 1524 | + outputPtr = _outputMultiByteChar(ch, outputPtr); |
| 1525 | + } |
1514 | 1526 | }
|
1515 | 1527 | }
|
1516 | 1528 | _outputTail = outputPtr;
|
@@ -1548,7 +1560,14 @@ private final void _writeStringSegment2(final String text, int offset, final int
|
1548 | 1560 | outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6));
|
1549 | 1561 | outputBuffer[outputPtr++] = (byte) (0x80 | (ch & 0x3f));
|
1550 | 1562 | } else {
|
1551 |
| - outputPtr = _outputMultiByteChar(ch, outputPtr); |
| 1563 | + // multibyte character |
| 1564 | + if (Feature.WRITE_UTF8_SURROGATES.enabledIn(_features) && isSurrogatePair((char) ch) && offset < end) { |
| 1565 | + char highSurrogate = (char) ch; |
| 1566 | + char lowSurrogate = text.charAt(offset++); |
| 1567 | + outputPtr = _outputSurrogatePair(highSurrogate, lowSurrogate, outputPtr); |
| 1568 | + } else { |
| 1569 | + outputPtr = _outputMultiByteChar(ch, outputPtr); |
| 1570 | + } |
1552 | 1571 | }
|
1553 | 1572 | }
|
1554 | 1573 | _outputTail = outputPtr;
|
@@ -2133,6 +2152,13 @@ protected final void _outputSurrogates(int surr1, int surr2) throws IOException
|
2133 | 2152 | bbuf[_outputTail++] = (byte) (0x80 | (c & 0x3f));
|
2134 | 2153 | }
|
2135 | 2154 |
|
| 2155 | + private int _outputSurrogatePair(char highSurrogate, char lowSurrogate, int outputPtr) { |
| 2156 | + String s = String.valueOf(highSurrogate) + lowSurrogate; |
| 2157 | + byte[] bytes = s.getBytes(StandardCharsets.UTF_8); |
| 2158 | + System.arraycopy(bytes, 0, _outputBuffer, outputPtr, bytes.length); |
| 2159 | + return outputPtr + bytes.length; |
| 2160 | + } |
| 2161 | + |
2136 | 2162 | /**
|
2137 | 2163 | *
|
2138 | 2164 | * @param ch
|
|
0 commit comments