From df1cf7d2867ea3ca0dd65d04dc55b32ebc4cdf5d Mon Sep 17 00:00:00 2001 From: Sebastian Toepfer Date: Mon, 10 Jun 2024 20:49:35 +0200 Subject: [PATCH 1/2] replace for-loop with foreach from stream-api the for loop needs the length of the current string and than access the char character by character via charAt. this prevents the JsonString from reloading its content. the foreach from stream retrieve char by char without knowing the end. so the jsonstring can be extended and reloading his content from a source (like a database). this approach also fits the buffer of the generator > the string supplies the char at the same speed at which the generator can fill and write the buffer. Signed-off-by: Sebastian Toepfer --- .../eclipse/parsson/JsonGeneratorImpl.java | 82 ++++++++----------- 1 file changed, 35 insertions(+), 47 deletions(-) diff --git a/impl/src/main/java/org/eclipse/parsson/JsonGeneratorImpl.java b/impl/src/main/java/org/eclipse/parsson/JsonGeneratorImpl.java index a0cc0322..2055948c 100644 --- a/impl/src/main/java/org/eclipse/parsson/JsonGeneratorImpl.java +++ b/impl/src/main/java/org/eclipse/parsson/JsonGeneratorImpl.java @@ -540,53 +540,37 @@ public void close() { // begin end begin end void writeEscapedString(CharSequence string) { writeChar('"'); - int len = string.length(); - for(int i = 0; i < len; i++) { - int begin = i, end = i; - char c = string.charAt(i); - // find all the characters that need not be escaped - // unescaped = %x20-21 | %x23-5B | %x5D-10FFFF - while(c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { - i++; end = i; - if (i < len) { - c = string.charAt(i); - } else { - break; - } - } - // Write characters without escaping - if (begin < end) { - writeString(string, begin, end); - if (i == len) { - break; - } - } - - switch (c) { - case '"': - case '\\': - writeChar('\\'); writeChar(c); - break; - case '\b': - writeChar('\\'); writeChar('b'); - break; - case '\f': - writeChar('\\'); writeChar('f'); - break; - case '\n': - writeChar('\\'); writeChar('n'); - break; - case '\r': - writeChar('\\'); writeChar('r'); - break; - case '\t': - writeChar('\\'); writeChar('t'); - break; - default: - String hex = "000" + Integer.toHexString(c); - writeString("\\u" + hex.substring(hex.length() - 4)); - } - } + string.chars() + .forEach(c -> { + if (c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { + writeChar(c); + } else { + switch (c) { + case '"': + case '\\': + writeChar('\\'); writeChar(c); + break; + case '\b': + writeChar('\\'); writeChar('b'); + break; + case '\f': + writeChar('\\'); writeChar('f'); + break; + case '\n': + writeChar('\\'); writeChar('n'); + break; + case '\r': + writeChar('\\'); writeChar('r'); + break; + case '\t': + writeChar('\\'); writeChar('t'); + break; + default: + String hex = "000" + Integer.toHexString(c); + writeString("\\u" + hex.substring(hex.length() - 4)); + } + } + }); writeChar('"'); } @@ -611,6 +595,10 @@ void writeString(CharSequence str) { writeString(str, 0, str.length()); } + void writeChar(final int c) { + writeChar((char) c); + } + void writeChar(char c) { if (len >= buf.length) { flushBuffer(); From a3f2190c89c9ce067491ab93c430e663b7ef184b Mon Sep 17 00:00:00 2001 From: Sebastian Toepfer Date: Mon, 10 Jun 2024 21:02:19 +0200 Subject: [PATCH 2/2] also use stream-api foreach in strings toString not realy needed, only to ensure the idea works Signed-off-by: Sebastian Toepfer --- .../org/eclipse/parsson/JsonStringImpl.java | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/impl/src/main/java/org/eclipse/parsson/JsonStringImpl.java b/impl/src/main/java/org/eclipse/parsson/JsonStringImpl.java index 5b247edb..ab08ffc5 100644 --- a/impl/src/main/java/org/eclipse/parsson/JsonStringImpl.java +++ b/impl/src/main/java/org/eclipse/parsson/JsonStringImpl.java @@ -67,40 +67,38 @@ public boolean equals(Object obj) { public String toString() { StringBuilder sb = new StringBuilder(); sb.append('"'); - - for(int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - // unescaped = %x20-21 | %x23-5B | %x5D-10FFFF - if (c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { - sb.append(c); - } else { - switch (c) { - case '"': - case '\\': - sb.append('\\'); sb.append(c); - break; - case '\b': - sb.append('\\'); sb.append('b'); - break; - case '\f': - sb.append('\\'); sb.append('f'); - break; - case '\n': - sb.append('\\'); sb.append('n'); - break; - case '\r': - sb.append('\\'); sb.append('r'); - break; - case '\t': - sb.append('\\'); sb.append('t'); - break; - default: - String hex = "000" + Integer.toHexString(c); - sb.append("\\u").append(hex.substring(hex.length() - 4)); - } - } - } - + value.chars() + .forEach(c -> { + // unescaped = %x20-21 | %x23-5B | %x5D-10FFFF + if (c >= 0x20 && c <= 0x10ffff && c != 0x22 && c != 0x5c) { + sb.append((char) c); + } else { + switch (c) { + case '"': + case '\\': + sb.append('\\'); sb.append((char) c); + break; + case '\b': + sb.append('\\'); sb.append('b'); + break; + case '\f': + sb.append('\\'); sb.append('f'); + break; + case '\n': + sb.append('\\'); sb.append('n'); + break; + case '\r': + sb.append('\\'); sb.append('r'); + break; + case '\t': + sb.append('\\'); sb.append('t'); + break; + default: + String hex = "000" + Integer.toHexString(c); + sb.append("\\u").append(hex.substring(hex.length() - 4)); + } + } + }); sb.append('"'); return sb.toString(); }