Skip to content

Commit

Permalink
Reuse YamlWireOut#sb safely
Browse files Browse the repository at this point in the history
  • Loading branch information
nicktindall committed Apr 18, 2024
1 parent c880412 commit b03500f
Show file tree
Hide file tree
Showing 6 changed files with 502 additions and 396 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
<configuration>
<referenceVersion>2.25ea0</referenceVersion>
<artifactsURI>https://teamcity.chronicle.software/repository/download</artifactsURI>
<binaryCompatibilityPercentageRequired>99.6</binaryCompatibilityPercentageRequired>
<binaryCompatibilityPercentageRequired>98.4</binaryCompatibilityPercentageRequired>
<extraOptions>
<extraOption>
<name>skip-internal-packages</name>
Expand Down
105 changes: 60 additions & 45 deletions src/main/java/net/openhft/chronicle/wire/JSONWire.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import net.openhft.chronicle.core.io.IORuntimeException;
import net.openhft.chronicle.core.io.InvalidMarshallableException;
import net.openhft.chronicle.core.pool.ClassLookup;
import net.openhft.chronicle.core.scoped.ScopedResource;
import net.openhft.chronicle.core.threads.ThreadLocalHelper;
import net.openhft.chronicle.core.util.ClassNotFoundRuntimeException;
import net.openhft.chronicle.core.util.UnresolvedType;
Expand Down Expand Up @@ -371,28 +372,30 @@ public void copyOne(@NotNull WireOut wire, boolean inMap, boolean topLevel) thro
* @throws InvalidMarshallableException if there's a problem with copying the data.
*/
private void copyTypePrefix(WireOut wire) throws InvalidMarshallableException {
final StringBuilder sb = acquireStringBuilder();
try (final ScopedResource<StringBuilder> sbR = acquireStringBuilder()) {
final StringBuilder sb = sbR.get();

// Extract the type literal
getValueIn().text(sb);
// Extract the type literal
getValueIn().text(sb);

// Remove the '@' prefix from the type literal
sb.deleteCharAt(0);
wire.getValueOut().typePrefix(sb);
// Remove the '@' prefix from the type literal
sb.deleteCharAt(0);
wire.getValueOut().typePrefix(sb);

// Consume any padding characters (e.g., whitespace)
consumePadding();
int ch = bytes.readUnsignedByte();
if (ch != ':')
throw new IORuntimeException("Expected a ':' after the type " + sb + " but got a " + (char) ch);
// Consume any padding characters (e.g., whitespace)
consumePadding();
int ch = bytes.readUnsignedByte();
if (ch != ':')
throw new IORuntimeException("Expected a ':' after the type " + sb + " but got a " + (char) ch);

// Recursively copy the associated value after the colon
copyOne(wire, true, false);
// Recursively copy the associated value after the colon
copyOne(wire, true, false);

consumePadding();
int ch2 = bytes.readUnsignedByte();
if (ch2 != '}')
throw new IORuntimeException("Expected a '}' after the type " + sb + " but got a " + (char) ch);
consumePadding();
int ch2 = bytes.readUnsignedByte();
if (ch2 != '}')
throw new IORuntimeException("Expected a '}' after the type " + sb + " but got a " + (char) ch);
}
}

/**
Expand All @@ -418,29 +421,31 @@ private boolean isTypePrefix() {
* @throws InvalidMarshallableException if there's a problem with copying the data.
*/
private void copyQuote(WireOut wire, int ch, boolean inMap, boolean topLevel) throws InvalidMarshallableException {
final StringBuilder sb = acquireStringBuilder();
// Extract the quoted text
while (bytes.readRemaining() > 0) {
int ch2 = bytes.readUnsignedByte();
if (ch2 == ch)
break;
sb.append((char) ch2);
try (final ScopedResource<StringBuilder> sbR = acquireStringBuilder()) {
final StringBuilder sb = sbR.get();
// Extract the quoted text
while (bytes.readRemaining() > 0) {
int ch2 = bytes.readUnsignedByte();
if (ch2 == ch)
break;
sb.append((char) ch2);

// If an escape character is found, append the following character as well
if (ch2 == '\\')
sb.append((char) bytes.readUnsignedByte());
}
// If an escape character is found, append the following character as well
if (ch2 == '\\')
sb.append((char) bytes.readUnsignedByte());
}

// Process any escaped characters within the text
unescape(sb);
// Process any escaped characters within the text
unescape(sb);

// Determine how to write the text to the wire based on the provided flags
if (topLevel) {
wire.writeEvent(String.class, sb);
} else if (inMap) {
wire.write(sb);
} else {
wire.getValueOut().text(sb);
// Determine how to write the text to the wire based on the provided flags
if (topLevel) {
wire.writeEvent(String.class, sb);
} else if (inMap) {
wire.write(sb);
} else {
wire.getValueOut().text(sb);
}
}
}

Expand Down Expand Up @@ -1133,18 +1138,23 @@ private Object parseType() throws InvalidMarshallableException {
if (!hasTypeDefinition()) {
return super.object();
} else {
final StringBuilder sb = acquireStringBuilder();
sb.setLength(0);
consume('{');
this.wireIn().read(sb);
final Class<?> clazz = classLookup().forName(sb.subSequence(1, sb.length()));
final Class<?> clazz = readAndLoadClassOther();
Object object = parseType(null, clazz, true);
consume('}');
consumePadding(1);
return object;
}
}

private Class<?> readAndLoadClassOther() {
try (final ScopedResource<StringBuilder> sbR = acquireStringBuilder()) {
final StringBuilder sb = sbR.get();
this.wireIn().read(sb);
return classLookup().forName(sb.subSequence(1, sb.length()));
}
}

private void consume(char c) {
consumePadding();
if (bytes.peekUnsignedByte() == c)
Expand Down Expand Up @@ -1173,10 +1183,7 @@ private <E> E parseType(@Nullable E using, @Nullable Class clazz, boolean bestEf
if (!hasTypeDefinition()) {
return super.object(using, clazz, bestEffort);
} else {
final StringBuilder sb = acquireStringBuilder();
sb.setLength(0);
readTypeDefinition(sb);
final Class<?> overrideClass = classLookup().forName(sb.subSequence(1, sb.length()));
final Class<?> overrideClass = readAndLoadClass();
if (clazz != null && !clazz.isAssignableFrom(overrideClass))
throw new ClassCastException("Unable to cast " + overrideClass.getName() + " to " + clazz.getName());
if (using != null && !overrideClass.isInstance(using))
Expand All @@ -1193,6 +1200,14 @@ private <E> E parseType(@Nullable E using, @Nullable Class clazz, boolean bestEf
}
}

private Class<?> readAndLoadClass() {
try (final ScopedResource<StringBuilder> sbR = acquireStringBuilder()) {
final StringBuilder sb = sbR.get();
readTypeDefinition(sb);
return classLookup().forName(sb.subSequence(1, sb.length()));
}
}

/**
* Checks if the next set of characters in the bytes stream represents a type definition.
* A type definition is expected to start with the pattern {"@ after consuming any padding.
Expand Down
Loading

0 comments on commit b03500f

Please sign in to comment.