Implement writeUTF

This commit is contained in:
Andrea Cavalli 2023-03-02 18:23:03 +01:00
parent 011c8f839c
commit ea1b464ddf
2 changed files with 39 additions and 6 deletions

View File

@ -1,5 +1,8 @@
package it.cavallium.dbengine.buffers; package it.cavallium.dbengine.buffers;
import static org.warp.commonutils.stream.SafeDataOutputStream.strLen;
import static org.warp.commonutils.stream.SafeDataOutputStream.utfLen;
import it.unimi.dsi.fastutil.Arrays; import it.unimi.dsi.fastutil.Arrays;
import java.io.DataOutput; import java.io.DataOutput;
import java.io.IOException; import java.io.IOException;
@ -178,9 +181,23 @@ public class BufDataOutput implements DataOutput {
dOut.writeChars(s); dOut.writeChars(s);
} }
private static String tooLongMsg(String s, int bits32) {
int slen = s.length();
String head = s.substring(0, 8);
String tail = s.substring(slen - 8, slen);
// handle int overflow with max 3x expansion
long actualLength = (long)slen + Integer.toUnsignedLong(bits32 - slen);
return "encoded string (" + head + "..." + tail + ") too long: "
+ actualLength + " bytes";
}
@Override @Override
public void writeUTF(@NotNull String s) { public void writeUTF(@NotNull String str) {
throw new UnsupportedOperationException(); var strlen = strLen(str);
var utflen = utfLen(str, strlen);
var bytes = Short.BYTES + utflen;
checkOutOfBounds(bytes);
dOut.writeUTF(strlen, utflen, str);
} }
public Buf asList() { public Buf asList() {

View File

@ -310,6 +310,10 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
writeUTF(str, this); writeUTF(str, this);
} }
public final void writeUTF(int strlen, int utflen, String str) {
writeUTF(strlen, utflen, str, this);
}
/** /**
* Writes a string to the specified DataOutput using * Writes a string to the specified DataOutput using
* <a href="DataInput.html#modified-utf-8">modified UTF-8</a> * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
@ -330,18 +334,30 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* @return The number of bytes written out. * @return The number of bytes written out.
*/ */
static int writeUTF(String str, SafeDataOutput out) { static int writeUTF(String str, SafeDataOutput out) {
final int strlen = str.length(); int strlen = strLen(str);
int utflen = strlen; // optimized for ASCII int utflen = utfLen(str, strlen);
return writeUTF(strlen, utflen, str, out);
}
for (int i = 0; i < strlen; i++) { public static int strLen(String str) {
return str.length();
}
public static int utfLen(String str, int strLen) {
int utflen = strLen; // optimized for ASCII
for (int i = 0; i < strLen; i++) {
int c = str.charAt(i); int c = str.charAt(i);
if (c >= 0x80 || c == 0) if (c >= 0x80 || c == 0)
utflen += (c >= 0x800) ? 2 : 1; utflen += (c >= 0x800) ? 2 : 1;
} }
if (utflen > 65535 || /* overflow */ utflen < strlen) if (utflen > 65535 || /* overflow */ utflen < strLen)
throw new IllegalArgumentException(tooLongMsg(str, utflen)); throw new IllegalArgumentException(tooLongMsg(str, utflen));
return utflen;
}
static int writeUTF(int strlen, int utflen, String str, SafeDataOutput out) {
final byte[] bytearr; final byte[] bytearr;
if (out instanceof SafeDataOutputStream) { if (out instanceof SafeDataOutputStream) {
SafeDataOutputStream dos = (SafeDataOutputStream)out; SafeDataOutputStream dos = (SafeDataOutputStream)out;