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")
@@ -1489,6 +1494,8 @@ private final void _writeStringSegment2(final char[] cbuf, int offset, final int
1489
1494
final byte [] outputBuffer = _outputBuffer ;
1490
1495
final int [] escCodes = _outputEscapes ;
1491
1496
1497
+ boolean combineSurrogates = Feature .COMBINE_UNICODE_SURROGATES .enabledIn (_features );
1498
+
1492
1499
while (offset < end ) {
1493
1500
int ch = cbuf [offset ++];
1494
1501
if (ch <= 0x7F ) {
@@ -1510,7 +1517,14 @@ private final void _writeStringSegment2(final char[] cbuf, int offset, final int
1510
1517
outputBuffer [outputPtr ++] = (byte ) (0xc0 | (ch >> 6 ));
1511
1518
outputBuffer [outputPtr ++] = (byte ) (0x80 | (ch & 0x3f ));
1512
1519
} else {
1513
- outputPtr = _outputMultiByteChar (ch , outputPtr );
1520
+ // multibyte character
1521
+ if (combineSurrogates && isSurrogatePair ((char ) ch ) && offset < end ) {
1522
+ char highSurrogate = (char ) ch ;
1523
+ char lowSurrogate = cbuf [offset ++];
1524
+ outputPtr = _outputSurrogatePair (highSurrogate , lowSurrogate , outputPtr );
1525
+ } else {
1526
+ outputPtr = _outputMultiByteChar (ch , outputPtr );
1527
+ }
1514
1528
}
1515
1529
}
1516
1530
_outputTail = outputPtr ;
@@ -1527,6 +1541,8 @@ private final void _writeStringSegment2(final String text, int offset, final int
1527
1541
final byte [] outputBuffer = _outputBuffer ;
1528
1542
final int [] escCodes = _outputEscapes ;
1529
1543
1544
+ boolean combineSurrogates = Feature .COMBINE_UNICODE_SURROGATES .enabledIn (_features );
1545
+
1530
1546
while (offset < end ) {
1531
1547
int ch = text .charAt (offset ++);
1532
1548
if (ch <= 0x7F ) {
@@ -1548,7 +1564,14 @@ private final void _writeStringSegment2(final String text, int offset, final int
1548
1564
outputBuffer [outputPtr ++] = (byte ) (0xc0 | (ch >> 6 ));
1549
1565
outputBuffer [outputPtr ++] = (byte ) (0x80 | (ch & 0x3f ));
1550
1566
} else {
1551
- outputPtr = _outputMultiByteChar (ch , outputPtr );
1567
+ // multibyte character
1568
+ if (combineSurrogates && isSurrogatePair ((char ) ch ) && offset < end ) {
1569
+ char highSurrogate = (char ) ch ;
1570
+ char lowSurrogate = text .charAt (offset ++);
1571
+ outputPtr = _outputSurrogatePair (highSurrogate , lowSurrogate , outputPtr );
1572
+ } else {
1573
+ outputPtr = _outputMultiByteChar (ch , outputPtr );
1574
+ }
1552
1575
}
1553
1576
}
1554
1577
_outputTail = outputPtr ;
@@ -2133,6 +2156,13 @@ protected final void _outputSurrogates(int surr1, int surr2) throws IOException
2133
2156
bbuf [_outputTail ++] = (byte ) (0x80 | (c & 0x3f ));
2134
2157
}
2135
2158
2159
+ private int _outputSurrogatePair (char highSurrogate , char lowSurrogate , int outputPtr ) {
2160
+ String s = String .valueOf (highSurrogate ) + lowSurrogate ;
2161
+ byte [] bytes = s .getBytes (StandardCharsets .UTF_8 );
2162
+ System .arraycopy (bytes , 0 , _outputBuffer , outputPtr , bytes .length );
2163
+ return outputPtr + bytes .length ;
2164
+ }
2165
+
2136
2166
/**
2137
2167
*
2138
2168
* @param ch
0 commit comments