Skip to content

Commit a42a5de

Browse files
committed
More efficient serialization of strings with escaped unicodes for JVMs and Scala Native
1 parent f1b1417 commit a42a5de

File tree

2 files changed

+22
-26
lines changed
  • jsoniter-scala-core

2 files changed

+22
-26
lines changed

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ final class JsonWriter private[jsoniter_scala](
13111311
}
13121312

13131313
private[this] def writeEscapedOrEncodedString(s: String, from: Int, pos: Int): Int =
1314-
if (config.escapeUnicode) writeEscapedString(s, from, s.length, pos, limit - 13, escapedChars)
1314+
if (config.escapeUnicode) writeEscapedString(s, from, s.length, pos, limit - 13, escapedChars, lowerCaseHexDigits)
13151315
else writeEncodedString(s, from, s.length, pos, limit - 7, escapedChars)
13161316

13171317
@tailrec
@@ -1328,7 +1328,7 @@ final class JsonWriter private[jsoniter_scala](
13281328
} else if (esc > 0) {
13291329
ByteArrayAccess.setShort(buf, pos, (esc << 8 | 0x5C).toShort)
13301330
writeEncodedString(s, from + 1, to, pos + 2, posLim, escapedChars)
1331-
} else writeEncodedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf), posLim, escapedChars)
1331+
} else writeEncodedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf, lowerCaseHexDigits), posLim, escapedChars)
13321332
} else if (ch1 < 0x800) { // 00000bbbbbaaaaaa (UTF-16 char) -> 110bbbbb 10aaaaaa (UTF-8 bytes)
13331333
ByteArrayAccess.setShort(buf, pos, (ch1 >> 6 | (ch1 << 8 & 0x3F00) | 0x80C0).toShort)
13341334
writeEncodedString(s, from + 1, to, pos + 2, posLim, escapedChars)
@@ -1348,29 +1348,29 @@ final class JsonWriter private[jsoniter_scala](
13481348
}
13491349

13501350
@tailrec
1351-
private[this] def writeEscapedString(s: String, from: Int, to: Int, pos: Int, posLim: Int, escapedChars: Array[Byte]): Int =
1351+
private[this] def writeEscapedString(s: String, from: Int, to: Int, pos: Int, posLim: Int, escapedChars: Array[Byte], ds: Array[Short]): Int =
13521352
if (from >= to) pos
1353-
else if (pos >= posLim) writeEscapedString(s, from, to, flushAndGrowBuf(13, pos), limit - 12, escapedChars)
1353+
else if (pos >= posLim) writeEscapedString(s, from, to, flushAndGrowBuf(13, pos), limit - 12, escapedChars, ds)
13541354
else {
13551355
val ch1 = s.charAt(from).toInt
13561356
if (ch1 < 0x80) {
13571357
val esc = escapedChars(ch1)
13581358
if (esc == 0) {
13591359
buf(pos) = ch1.toByte
1360-
writeEscapedString(s, from + 1, to, pos + 1, posLim, escapedChars)
1360+
writeEscapedString(s, from + 1, to, pos + 1, posLim, escapedChars, ds)
13611361
} else if (esc > 0) {
13621362
ByteArrayAccess.setShort(buf, pos, (esc << 8 | 0x5C).toShort)
1363-
writeEscapedString(s, from + 1, to, pos + 2, posLim, escapedChars)
1364-
} else writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf), posLim, escapedChars)
1363+
writeEscapedString(s, from + 1, to, pos + 2, posLim, escapedChars, ds)
1364+
} else writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf, ds), posLim, escapedChars, ds)
13651365
} else if ((ch1 & 0xF800) != 0xD800) {
1366-
writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1, pos, buf), posLim, escapedChars)
1366+
writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1, pos, buf, ds), posLim, escapedChars, ds)
13671367
} else {
13681368
var ch2 = 0
13691369
if (ch1 >= 0xDC00 || from + 1 >= to || {
13701370
ch2 = s.charAt(from + 1).toInt
13711371
(ch2 & 0xFC00) != 0xDC00
13721372
}) illegalSurrogateError()
1373-
writeEscapedString(s, from + 2, to, writeEscapedUnicode(ch2, writeEscapedUnicode(ch1, pos, buf), buf), posLim, escapedChars)
1373+
writeEscapedString(s, from + 2, to, writeEscapedUnicode(ch2, writeEscapedUnicode(ch1, pos, buf, ds), buf, ds), posLim, escapedChars, ds)
13741374
}
13751375
}
13761376

@@ -1406,17 +1406,15 @@ final class JsonWriter private[jsoniter_scala](
14061406
count = pos
14071407
}
14081408

1409-
private[this] def writeEscapedUnicode(ch: Int, pos: Int, buf: Array[Byte]): Int = {
1410-
val ds = lowerCaseHexDigits
1409+
private[this] def writeEscapedUnicode(ch: Int, pos: Int, buf: Array[Byte], ds: Array[Short]): Int = {
14111410
ByteArrayAccess.setShort(buf, pos, 0x755C)
14121411
val d1 = ds(ch >> 8)
14131412
val d2 = ds(ch & 0xFF) << 16
14141413
ByteArrayAccess.setInt(buf, pos + 2, d1 | d2)
14151414
pos + 6
14161415
}
14171416

1418-
private[this] def writeEscapedUnicode(b: Byte, pos: Int, buf: Array[Byte]): Int = {
1419-
val ds = lowerCaseHexDigits
1417+
private[this] def writeEscapedUnicode(b: Byte, pos: Int, buf: Array[Byte], ds: Array[Short]): Int = {
14201418
ByteArrayAccess.setInt(buf, pos, 0x3030755C)
14211419
ByteArrayAccess.setShort(buf, pos + 4, ds(b & 0xFF))
14221420
pos + 6

jsoniter-scala-core/native/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ final class JsonWriter private[jsoniter_scala](
13111311
}
13121312

13131313
private[this] def writeEscapedOrEncodedString(s: String, from: Int, pos: Int): Int =
1314-
if (config.escapeUnicode) writeEscapedString(s, from, s.length, pos, limit - 13, escapedChars)
1314+
if (config.escapeUnicode) writeEscapedString(s, from, s.length, pos, limit - 13, escapedChars, lowerCaseHexDigits)
13151315
else writeEncodedString(s, from, s.length, pos, limit - 7, escapedChars)
13161316

13171317
@tailrec
@@ -1328,7 +1328,7 @@ final class JsonWriter private[jsoniter_scala](
13281328
} else if (esc > 0) {
13291329
ByteArrayAccess.setShort(buf, pos, (esc << 8 | 0x5C).toShort)
13301330
writeEncodedString(s, from + 1, to, pos + 2, posLim, escapedChars)
1331-
} else writeEncodedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf), posLim, escapedChars)
1331+
} else writeEncodedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf, lowerCaseHexDigits), posLim, escapedChars)
13321332
} else if (ch1 < 0x800) { // 00000bbbbbaaaaaa (UTF-16 char) -> 110bbbbb 10aaaaaa (UTF-8 bytes)
13331333
ByteArrayAccess.setShort(buf, pos, (ch1 >> 6 | (ch1 << 8 & 0x3F00) | 0x80C0).toShort)
13341334
writeEncodedString(s, from + 1, to, pos + 2, posLim, escapedChars)
@@ -1348,29 +1348,29 @@ final class JsonWriter private[jsoniter_scala](
13481348
}
13491349

13501350
@tailrec
1351-
private[this] def writeEscapedString(s: String, from: Int, to: Int, pos: Int, posLim: Int, escapedChars: Array[Byte]): Int =
1351+
private[this] def writeEscapedString(s: String, from: Int, to: Int, pos: Int, posLim: Int, escapedChars: Array[Byte], ds: Array[Short]): Int =
13521352
if (from >= to) pos
1353-
else if (pos >= posLim) writeEscapedString(s, from, to, flushAndGrowBuf(13, pos), limit - 12, escapedChars)
1353+
else if (pos >= posLim) writeEscapedString(s, from, to, flushAndGrowBuf(13, pos), limit - 12, escapedChars, ds)
13541354
else {
13551355
val ch1 = s.charAt(from).toInt
13561356
if (ch1 < 0x80) {
13571357
val esc = escapedChars(ch1)
13581358
if (esc == 0) {
13591359
buf(pos) = ch1.toByte
1360-
writeEscapedString(s, from + 1, to, pos + 1, posLim, escapedChars)
1360+
writeEscapedString(s, from + 1, to, pos + 1, posLim, escapedChars, ds)
13611361
} else if (esc > 0) {
13621362
ByteArrayAccess.setShort(buf, pos, (esc << 8 | 0x5C).toShort)
1363-
writeEscapedString(s, from + 1, to, pos + 2, posLim, escapedChars)
1364-
} else writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf), posLim, escapedChars)
1363+
writeEscapedString(s, from + 1, to, pos + 2, posLim, escapedChars, ds)
1364+
} else writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1.toByte, pos, buf, ds), posLim, escapedChars, ds)
13651365
} else if ((ch1 & 0xF800) != 0xD800) {
1366-
writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1, pos, buf), posLim, escapedChars)
1366+
writeEscapedString(s, from + 1, to, writeEscapedUnicode(ch1, pos, buf, ds), posLim, escapedChars, ds)
13671367
} else {
13681368
var ch2 = 0
13691369
if (ch1 >= 0xDC00 || from + 1 >= to || {
13701370
ch2 = s.charAt(from + 1).toInt
13711371
(ch2 & 0xFC00) != 0xDC00
13721372
}) illegalSurrogateError()
1373-
writeEscapedString(s, from + 2, to, writeEscapedUnicode(ch2, writeEscapedUnicode(ch1, pos, buf), buf), posLim, escapedChars)
1373+
writeEscapedString(s, from + 2, to, writeEscapedUnicode(ch2, writeEscapedUnicode(ch1, pos, buf, ds), buf, ds), posLim, escapedChars, ds)
13741374
}
13751375
}
13761376

@@ -1406,17 +1406,15 @@ final class JsonWriter private[jsoniter_scala](
14061406
count = pos
14071407
}
14081408

1409-
private[this] def writeEscapedUnicode(ch: Int, pos: Int, buf: Array[Byte]): Int = {
1410-
val ds = lowerCaseHexDigits
1409+
private[this] def writeEscapedUnicode(ch: Int, pos: Int, buf: Array[Byte], ds: Array[Short]): Int = {
14111410
ByteArrayAccess.setShort(buf, pos, 0x755C)
14121411
val d1 = ds(ch >> 8)
14131412
val d2 = ds(ch & 0xFF) << 16
14141413
ByteArrayAccess.setInt(buf, pos + 2, d1 | d2)
14151414
pos + 6
14161415
}
14171416

1418-
private[this] def writeEscapedUnicode(b: Byte, pos: Int, buf: Array[Byte]): Int = {
1419-
val ds = lowerCaseHexDigits
1417+
private[this] def writeEscapedUnicode(b: Byte, pos: Int, buf: Array[Byte], ds: Array[Short]): Int = {
14201418
ByteArrayAccess.setInt(buf, pos, 0x3030755C)
14211419
ByteArrayAccess.setShort(buf, pos + 4, ds(b & 0xFF))
14221420
pos + 6

0 commit comments

Comments
 (0)