@@ -307,34 +307,59 @@ private static final class BufferPositionPair {
307
307
}
308
308
309
309
protected int writeCharacters (final String str , final boolean checkNullTermination ) {
310
- int len = str .length ();
310
+ int stringLength = str .length ();
311
311
int sp = 0 ;
312
312
int prevPos = position ;
313
313
314
- ByteBuf buf = getCurrentByteBuffer ();
315
- int currBufferPos = buf .position ();
316
- int limit = buf .limit ();
317
- int remaining = limit - currBufferPos ;
314
+ ByteBuf curBuffer = getCurrentByteBuffer ();
315
+ int curBufferPos = curBuffer .position ();
316
+ int curBufferLimit = curBuffer .limit ();
317
+ int remaining = curBufferLimit - curBufferPos ;
318
318
319
- if (buf .hasArray ()) {
320
- byte [] dst = buf .array ();
321
- int arrayOffset = buf .arrayOffset ();
319
+ if (curBuffer .hasArray ()) {
320
+ byte [] dst = curBuffer .array ();
321
+ int arrayOffset = curBuffer .arrayOffset ();
322
322
if (remaining >= str .length () + 1 ) {
323
- sp = writeOnArrayAscii (str , dst , arrayOffset + currBufferPos , checkNullTermination );
324
- currBufferPos += sp ;
325
- if (sp == len ) {
326
- dst [arrayOffset + currBufferPos ++] = 0 ;
323
+ // Write ASCII characters directly to the array until we hit a non-ASCII character
324
+ sp = writeOnArrayAscii (str , dst , arrayOffset + curBufferPos , checkNullTermination );
325
+ curBufferPos += sp ;
326
+ if (sp == stringLength ) {
327
+ dst [arrayOffset + curBufferPos ++] = 0 ;
327
328
position += sp + 1 ;
328
- buf .position (currBufferPos );
329
+ curBuffer .position (curBufferPos );
329
330
return sp + 1 ;
330
331
}
331
332
position += sp ;
332
- buf .position (currBufferPos );
333
+ curBuffer .position (curBufferPos );
333
334
}
334
335
}
335
336
336
- while (sp < len ) {
337
- remaining = limit - currBufferPos ;
337
+ // We get here, when the buffer is not backed by an array, or when the string contains non-ASCII characters.
338
+ return writeOnBuffers (str ,
339
+ checkNullTermination ,
340
+ sp ,
341
+ stringLength ,
342
+ curBufferLimit ,
343
+ curBufferPos ,
344
+ curBuffer ,
345
+ prevPos );
346
+ }
347
+
348
+ private int writeOnBuffers (final String str ,
349
+ final boolean checkNullTermination ,
350
+ final int stringPointer ,
351
+ final int stringLength ,
352
+ final int bufferLimit ,
353
+ final int bufferPos ,
354
+ final ByteBuf buffer ,
355
+ final int prevPos ) {
356
+ int remaining ;
357
+ int sp = stringPointer ;
358
+ int curBufferPos = bufferPos ;
359
+ int curBufferLimit = bufferLimit ;
360
+ ByteBuf curBuffer = buffer ;
361
+ while (sp < stringLength ) {
362
+ remaining = curBufferLimit - curBufferPos ;
338
363
int c = str .charAt (sp );
339
364
340
365
if (checkNullTermination && c == 0x0 ) {
@@ -344,43 +369,49 @@ protected int writeCharacters(final String str, final boolean checkNullTerminati
344
369
345
370
if (c < 0x80 ) {
346
371
if (remaining == 0 ) {
347
- buf = getNextByteBuffer ();
348
- currBufferPos = 0 ;
349
- limit = buf .limit ();
372
+ curBuffer = getNextByteBuffer ();
373
+ curBufferPos = 0 ;
374
+ curBufferLimit = curBuffer .limit ();
350
375
}
351
- buf .put ((byte ) c );
352
- currBufferPos ++;
376
+ curBuffer .put ((byte ) c );
377
+ curBufferPos ++;
353
378
position ++;
354
379
} else if (c < 0x800 ) {
355
380
if (remaining < 2 ) {
356
381
write ((byte ) (0xc0 + (c >> 6 )));
357
382
write ((byte ) (0x80 + (c & 0x3f )));
358
383
359
- buf = getCurrentByteBuffer ();
360
- currBufferPos = buf .position ();
361
- limit = buf .limit ();
384
+ curBuffer = getCurrentByteBuffer ();
385
+ curBufferPos = curBuffer .position ();
386
+ curBufferLimit = curBuffer .limit ();
362
387
} else {
363
- buf .put ((byte ) (0xc0 + (c >> 6 )));
364
- buf .put ((byte ) (0x80 + (c & 0x3f )));
365
- currBufferPos += 2 ;
388
+ curBuffer .put ((byte ) (0xc0 + (c >> 6 )));
389
+ curBuffer .put ((byte ) (0x80 + (c & 0x3f )));
390
+ curBufferPos += 2 ;
366
391
position += 2 ;
367
392
}
368
393
} else {
394
+ // Handle multibyte characters (may involve surrogate pairs)
369
395
c = Character .codePointAt (str , sp );
396
+ /*
397
+ Malformed surrogate pairs are encoded as-is (3 byte code unit) without substituting any code point.
398
+ This known deviation from the spec and current functionality remains for backward compatibility.
399
+ Ticket: JAVA-5575
400
+ */
370
401
if (c < 0x10000 ) {
371
402
if (remaining < 3 ) {
372
403
write ((byte ) (0xe0 + (c >> 12 )));
373
404
write ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
374
405
write ((byte ) (0x80 + (c & 0x3f )));
375
406
376
- buf = getCurrentByteBuffer ();
377
- currBufferPos = buf .position ();
378
- limit = buf .limit ();
407
+ curBuffer = getCurrentByteBuffer ();
408
+ curBufferPos = curBuffer .position ();
409
+ curBufferLimit = curBuffer .limit ();
379
410
} else {
380
- buf .put ((byte ) (0xe0 + (c >> 12 )));
381
- buf .put ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
382
- buf .put ((byte ) (0x80 + (c & 0x3f )));
383
- currBufferPos += 3 ;
411
+ curBuffer .put ((byte ) (0xe0 + (c >> 12 )));
412
+ curBuffer .put ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
413
+ curBuffer .put ((byte ) (0x80 + (c & 0x3f )));
414
+ curBufferPos += 3 ;
384
415
position += 3 ;
385
416
}
386
417
} else {
@@ -390,15 +421,15 @@ protected int writeCharacters(final String str, final boolean checkNullTerminati
390
421
write ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
391
422
write ((byte ) (0x80 + (c & 0x3f )));
392
423
393
- buf = getCurrentByteBuffer ();
394
- currBufferPos = buf .position ();
395
- limit = buf .limit ();
424
+ curBuffer = getCurrentByteBuffer ();
425
+ curBufferPos = curBuffer .position ();
426
+ curBufferLimit = curBuffer .limit ();
396
427
} else {
397
- buf .put ((byte ) (0xf0 + (c >> 18 )));
398
- buf .put ((byte ) (0x80 + ((c >> 12 ) & 0x3f )));
399
- buf .put ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
400
- buf .put ((byte ) (0x80 + (c & 0x3f )));
401
- currBufferPos += 4 ;
428
+ curBuffer .put ((byte ) (0xf0 + (c >> 18 )));
429
+ curBuffer .put ((byte ) (0x80 + ((c >> 12 ) & 0x3f )));
430
+ curBuffer .put ((byte ) (0x80 + ((c >> 6 ) & 0x3f )));
431
+ curBuffer .put ((byte ) (0x80 + (c & 0x3f )));
432
+ curBufferPos += 4 ;
402
433
position += 4 ;
403
434
}
404
435
}
0 commit comments