Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
855 changes: 855 additions & 0 deletions docs/performance/blaze-xml-optimization-handover.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions modules/fhir-structure/java/blaze/ReducibleArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public ReducibleArray(List<?> list) {
this.items = list.toArray();
}

public Object[] array() {
return items;
}

public Object reduce(IFn f, Object init) {
for (Object item : items) {
init = f.invoke(init, item);
Expand Down
208 changes: 208 additions & 0 deletions modules/fhir-structure/java/blaze/fhir/XmlUtf8Writer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package blaze.fhir;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

public final class XmlUtf8Writer extends Writer {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is a bit to low-level.


private final OutputStream out;
private final byte[] buffer;
private int pos;

public XmlUtf8Writer(OutputStream out, int bufferSize) {
this.out = out;
this.buffer = new byte[bufferSize];
}

private void ensureOpen() throws IOException {
if (out == null) {
throw new IOException("Stream closed");
}
}

private void ensureCapacity(int n) throws IOException {
if (buffer.length - pos < n) {
flushBuffer();
}
}

private void flushBuffer() throws IOException {
if (pos > 0) {
out.write(buffer, 0, pos);
pos = 0;
}
}

private void writeByte(int b) throws IOException {
ensureCapacity(1);
buffer[pos++] = (byte) b;
}

private void writeCodePoint(int codePoint) throws IOException {
if (codePoint < 0x80) {
writeByte(codePoint);
} else if (codePoint < 0x800) {
ensureCapacity(2);
buffer[pos++] = (byte) (0xC0 | (codePoint >> 6));
buffer[pos++] = (byte) (0x80 | (codePoint & 0x3F));
} else if (codePoint < 0x10000) {
ensureCapacity(3);
buffer[pos++] = (byte) (0xE0 | (codePoint >> 12));
buffer[pos++] = (byte) (0x80 | ((codePoint >> 6) & 0x3F));
buffer[pos++] = (byte) (0x80 | (codePoint & 0x3F));
} else {
ensureCapacity(4);
buffer[pos++] = (byte) (0xF0 | (codePoint >> 18));
buffer[pos++] = (byte) (0x80 | ((codePoint >> 12) & 0x3F));
buffer[pos++] = (byte) (0x80 | ((codePoint >> 6) & 0x3F));
buffer[pos++] = (byte) (0x80 | (codePoint & 0x3F));
}
}

private void writeAscii(String str, int off, int end) throws IOException {
while (off < end) {
ensureCapacity(1);
int n = Math.min(buffer.length - pos, end - off);
for (int i = 0; i < n; i++) {
buffer[pos + i] = (byte) str.charAt(off + i);
}
pos += n;
off += n;
}
}

private void writeAscii(char[] cbuf, int off, int end) throws IOException {
while (off < end) {
ensureCapacity(1);
int n = Math.min(buffer.length - pos, end - off);
for (int i = 0; i < n; i++) {
buffer[pos + i] = (byte) cbuf[off + i];
}
pos += n;
off += n;
}
}

private static boolean validXmlChar(char c) {
return c == 0x09 || c == 0x0A || c == 0x0D ||
(0x20 <= c && c <= 0xD7FF) ||
(0xE000 <= c && c <= 0xFFFD);
}

public void writeEscaped(String str) throws IOException {
ensureOpen();
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (c < 0x80) {
if (c >= 0x20) {
switch (c) {
case '&' -> writeAscii("&amp;", 0, 5);
case '<' -> writeAscii("&lt;", 0, 4);
case '>' -> writeAscii("&gt;", 0, 4);
case '"' -> writeAscii("&quot;", 0, 6);
default -> {
if (pos == buffer.length) {
flushBuffer();
}
buffer[pos++] = (byte) c;
}
}
} else if (c == 0x09 || c == 0x0A || c == 0x0D) {
if (pos == buffer.length) {
flushBuffer();
}
buffer[pos++] = (byte) c;
} else {
writeByte('?');
}
} else if (Character.isHighSurrogate(c)) {
int j = i + 1;
if (j < len && Character.isLowSurrogate(str.charAt(j))) {
writeCodePoint(Character.toCodePoint(c, str.charAt(j)));
i = j;
} else {
writeByte('?');
}
} else if (Character.isLowSurrogate(c) || !validXmlChar(c)) {
writeByte('?');
} else {
writeCodePoint(c);
}
}
}

@Override
public void write(int c) throws IOException {
ensureOpen();
writeCodePoint(Character.isSurrogate((char) c) ? '?' : c);
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
ensureOpen();
int end = off + len;
for (int i = off; i < end; i++) {
char c = cbuf[i];
if (c < 0x80) {
if (pos == buffer.length) {
flushBuffer();
}
buffer[pos++] = (byte) c;
} else if (Character.isHighSurrogate(c)) {
int j = i + 1;
if (j < end && Character.isLowSurrogate(cbuf[j])) {
writeCodePoint(Character.toCodePoint(c, cbuf[j]));
i = j;
} else {
writeByte('?');
}
} else if (Character.isLowSurrogate(c)) {
writeByte('?');
} else {
writeCodePoint(c);
}
}
}

@Override
public void write(String str, int off, int len) throws IOException {
ensureOpen();
int end = off + len;
for (int i = off; i < end; i++) {
char c = str.charAt(i);
if (c < 0x80) {
if (pos == buffer.length) {
flushBuffer();
}
buffer[pos++] = (byte) c;
} else if (Character.isHighSurrogate(c)) {
int j = i + 1;
if (j < end && Character.isLowSurrogate(str.charAt(j))) {
writeCodePoint(Character.toCodePoint(c, str.charAt(j)));
i = j;
} else {
writeByte('?');
}
} else if (Character.isLowSurrogate(c)) {
writeByte('?');
} else {
writeCodePoint(c);
}
}
}

@Override
public void flush() throws IOException {
ensureOpen();
flushBuffer();
out.flush();
}

@Override
public void close() throws IOException {
flush();
out.close();
}
}
67 changes: 67 additions & 0 deletions modules/fhir-structure/java/blaze/fhir/XmlUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package blaze.fhir;

import java.io.IOException;
import java.io.Writer;

public final class XmlUtil {

private XmlUtil() {
}

private static boolean validXmlChar(char c) {
return c == 0x09 || c == 0x0A || c == 0x0D ||
(0x20 <= c && c <= 0xD7FF) ||
(0xE000 <= c && c <= 0xFFFD);
}

public static void writeEscaped(Writer writer, String s) throws IOException {
if (writer instanceof XmlUtf8Writer xmlWriter) {
xmlWriter.writeEscaped(s);
return;
}
int len = s.length();
int start = 0;
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
switch (c) {
case '&' -> {
if (start < i) writer.write(s, start, i - start);
writer.write("&amp;");
start = i + 1;
}
case '<' -> {
if (start < i) writer.write(s, start, i - start);
writer.write("&lt;");
start = i + 1;
}
case '>' -> {
if (start < i) writer.write(s, start, i - start);
writer.write("&gt;");
start = i + 1;
}
case '"' -> {
if (start < i) writer.write(s, start, i - start);
writer.write("&quot;");
start = i + 1;
}
default -> {
if (Character.isHighSurrogate(c)) {
int j = i + 1;
if (j < len && Character.isLowSurrogate(s.charAt(j))) {
i = j;
} else {
if (start < i) writer.write(s, start, i - start);
writer.write("?");
start = j;
}
} else if (Character.isLowSurrogate(c) || !validXmlChar(c)) {
if (start < i) writer.write(s, start, i - start);
writer.write("?");
start = i + 1;
}
}
}
}
if (start < len) writer.write(s, start, len - start);
}
}
Loading