From f02df6fc0b006cc58c3271087416081d6d04665f Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Fri, 18 Mar 2022 14:57:41 +0300 Subject: [PATCH] Avoid producing garbage in escaping quotes fixes #377 --- .../net/openhft/chronicle/wire/CSVWire.java | 5 ++-- .../net/openhft/chronicle/wire/JSONWire.java | 10 +++++++ .../net/openhft/chronicle/wire/TextWire.java | 28 +++++++++++-------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/wire/CSVWire.java b/src/main/java/net/openhft/chronicle/wire/CSVWire.java index b20d02320..9717be070 100644 --- a/src/main/java/net/openhft/chronicle/wire/CSVWire.java +++ b/src/main/java/net/openhft/chronicle/wire/CSVWire.java @@ -27,6 +27,7 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; /** * YAML Based wire format @@ -34,6 +35,7 @@ public class CSVWire extends TextWire { private static final ThreadLocal> ESCAPED_END_OF_TEXT = new ThreadLocal<>(); + static final Supplier COMMA_STOP_ESCAPING = StopCharTesters.COMMA_STOP::escaping; private final List header = new ArrayList<>(); @@ -65,8 +67,7 @@ public static CSVWire from(@NotNull String text) { @NotNull static StopCharTester getEscapingCSVEndOfText() { - StopCharTester escaping = ThreadLocalHelper.getTL(ESCAPED_END_OF_TEXT, - StopCharTesters.COMMA_STOP::escaping); + StopCharTester escaping = ThreadLocalHelper.getTL(ESCAPED_END_OF_TEXT, COMMA_STOP_ESCAPING); // reset it. escaping.isStopChar(' '); return escaping; diff --git a/src/main/java/net/openhft/chronicle/wire/JSONWire.java b/src/main/java/net/openhft/chronicle/wire/JSONWire.java index 456d0442b..0d936d33b 100644 --- a/src/main/java/net/openhft/chronicle/wire/JSONWire.java +++ b/src/main/java/net/openhft/chronicle/wire/JSONWire.java @@ -19,6 +19,7 @@ import net.openhft.chronicle.bytes.Bytes; import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.StopCharsTester; import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.core.io.IORuntimeException; import net.openhft.chronicle.core.util.ClassNotFoundRuntimeException; @@ -32,6 +33,7 @@ import java.time.LocalTime; import java.util.Map; import java.util.function.BiFunction; +import java.util.function.Supplier; import static net.openhft.chronicle.bytes.NativeBytes.nativeBytes; @@ -43,6 +45,7 @@ public class JSONWire extends TextWire { @SuppressWarnings("rawtypes") static final BytesStore COMMA = BytesStore.from(","); + static final Supplier STRICT_END_OF_TEXT_JSON_ESCAPING = TextStopCharsTesters.STRICT_END_OF_TEXT_JSON::escaping; boolean useTypes; @SuppressWarnings("rawtypes") @@ -201,11 +204,18 @@ protected StringBuilder readField(@NotNull StringBuilder sb) { } @Override + @Deprecated(/* To be removed in 2.24 */) @NotNull protected TextStopCharsTesters strictEndOfText() { return TextStopCharsTesters.STRICT_END_OF_TEXT_JSON; } + @Override + @NotNull + protected Supplier strictEndOfTextEscaping() { + return STRICT_END_OF_TEXT_JSON_ESCAPING; + } + class JSONValueOut extends TextValueOut { @NotNull @Override diff --git a/src/main/java/net/openhft/chronicle/wire/TextWire.java b/src/main/java/net/openhft/chronicle/wire/TextWire.java index 11de24529..d2b362336 100644 --- a/src/main/java/net/openhft/chronicle/wire/TextWire.java +++ b/src/main/java/net/openhft/chronicle/wire/TextWire.java @@ -77,6 +77,11 @@ public class TextWire extends AbstractWire implements Wire { static final BytesStore END_FIELD = NEW_LINE; static final char[] HEXADECIMAL = "0123456789ABCDEF".toCharArray(); static final Pattern REGX_PATTERN = Pattern.compile("\\.|\\$"); + static final Supplier QUOTES_ESCAPING = StopCharTesters.QUOTES::escaping; + static final Supplier SINGLE_QUOTES_ESCAPING = StopCharTesters.SINGLE_QUOTES::escaping; + static final Supplier END_OF_TEXT_ESCAPING = TextStopCharTesters.END_OF_TEXT::escaping; + static final Supplier STRICT_END_OF_TEXT_ESCAPING = TextStopCharsTesters.STRICT_END_OF_TEXT::escaping; + static final Supplier END_EVENT_NAME_ESCAPING = TextStopCharsTesters.END_EVENT_NAME::escaping; static { IOTools.unmonitor(TYPE); @@ -199,8 +204,7 @@ public static void unescape(@NotNull ACS @Nullable static StopCharTester getEscapingSingleQuotes() { - StopCharTester sct = ThreadLocalHelper.getTL(ESCAPED_SINGLE_QUOTES, - StopCharTesters.SINGLE_QUOTES::escaping); + StopCharTester sct = ThreadLocalHelper.getTL(ESCAPED_SINGLE_QUOTES, SINGLE_QUOTES_ESCAPING); // reset it. sct.isStopChar(' '); return sct; @@ -534,8 +538,7 @@ private K toExpected(Class expectedClass, StringBuilder sb) { @NotNull protected StopCharTester getEscapingEndOfText() { - StopCharTester escaping = ThreadLocalHelper.getTL(ESCAPED_END_OF_TEXT, - TextStopCharTesters.END_OF_TEXT::escaping); + StopCharTester escaping = ThreadLocalHelper.getTL(ESCAPED_END_OF_TEXT, END_OF_TEXT_ESCAPING); // reset it. escaping.isStopChar(' '); return escaping; @@ -543,23 +546,27 @@ protected StopCharTester getEscapingEndOfText() { @NotNull protected StopCharsTester getStrictEscapingEndOfText() { - TextStopCharsTesters strictEndOfText = strictEndOfText(); - StopCharsTester escaping = ThreadLocalHelper.getTL(STRICT_ESCAPED_END_OF_TEXT, - strictEndOfText::escaping); + StopCharsTester escaping = ThreadLocalHelper.getTL(STRICT_ESCAPED_END_OF_TEXT, strictEndOfTextEscaping()); // reset it. escaping.isStopChar(' ', ' '); return escaping; } @NotNull + @Deprecated(/* To be removed in 2.24 - use strictEndOfTextEscaping */) protected TextStopCharsTesters strictEndOfText() { return TextStopCharsTesters.STRICT_END_OF_TEXT; } + @NotNull + protected Supplier strictEndOfTextEscaping() { + return strictEndOfText() == TextStopCharsTesters.STRICT_END_OF_TEXT ? + STRICT_END_OF_TEXT_ESCAPING : strictEndOfText()::escaping; + } + @NotNull protected StopCharsTester getEscapingEndEventName() { - StopCharsTester escaping = ThreadLocalHelper.getTL(STRICT_ESCAPED_END_OF_TEXT, - TextStopCharsTesters.END_EVENT_NAME::escaping); + StopCharsTester escaping = ThreadLocalHelper.getTL(STRICT_ESCAPED_END_OF_TEXT, END_EVENT_NAME_ESCAPING); // reset it. escaping.isStopChar(' ', ' '); return escaping; @@ -567,8 +574,7 @@ protected StopCharsTester getEscapingEndEventName() { @Nullable protected StopCharTester getEscapingQuotes() { - StopCharTester sct = ThreadLocalHelper.getTL(ESCAPED_QUOTES, - StopCharTesters.QUOTES::escaping); + StopCharTester sct = ThreadLocalHelper.getTL(ESCAPED_QUOTES, QUOTES_ESCAPING); // reset it. sct.isStopChar(' '); return sct;