public static void writeString(String value, DataOutput out) throws IOException {
InternalDataSerializer.checkOut(out);
final boolean isDebugEnabled = logger.isTraceEnabled(LogMarker.SERIALIZER);
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing String \"{}\"", value);
}
if (value == null) {
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing NULL_STRING");
}
out.writeByte(DSCODE.NULL_STRING);
} else {
// [bruce] writeUTF is expensive - it creates a char[] to fetch
// the string's contents, iterates over the array to compute the
// encoded length, creates a byte[] to hold the encoded bytes,
// iterates over the char[] again to create the encode bytes,
// then writes the bytes. Since we usually deal with ISO-8859-1
// strings, we can accelerate this by accessing chars directly
// with charAt and fill a single-byte buffer. If we run into
// a multibyte char, we revert to using writeUTF()
int len = value.length();
int utfLen = len; // added for bug 40932
for (int i = 0; i < len; i++) {
char c = value.charAt(i);
if ((c <= 0x007F) && (c >= 0x0001)) {
// nothing needed
} else if (c > 0x07FF) {
utfLen += 2;
} else {
utfLen += 1;
}
// Note we no longer have an early out when we detect the first
// non-ascii char because we need to compute the utfLen for bug 40932.
// This is not a performance problem because most strings are ascii
// and they never did the early out.
}
boolean writeUTF = utfLen > len;
if (writeUTF) {
if (utfLen > 0xFFFF) {
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing utf HUGE_STRING of len={}", len);
}
out.writeByte(DSCODE.HUGE_STRING);
out.writeInt(len);
out.writeChars(value);
} else {
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing utf STRING of len={}", len);
}
out.writeByte(DSCODE.STRING);
out.writeUTF(value);
}
} else {
if (len > 0xFFFF) {
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing HUGE_STRING_BYTES of len={}", len);
}
out.writeByte(DSCODE.HUGE_STRING_BYTES);
out.writeInt(len);
out.writeBytes(value);
} else {
if (isDebugEnabled) {
logger.trace(LogMarker.SERIALIZER, "Writing STRING_BYTES of len={}", len);
}
out.writeByte(DSCODE.STRING_BYTES);
out.writeShort(len);
out.writeBytes(value);
}
}
}
} |