@@ -30,8 +30,14 @@ public final class JsonStringEncoder
30
30
private final static int SURR2_FIRST = 0xDC00 ;
31
31
private final static int SURR2_LAST = 0xDFFF ;
32
32
33
- private final static int INITIAL_CHAR_BUFFER_SIZE = 120 ;
34
- private final static int INITIAL_BYTE_BUFFER_SIZE = 200 ;
33
+ // 18-Aug-2021, tatu: [core#712] Change to more dynamic allocation; try
34
+ // to estimate ok initial encoding buffer, switch to segmented for
35
+ // possible (but rare) big content
36
+
37
+ final static int MIN_CHAR_BUFFER_SIZE = 16 ;
38
+ final static int MAX_CHAR_BUFFER_SIZE = 32000 ; // use segments beyond
39
+ final static int MIN_BYTE_BUFFER_SIZE = 24 ;
40
+ final static int MAX_BYTE_BUFFER_SIZE = 32000 ; // use segments beyond
35
41
36
42
/*
37
43
/**********************************************************************
@@ -70,11 +76,11 @@ public static JsonStringEncoder getInstance() {
70
76
*/
71
77
public char [] quoteAsString (String input )
72
78
{
73
- char [] outputBuffer = new char [INITIAL_CHAR_BUFFER_SIZE ];
79
+ final int inputLen = input .length ();
80
+ char [] outputBuffer = new char [_initialCharBufSize (inputLen )];
74
81
final int [] escCodes = CharTypes .get7BitOutputEscapes ();
75
82
final int escCodeCount = escCodes .length ;
76
83
int inPtr = 0 ;
77
- final int inputLen = input .length ();
78
84
TextBuffer textBuffer = null ;
79
85
int outPtr = 0 ;
80
86
char [] qbuf = null ;
@@ -152,11 +158,11 @@ public char[] quoteAsString(CharSequence input)
152
158
153
159
TextBuffer textBuffer = null ;
154
160
155
- char [] outputBuffer = new char [INITIAL_CHAR_BUFFER_SIZE ];
161
+ final int inputLen = input .length ();
162
+ char [] outputBuffer = new char [_initialCharBufSize (inputLen )];
156
163
final int [] escCodes = CharTypes .get7BitOutputEscapes ();
157
164
final int escCodeCount = escCodes .length ;
158
165
int inPtr = 0 ;
159
- final int inputLen = input .length ();
160
166
int outPtr = 0 ;
161
167
char [] qbuf = null ;
162
168
@@ -274,7 +280,7 @@ public byte[] quoteAsUTF8(String text)
274
280
int inputPtr = 0 ;
275
281
int inputEnd = text .length ();
276
282
int outputPtr = 0 ;
277
- byte [] outputBuffer = new byte [INITIAL_BYTE_BUFFER_SIZE ];
283
+ byte [] outputBuffer = new byte [_initialByteBufSize ( inputEnd ) ];
278
284
ByteArrayBuilder bb = null ;
279
285
280
286
main :
@@ -380,7 +386,7 @@ public byte[] encodeAsUTF8(String text)
380
386
int inputPtr = 0 ;
381
387
int inputEnd = text .length ();
382
388
int outputPtr = 0 ;
383
- byte [] outputBuffer = new byte [INITIAL_BYTE_BUFFER_SIZE ];
389
+ byte [] outputBuffer = new byte [_initialByteBufSize ( inputEnd ) ];
384
390
int outputEnd = outputBuffer .length ;
385
391
ByteArrayBuilder bb = null ;
386
392
@@ -481,7 +487,7 @@ public byte[] encodeAsUTF8(CharSequence text)
481
487
int inputPtr = 0 ;
482
488
int inputEnd = text .length ();
483
489
int outputPtr = 0 ;
484
- byte [] outputBuffer = new byte [INITIAL_BYTE_BUFFER_SIZE ];
490
+ byte [] outputBuffer = new byte [_initialByteBufSize ( inputEnd ) ];
485
491
int outputEnd = outputBuffer .length ;
486
492
ByteArrayBuilder bb = null ;
487
493
@@ -628,4 +634,22 @@ private static int _convert(int p1, int p2) {
628
634
private static void _illegal (int c ) {
629
635
throw new IllegalArgumentException (UTF8Writer .illegalSurrogateDesc (c ));
630
636
}
637
+
638
+ // non-private for unit test access
639
+ static int _initialCharBufSize (int strLen ) {
640
+ // char->char won't expand but we need to give some room for escaping
641
+ // like 1/8 (12.5% expansion) but cap addition to something modest
642
+ final int estimated = Math .max (MIN_CHAR_BUFFER_SIZE ,
643
+ strLen + Math .min (6 + (strLen >> 3 ), 1000 ));
644
+ return Math .min (estimated , MAX_CHAR_BUFFER_SIZE );
645
+ }
646
+
647
+ // non-private for unit test access
648
+ static int _initialByteBufSize (int strLen ) {
649
+ // char->byte for UTF-8 can expand size by x3 itself, and escaping
650
+ // more... but let's use lower factor of 1.5
651
+ final int doubled = Math .max (MIN_BYTE_BUFFER_SIZE , strLen + 6 + (strLen >>1 ));
652
+ // but use upper bound for humongous cases (segmented)
653
+ return Math .min (doubled , MAX_BYTE_BUFFER_SIZE );
654
+ }
631
655
}
0 commit comments