mirror of
https://github.com/microsoft/HybridRow.git
synced 2026-01-21 10:23:13 +00:00
Code cleanup, especially in Utf8String class which is much improved.
This commit is contained in:
@@ -23,7 +23,7 @@ public final class Reference<T> {
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void set(T value) {
|
||||
@@ -41,7 +41,7 @@ public final class Reference<T> {
|
||||
* @return {@code true} if there is a value present, otherwise {@code false}
|
||||
*/
|
||||
public boolean isPresent() {
|
||||
return value != null;
|
||||
return this.value != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,12 +66,12 @@ public final class Reference<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(value, ((Reference)other).value);
|
||||
return Objects.equals(this.value, ((Reference)other).value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value == null ? "null" : value.toString();
|
||||
return this.value == null ? "null" : this.value.toString();
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,13 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeType;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.base.Utf8;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufHolder;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.ByteProcessor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -27,6 +30,7 @@ import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@@ -40,32 +44,49 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public final class Utf8String implements ByteBufHolder, CharSequence, Comparable<Utf8String> {
|
||||
|
||||
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER, 0);
|
||||
public static final Utf8String NULL = new Utf8String();
|
||||
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER);
|
||||
public static final Utf8String NULL = new Utf8String(null);
|
||||
|
||||
private final ByteBuf buffer;
|
||||
private final int length;
|
||||
private final Supplier<Integer> codePointCount;
|
||||
private final Supplier<Integer> utf16CodeUnitCount;
|
||||
|
||||
private Utf8String() {
|
||||
this.buffer = null;
|
||||
this.length = -1;
|
||||
}
|
||||
private Utf8String(@Nullable final ByteBuf buffer) {
|
||||
|
||||
private Utf8String(@Nonnull final ByteBuf buffer) {
|
||||
this(buffer, decodedLength(buffer));
|
||||
}
|
||||
if (buffer == null) {
|
||||
this.buffer = null;
|
||||
this.codePointCount = Suppliers.memoize(() -> -1);
|
||||
this.utf16CodeUnitCount = Suppliers.memoize(() -> -1);
|
||||
return;
|
||||
}
|
||||
|
||||
private Utf8String(@Nonnull final ByteBuf buffer, final int decodedLength) {
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
this.buffer = buffer.asReadOnly();
|
||||
this.length = decodedLength;
|
||||
if (buffer.writerIndex() == 0) {
|
||||
this.buffer = Unpooled.EMPTY_BUFFER;
|
||||
this.codePointCount = Suppliers.memoize(() -> 0);
|
||||
this.utf16CodeUnitCount = Suppliers.memoize(() -> 0);
|
||||
return;
|
||||
}
|
||||
|
||||
this.buffer = buffer;
|
||||
|
||||
this.codePointCount = Suppliers.memoize(() -> {
|
||||
final UTF8CodePointCounter counter = new UTF8CodePointCounter();
|
||||
this.buffer.forEachByte(0, this.buffer.writerIndex(), counter);
|
||||
return counter.value();
|
||||
});
|
||||
|
||||
this.utf16CodeUnitCount = Suppliers.memoize(() -> {
|
||||
final UTF16CodeUnitCounter counter = new UTF16CodeUnitCounter();
|
||||
this.buffer.forEachByte(0, this.buffer.writerIndex(), counter);
|
||||
return counter.value();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if the length of this instance is zero
|
||||
*/
|
||||
public final boolean isEmpty() {
|
||||
return this.length == 0;
|
||||
return this.buffer != null && this.buffer.writerIndex() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,10 +113,10 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
* Non-allocating enumeration of each code point in the UTF-8 stream
|
||||
*/
|
||||
public final IntStream codePoints() {
|
||||
if (this.length == 0) {
|
||||
if (this.buffer == null || this.buffer.writerIndex() == 0) {
|
||||
return IntStream.empty();
|
||||
}
|
||||
return StreamSupport.intStream(new CodePointIterable(this.buffer, this.length), false);
|
||||
return StreamSupport.intStream(new CodePointIterable(this.buffer, this.codePointCount.get()), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +151,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
|
||||
if (limit > 0) {
|
||||
|
||||
final CodePointIterable iterable = new CodePointIterable(this.buffer, this.length);
|
||||
final CodePointIterable iterable = new CodePointIterable(this.buffer, this.utf16CodeUnitCount.get());
|
||||
int index = 0;
|
||||
|
||||
for (int codePoint : iterable) {
|
||||
@@ -182,16 +203,16 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
/**
|
||||
* Encoded length of this {@link Utf8String}
|
||||
* <p>
|
||||
* This is the same value as would be returned by {@link String#getBytes()#length} with no time or space overhead.
|
||||
* This is the same value as would be returned by {@link String#getBytes()#utf16CodeUnitCount} with no time or space overhead.
|
||||
*
|
||||
* @return encoded length of {@link Utf8String}
|
||||
*/
|
||||
public final int encodedLength() {
|
||||
return this.buffer.writerIndex();
|
||||
return this.buffer == null ? 0 : this.buffer.writerIndex();
|
||||
}
|
||||
|
||||
public final boolean equals(ByteBuf other) {
|
||||
return this.buffer.equals(other);
|
||||
return Objects.equal(this.buffer, other);
|
||||
}
|
||||
|
||||
public final boolean equals(String other) {
|
||||
@@ -202,33 +223,25 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
public final boolean equals(Utf8String other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (other == this) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return this.buffer.equals(other.buffer);
|
||||
if (null == other) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equal(this.buffer, other.buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (other == this) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other instanceof ByteBuf) {
|
||||
return this.equals((ByteBuf)other);
|
||||
if (null == other || this.getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (other instanceof String) {
|
||||
return this.equals((String)other);
|
||||
}
|
||||
if (other instanceof Utf8String) {
|
||||
return this.equals((Utf8String)other);
|
||||
}
|
||||
return false;
|
||||
Utf8String that = (Utf8String) other;
|
||||
return this.utf16CodeUnitCount == that.utf16CodeUnitCount && Objects.equal(this.buffer, that.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,11 +260,12 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation
|
||||
* Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation.
|
||||
* <p>
|
||||
* The {@link Utf8String} created retains the {@link ByteBuf}. (No data is transferred.)
|
||||
* The {@link Utf8String} created retains the {@link ByteBuf} and ensures it is read-only by calling
|
||||
* {@link ByteBuf#asReadOnly}. No data is transferred.
|
||||
*
|
||||
* @param buffer The {@link ByteBuf} to assign to the {@link Utf8String} created.
|
||||
* @param buffer a {@link ByteBuf} to assign to the {@link Utf8String} created.
|
||||
* @return a new {@link Utf8String}
|
||||
*/
|
||||
@Nonnull
|
||||
@@ -266,12 +280,13 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of this character sequence
|
||||
* Returns the length of this character sequence.
|
||||
* <p>
|
||||
* The length is the number of Unicode characters in the sequence.
|
||||
* The length is the number of UTF-16 code units in the sequence. This is the same value as would be returned by
|
||||
* {@link Utf8String#toUtf16()#length()} with no time or space overhead.
|
||||
*/
|
||||
public final int length() {
|
||||
return this.length;
|
||||
return this.utf16CodeUnitCount.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,10 +300,11 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at
|
||||
* {@code 0}.
|
||||
* Decreases the reference count by {@code 1}.
|
||||
*
|
||||
* @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated
|
||||
* The underlying storage for this instance is deallocated, if the reference count reaches {@code 0}.
|
||||
*
|
||||
* @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated.
|
||||
*/
|
||||
@Override
|
||||
public boolean release() {
|
||||
@@ -296,11 +312,12 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference
|
||||
* count reaches at {@code 0}.
|
||||
* Decreases the reference count by the specified {@code decrement}
|
||||
*
|
||||
* @param decrement
|
||||
* @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated
|
||||
* The underlying storage for this instance is deallocated, if the reference count reaches {@code 0}.
|
||||
*
|
||||
* @param decrement the value to subtract from the reference count.
|
||||
* @return {@code true} if and only if the reference count became {@code 0}.
|
||||
*/
|
||||
@Override
|
||||
public boolean release(int decrement) {
|
||||
@@ -308,7 +325,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link Utf8String} which contains the specified {@code content}
|
||||
* Returns a new {@link Utf8String} which contains the specified {@code content}.
|
||||
*
|
||||
* @param content text of the {@link Utf8String} to be created.
|
||||
*/
|
||||
@@ -330,7 +347,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates this {@link Utf8String}
|
||||
* Duplicates this {@link Utf8String}.
|
||||
* <p>
|
||||
* This method returns a retained duplicate unlike {@link #duplicate()}.
|
||||
*
|
||||
@@ -343,9 +360,8 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
checkArgument(start < 0 || end < 0 || start > end || end > this.length, "start: %s, end: %s", start, end);
|
||||
// TODO: DANOBLE: compute buffer index for start and end character positions and use them in the slice
|
||||
return new Utf8String(this.buffer.slice(), end - start);
|
||||
checkArgument(start < 0 || end < 0 || start > end || end > this.length(), "start: %s, end: %s", start, end);
|
||||
return new Utf8String(this.buffer.slice(start, end));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,43 +410,34 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
|
||||
checkState(count == length, "count: %s, length: %s", count, length);
|
||||
|
||||
return new Utf8String(buffer, string.length());
|
||||
return new Utf8String(buffer);
|
||||
}
|
||||
|
||||
private static int decodedLength(final ByteBuf buffer) {
|
||||
|
||||
final CodePointIterable iterable = new CodePointIterable(buffer, -1);
|
||||
int decodedLength = 0;
|
||||
|
||||
for (int ignored : iterable) {
|
||||
decodedLength++;
|
||||
}
|
||||
|
||||
return decodedLength;
|
||||
}
|
||||
|
||||
private static final class CodePointIterable implements Iterable<Integer>, Iterator<Integer>, Spliterator.OfInt {
|
||||
private static final class CodePointIterable extends UTF8CodePointGetter implements
|
||||
Iterable<Integer>, Iterator<Integer>, Spliterator.OfInt {
|
||||
|
||||
private static final int CHARACTERISTICS = Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED;
|
||||
|
||||
private final ByteBuf buffer;
|
||||
private final int length;
|
||||
private int index;
|
||||
private final int codePointCount;
|
||||
|
||||
CodePointIterable(final ByteBuf buffer, final int length) {
|
||||
private int start, length;
|
||||
|
||||
CodePointIterable(final ByteBuf buffer, final int codePointCount) {
|
||||
this.codePointCount = codePointCount;
|
||||
this.buffer = buffer;
|
||||
this.length = length;
|
||||
this.index = 0;
|
||||
this.start = 0;
|
||||
this.length = buffer.writerIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return this.length == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
return this.codePointCount == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return this.length < 0 ? Long.MAX_VALUE : this.length;
|
||||
return this.codePointCount < 0 ? Long.MAX_VALUE : this.codePointCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -440,7 +447,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.index < this.buffer.capacity();
|
||||
return this.length > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -456,50 +463,10 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
final int leadingByte = this.buffer.getByte(this.index++) & 0xFF;
|
||||
this.start = this.buffer.forEachByte(this.start, this.length, this);
|
||||
this.length -= this.start;
|
||||
|
||||
// A 1-byte UTF-8 code point is a special case that covers the 7-bit ASCII character set
|
||||
|
||||
if (leadingByte < 0x80) {
|
||||
return leadingByte;
|
||||
}
|
||||
|
||||
// The initial byte of 2-, 3- and 4-byte UTF-8 code points start with 2, 3, or 4 one bits followed by a 0
|
||||
// bit
|
||||
|
||||
final int codePoint;
|
||||
|
||||
if ((leadingByte & 0b1110_0000) == 0b1100_0000) {
|
||||
|
||||
// 110xxxxx 10xxxxxx => 0x00000080 - 0x000007FF
|
||||
|
||||
codePoint = ((leadingByte & 0b0001_1111) << 6) |
|
||||
(this.buffer.getByte(this.index++) & 0b0011_1111);
|
||||
|
||||
} else if ((leadingByte & 0b1111_0000) == 0b1110_0000) {
|
||||
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx => 0x00000800 - 0x0000FFFF
|
||||
|
||||
codePoint = ((leadingByte & 0b0000_1111) << 12) |
|
||||
((this.buffer.getByte(this.index++) & 0b0011_1111) << 6) |
|
||||
((this.buffer.getByte(this.index++) & 0b0011_1111));
|
||||
|
||||
} else if ((leadingByte & 0b1111_1000) == 0b1111_0000) {
|
||||
|
||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx => 0x00010000 - 0x001FFFFF
|
||||
|
||||
codePoint = ((leadingByte & 0b0000_0111) << 18) |
|
||||
((this.buffer.getByte(this.index++) & 0b0011_1111) << 12) |
|
||||
((this.buffer.getByte(this.index++) & 0b0011_1111) << 6) |
|
||||
((this.buffer.getByte(this.index++) & 0b0011_1111));
|
||||
|
||||
} else {
|
||||
// leading byte is improperly encoded and we'll detect that before returning
|
||||
codePoint = leadingByte;
|
||||
}
|
||||
|
||||
checkState(Character.isDefined(codePoint), "invalid character: %s", codePoint);
|
||||
return codePoint;
|
||||
return this.codePoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -563,4 +530,204 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
||||
generator.writeString(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ByteProcessor} used by to count the number of UTF-16 code units in a UTF-8 encoded string.
|
||||
*
|
||||
* This class makes use of the fact that code points that UTF-16 encodes with two 16-bit code units, UTF-8 encodes
|
||||
* with 4 8-bit code units, and vice versa. Lead bytes are identified and counted. All other bytes are skipped.
|
||||
* Code points are not validated. The {@link #process} method counts undefined leading bytes as an undefined UTF-16
|
||||
* code unit to be replaced.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
|
||||
*/
|
||||
private static final class UTF16CodeUnitCounter implements ByteProcessor {
|
||||
|
||||
private int count = 0;
|
||||
private int skip = 0;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) throws Exception {
|
||||
|
||||
if (this.skip > 0) {
|
||||
this.skip--;
|
||||
} else {
|
||||
final int leadingByte = value & 0xFF;
|
||||
if (leadingByte < 0x7F) {
|
||||
// UTF-8-1 = 0x00-7F
|
||||
this.skip = 0;
|
||||
this.count++;
|
||||
} else if (0xC2 <= leadingByte && leadingByte <= 0xDF) {
|
||||
// UTF8-8-2 = 0xC2-DF UTF8-tail
|
||||
this.skip = 1;
|
||||
this.count++;
|
||||
} else if (0xE0 <= leadingByte && leadingByte <= 0xEF) {
|
||||
// UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail)
|
||||
this.skip = 2;
|
||||
this.count++;
|
||||
} else if (0xF0 <= leadingByte && leadingByte <= 0xF4) {
|
||||
// UTF8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail )
|
||||
this.skip = 3;
|
||||
this.count += 2;
|
||||
} else {
|
||||
this.skip = 0;
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ByteProcessor} used by to count the number of Unicode code points in a UTF-8 encoded string.
|
||||
*
|
||||
* Lead bytes are identified and counted. All other bytes are skipped. Code points are not validated. The
|
||||
* {@link #process} method counts undefined lead bytes as a single code point to be replaced.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
|
||||
*/
|
||||
private static final class UTF8CodePointCounter implements ByteProcessor {
|
||||
|
||||
private int count = 0;
|
||||
private int skip = 0;
|
||||
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
|
||||
if (this.skip > 0) {
|
||||
this.skip--;
|
||||
} else {
|
||||
final int leadingByte = value & 0xFF;
|
||||
if (leadingByte < 0x7F) {
|
||||
// UTF-8-1 = 0x00-7F
|
||||
this.skip = 0;
|
||||
} else if (0xC2 <= leadingByte && leadingByte <= 0xDF) {
|
||||
// UTF8-8-2 = 0xC2-DF UTF8-tail
|
||||
this.skip = 1;
|
||||
} else if (0xE0 <= leadingByte && leadingByte <= 0xEF) {
|
||||
// UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail)
|
||||
this.skip = 2;
|
||||
} else if (0xF0 <= leadingByte && leadingByte <= 0xF4) {
|
||||
// UTF8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail )
|
||||
this.skip = 3;
|
||||
} else {
|
||||
// Undefined leading byte
|
||||
this.skip = 0;
|
||||
}
|
||||
this.count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ByteProcessor} used to read a UTF-8 encoded string one Unicode code point at a time.
|
||||
* <p>
|
||||
* This {@link #process(byte)} method reads a single code point at a time. The first byte read following
|
||||
* construction of an instance of this class must be a leading byte. This is used to determine the number of
|
||||
* single-byte UTF-8 code units in the code point.
|
||||
* <p>
|
||||
* Code points are validated. The {@link #process(byte)} method returns the Unicode
|
||||
* <a href="https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character">Replacement character</a>
|
||||
* when an undefined code point is encountered.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
|
||||
*/
|
||||
private static class UTF8CodePointGetter implements ByteProcessor {
|
||||
|
||||
private static final int REPLACEMENT_CHARACTER = 0xFFFD;
|
||||
|
||||
private int codePoint = 0;
|
||||
private int shift = -1;
|
||||
|
||||
/**
|
||||
* Gets the next code unit in a UTF-8 code point sequence.
|
||||
*
|
||||
* @param value the next code unit in a UTF-8
|
||||
*
|
||||
* @return {@code true} if additional code units must be read to complete the code point; otherwise, if the
|
||||
* code point is complete, a value of {@code false} is returned.
|
||||
*/
|
||||
@Override
|
||||
public boolean process(byte value) {
|
||||
|
||||
switch (this.shift) {
|
||||
|
||||
default: {
|
||||
|
||||
// Next unit of code point sequence
|
||||
|
||||
this.codePoint |= (value & 0xFF << this.shift);
|
||||
this.shift -= Byte.SIZE;
|
||||
return true;
|
||||
}
|
||||
case 0: {
|
||||
|
||||
// End of code point sequence
|
||||
|
||||
this.codePoint |= value & 0xFF;
|
||||
this.shift = -1;
|
||||
|
||||
if (!Character.isDefined(this.codePoint)) {
|
||||
this.codePoint = REPLACEMENT_CHARACTER;
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
case -1: {
|
||||
|
||||
// Start of code point sequence
|
||||
|
||||
final int leadingByte = value & 0xFF;
|
||||
|
||||
if (leadingByte < 0x7F) {
|
||||
// UTF-8-1 = 0x00-7F
|
||||
this.codePoint = leadingByte;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0xC2 <= leadingByte && leadingByte <= 0xDF) {
|
||||
// UTF8-8-2 = 0xC2-DF UTF8-tail
|
||||
this.codePoint = leadingByte << Byte.SIZE;
|
||||
this.shift = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (0xE0 <= leadingByte && leadingByte <= 0xEF) {
|
||||
// UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail)
|
||||
this.codePoint = leadingByte << 2 * Byte.SIZE;
|
||||
this.shift = Byte.SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (0xF0 <= leadingByte && leadingByte <= 0xF4) {
|
||||
// UTF8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail )
|
||||
this.codePoint = leadingByte << 3 * Byte.SIZE;
|
||||
this.shift = 3 * Byte.SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
this.codePoint = REPLACEMENT_CHARACTER;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the most-recently read code point.
|
||||
*
|
||||
* @return value of the most-recently read code point.
|
||||
*/
|
||||
int codePoint() {
|
||||
return this.codePoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,274 +17,278 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
*/
|
||||
public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString> {
|
||||
|
||||
private static final UtfAnyString EMPTY = new UtfAnyString("");
|
||||
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
|
||||
public static final UtfAnyString EMPTY = new UtfAnyString("");
|
||||
public static final UtfAnyString NULL = new UtfAnyString();
|
||||
|
||||
private CharSequence buffer;
|
||||
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
|
||||
|
||||
public UtfAnyString(final String string) {
|
||||
this.buffer = string;
|
||||
}
|
||||
private CharSequence buffer;
|
||||
|
||||
public UtfAnyString(final Utf8String utf8String) {
|
||||
this.buffer = utf8String;
|
||||
}
|
||||
public UtfAnyString(final String value) {
|
||||
this.buffer = value;
|
||||
}
|
||||
|
||||
private UtfAnyString(final CharSequence sequence) {
|
||||
this.buffer = sequence;
|
||||
}
|
||||
public UtfAnyString(final Utf8String value) {
|
||||
this.buffer = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if the {@link UtfAnyString} is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.buffer != null && this.buffer.length() == 0;
|
||||
}
|
||||
private UtfAnyString() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code true} if the {@link UtfAnyString} is {@code null}
|
||||
*/
|
||||
public boolean isNull() {
|
||||
return null == this.buffer;
|
||||
}
|
||||
private UtfAnyString(final CharSequence sequence) {
|
||||
this.buffer = sequence;
|
||||
}
|
||||
|
||||
public boolean isUtf16() {
|
||||
return this.buffer instanceof String;
|
||||
}
|
||||
/**
|
||||
* {@code true} if the {@link UtfAnyString} is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.buffer != null && this.buffer.length() == 0;
|
||||
}
|
||||
|
||||
public boolean isUtf8() {
|
||||
return this.buffer instanceof Utf8String;
|
||||
}
|
||||
/**
|
||||
* {@code true} if the {@link UtfAnyString} is {@code null}
|
||||
*/
|
||||
public boolean isNull() {
|
||||
return null == this.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code char} value at the specified {@code index}
|
||||
* <p>
|
||||
* An index ranges from zero to {@link UtfAnyString#length()} minus one. The first {@code char} value of the
|
||||
* sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char}
|
||||
* value specified by the {@code index} is a surrogate, the surrogate (not the surrogate pair) is returned.
|
||||
*
|
||||
* @param index the index of the {@code char} value to be returned
|
||||
* @return the specified {@code char} value
|
||||
* @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
|
||||
* {@link UtfAnyString#length()}
|
||||
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
|
||||
*/
|
||||
@Override
|
||||
public char charAt(final int index) {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.charAt(index);
|
||||
}
|
||||
public boolean isUtf16() {
|
||||
return this.buffer instanceof String;
|
||||
}
|
||||
|
||||
public int compareTo(@Nonnull final String other) {
|
||||
public boolean isUtf8() {
|
||||
return this.buffer instanceof Utf8String;
|
||||
}
|
||||
|
||||
checkNotNull(other);
|
||||
/**
|
||||
* Returns the {@code char} value at the specified {@code index}
|
||||
* <p>
|
||||
* An index ranges from zero to {@link UtfAnyString#length()} minus one. The first {@code char} value of the
|
||||
* sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char}
|
||||
* value specified by the {@code index} is a surrogate, the surrogate (not the surrogate pair) is returned.
|
||||
*
|
||||
* @param index the index of the {@code char} value to be returned.
|
||||
* @return the specified {@code char} value
|
||||
* @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
|
||||
* {@link UtfAnyString#length()}
|
||||
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}.
|
||||
*/
|
||||
@Override
|
||||
public char charAt(final int index) {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.charAt(index);
|
||||
}
|
||||
|
||||
if (other == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
public int compareTo(@Nonnull final String other) {
|
||||
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
checkNotNull(other, "expected non-null other");
|
||||
|
||||
return this.buffer instanceof String
|
||||
? ((String) this.buffer).compareTo(other)
|
||||
: ((Utf8String) this.buffer).compareTo(other);
|
||||
}
|
||||
if (other == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int compareTo(@Nonnull final Utf8String other) {
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
checkNotNull(other);
|
||||
return this.buffer instanceof String
|
||||
? ((String) this.buffer).compareTo(other)
|
||||
: ((Utf8String) this.buffer).compareTo(other);
|
||||
}
|
||||
|
||||
if (other == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
public int compareTo(@Nonnull final Utf8String other) {
|
||||
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
checkNotNull(other, "expected non-null other");
|
||||
|
||||
return this.buffer instanceof String
|
||||
? -other.compareTo((String) this.buffer)
|
||||
: ((Utf8String) this.buffer).compareTo(other);
|
||||
}
|
||||
if (other == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@Nonnull final UtfAnyString other) {
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
checkNotNull(other);
|
||||
return this.buffer instanceof String
|
||||
? -other.compareTo((String) this.buffer)
|
||||
: ((Utf8String) this.buffer).compareTo(other);
|
||||
}
|
||||
|
||||
if (other.buffer == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int compareTo(@Nonnull final UtfAnyString other) {
|
||||
|
||||
if (other.buffer == null) {
|
||||
return 1;
|
||||
}
|
||||
checkNotNull(other, "expected non-null other");
|
||||
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
if (other.buffer == this.buffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.buffer instanceof String) {
|
||||
return other.buffer instanceof String
|
||||
? ((String) this.buffer).compareTo((String) other.buffer)
|
||||
: -((Utf8String) other.buffer).compareTo((String) this.buffer);
|
||||
}
|
||||
if (other.buffer == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
|
||||
}
|
||||
if (this.buffer == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static UtfAnyString empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
if (this.buffer instanceof String) {
|
||||
return other.buffer instanceof String
|
||||
? ((String) this.buffer).compareTo((String) other.buffer)
|
||||
: -((Utf8String) other.buffer).compareTo((String) this.buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
|
||||
}
|
||||
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
public static UtfAnyString empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
if (other instanceof String) {
|
||||
return this.equals((String) other);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
|
||||
if (other instanceof Utf8String) {
|
||||
return this.equals((Utf8String) other);
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other instanceof UtfAnyString) {
|
||||
return this.equals((UtfAnyString) other);
|
||||
}
|
||||
if (other instanceof String) {
|
||||
return this.equals((String) other);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if (other instanceof Utf8String) {
|
||||
return this.equals((Utf8String) other);
|
||||
}
|
||||
|
||||
public boolean equals(final String other) {
|
||||
if (other instanceof UtfAnyString) {
|
||||
return this.equals((UtfAnyString) other);
|
||||
}
|
||||
|
||||
if (null == this.buffer) {
|
||||
return null == other;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.buffer instanceof String) {
|
||||
return other.contentEquals(this.buffer); // skips the type check that String.equals performs
|
||||
}
|
||||
public boolean equals(final String other) {
|
||||
|
||||
return ((Utf8String) this.buffer).equals(other);
|
||||
}
|
||||
if (null == this.buffer) {
|
||||
return null == other;
|
||||
}
|
||||
|
||||
public boolean equals(final Utf8String other) {
|
||||
if (this.buffer instanceof String) {
|
||||
return other.contentEquals(this.buffer); // skips the type check that String.equals performs
|
||||
}
|
||||
|
||||
if (null == other) {
|
||||
return null == this.buffer;
|
||||
}
|
||||
return ((Utf8String) this.buffer).equals(other);
|
||||
}
|
||||
|
||||
return other.equals(this.buffer);
|
||||
}
|
||||
public boolean equals(final Utf8String other) {
|
||||
|
||||
public boolean equals(final UtfAnyString other) {
|
||||
if (null == other) {
|
||||
return null == this.buffer;
|
||||
}
|
||||
|
||||
if (null == other) {
|
||||
return false;
|
||||
}
|
||||
return other.equals(this.buffer);
|
||||
}
|
||||
|
||||
if (null == this.buffer) {
|
||||
return null == other.buffer;
|
||||
}
|
||||
public boolean equals(final UtfAnyString other) {
|
||||
|
||||
return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
|
||||
}
|
||||
if (null == other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (null == this.buffer) {
|
||||
return null == other.buffer;
|
||||
}
|
||||
|
||||
final long[] hash = { 5_381, 5_381 };
|
||||
return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
|
||||
}
|
||||
|
||||
if (this.buffer == null) {
|
||||
return NULL_HASHCODE;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
if (this.buffer instanceof String) {
|
||||
final long[] hash = { 5_381, 5_381 };
|
||||
|
||||
final int ignored = ((String) this.buffer).codePoints().reduce(0, (index, codePoint) -> {
|
||||
if (index % 2 == 0) {
|
||||
hash[0] = ((hash[0] << 5) + hash[0]) ^ codePoint;
|
||||
} else {
|
||||
hash[1] = ((hash[1] << 5) + hash[1]) ^ codePoint;
|
||||
}
|
||||
return index;
|
||||
});
|
||||
if (this.buffer == null) {
|
||||
return NULL_HASHCODE;
|
||||
}
|
||||
|
||||
return reduceHashCode(hash[0], hash[1]);
|
||||
}
|
||||
if (this.buffer instanceof String) {
|
||||
|
||||
return this.buffer.hashCode();
|
||||
}
|
||||
final int ignored = ((String) this.buffer).codePoints().reduce(0, (index, codePoint) -> {
|
||||
if (index % 2 == 0) {
|
||||
hash[0] = ((hash[0] << 5) + hash[0]) ^ codePoint;
|
||||
} else {
|
||||
hash[1] = ((hash[1] << 5) + hash[1]) ^ codePoint;
|
||||
}
|
||||
return index;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the length of this character sequence. The length is the number
|
||||
* of 16-bit {@code char}s in the sequence.
|
||||
*
|
||||
* @return the number of {@code char}s in this sequence
|
||||
*
|
||||
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}
|
||||
*/
|
||||
@Override
|
||||
public int length() {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.length();
|
||||
}
|
||||
return reduceHashCode(hash[0], hash[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code CharSequence} that is a subsequence of this sequence
|
||||
* <p>
|
||||
* The subsequence starts with the {@code char} value at the specified index and ends with the{@code char} value at
|
||||
* index {@code end - 1}. The length (in {@code char}s) of the returned sequence is {@code end - start}, so if
|
||||
* {@code start == end}, an empty sequence is returned.
|
||||
*
|
||||
* @param start the start index, inclusive
|
||||
* @param end the end index, exclusive
|
||||
* @return the specified subsequence
|
||||
* @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than
|
||||
* {@link UtfAnyString#length()}, or {@code start} is greater than {@code
|
||||
* end}.
|
||||
* @throws UnsupportedOperationException if string is {@code null}
|
||||
*/
|
||||
@Override
|
||||
@Nonnull
|
||||
public CharSequence subSequence(final int start, final int end) {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.subSequence(start, end);
|
||||
}
|
||||
return this.buffer.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
return String.valueOf(this.buffer);
|
||||
}
|
||||
/**
|
||||
* Returns the length of this character sequence. The length is the number
|
||||
* of 16-bit {@code char}s in the sequence.
|
||||
*
|
||||
* @return the number of {@code char}s in this sequence
|
||||
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}
|
||||
*/
|
||||
@Override
|
||||
public int length() {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.length();
|
||||
}
|
||||
|
||||
public String toUtf16() {
|
||||
if (null == this.buffer) {
|
||||
return null;
|
||||
}
|
||||
return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString();
|
||||
}
|
||||
/**
|
||||
* Returns a {@code CharSequence} that is a subsequence of this sequence
|
||||
* <p>
|
||||
* The subsequence starts with the {@code char} value at the specified index and ends with the{@code char} value at
|
||||
* index {@code end - 1}. The length (in {@code char}s) of the returned sequence is {@code end - start}, so if
|
||||
* {@code start == end}, an empty sequence is returned.
|
||||
*
|
||||
* @param start the start index, inclusive
|
||||
* @param end the end index, exclusive
|
||||
* @return the specified subsequence
|
||||
* @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than
|
||||
* {@link UtfAnyString#length()}, or {@code start} is greater than {@code
|
||||
* end}.
|
||||
* @throws UnsupportedOperationException if string is {@code null}
|
||||
*/
|
||||
@Override
|
||||
@Nonnull
|
||||
public CharSequence subSequence(final int start, final int end) {
|
||||
if (this.buffer == null) {
|
||||
throw new UnsupportedOperationException("String is null");
|
||||
}
|
||||
return this.buffer.subSequence(start, end);
|
||||
}
|
||||
|
||||
public Utf8String toUtf8() {
|
||||
if (null == this.buffer) {
|
||||
return null;
|
||||
}
|
||||
return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer;
|
||||
}
|
||||
@Override
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
return String.valueOf(this.buffer);
|
||||
}
|
||||
|
||||
private static int reduceHashCode(final long h1, final long h2) {
|
||||
return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue();
|
||||
}
|
||||
public String toUtf16() {
|
||||
if (null == this.buffer) {
|
||||
return null;
|
||||
}
|
||||
return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString();
|
||||
}
|
||||
|
||||
public Utf8String toUtf8() {
|
||||
if (null == this.buffer) {
|
||||
return null;
|
||||
}
|
||||
return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer;
|
||||
}
|
||||
|
||||
private static int reduceHashCode(final long h1, final long h2) {
|
||||
return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ import javax.annotation.Nonnull;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
public final class LayoutBinary extends LayoutTypePrimitive<ByteBuf> {
|
||||
// implements
|
||||
// LayoutListWritable<Byte>,
|
||||
// LayoutListReadable<Byte>,
|
||||
@@ -41,7 +41,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
@Nonnull final RowBuffer buffer,
|
||||
@Nonnull final RowCursor scope,
|
||||
@Nonnull final LayoutColumn column,
|
||||
@Nonnull final Out<byte[]> value) {
|
||||
@Nonnull final Out<ByteBuf> value) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(scope, "expected non-null scope");
|
||||
@@ -56,14 +56,14 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
return Result.NOT_FOUND;
|
||||
}
|
||||
|
||||
value.set(ByteBufUtil.getBytes(buffer.readFixedBinary(scope.start() + column.offset(), column.size())));
|
||||
value.set(buffer.readFixedBinary(scope.start() + column.offset(), column.size()));
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Result readSparse(
|
||||
@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull final Out<byte[]> value) {
|
||||
@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull final Out<ByteBuf> value) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(edit, "expected non-null edit");
|
||||
@@ -76,7 +76,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
return result;
|
||||
}
|
||||
|
||||
value.set(ByteBufUtil.getBytes(buffer.readSparseBinary(edit)));
|
||||
value.set(buffer.readSparseBinary(edit));
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
@Nonnull RowBuffer buffer,
|
||||
@Nonnull RowCursor scope,
|
||||
@Nonnull LayoutColumn column,
|
||||
@Nonnull Out<byte[]> value) {
|
||||
@Nonnull Out<ByteBuf> value) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(scope, "expected non-null scope");
|
||||
@@ -101,7 +101,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
}
|
||||
|
||||
final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
|
||||
value.set(ByteBufUtil.getBytes(buffer.readVariableBinary(valueOffset)));
|
||||
value.set(buffer.readVariableBinary(valueOffset));
|
||||
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
@Nonnull RowBuffer buffer,
|
||||
@Nonnull RowCursor scope,
|
||||
@Nonnull LayoutColumn column,
|
||||
@Nonnull byte[] value) {
|
||||
@Nonnull ByteBuf value) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(scope, "expected non-null scope");
|
||||
@@ -121,23 +121,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
|
||||
checkArgument(scope.scopeType() instanceof LayoutUDT);
|
||||
checkArgument(column.size() >= 0);
|
||||
checkArgument(value.length == column.size());
|
||||
|
||||
if (scope.immutable()) {
|
||||
return Result.INSUFFICIENT_PERMISSIONS;
|
||||
}
|
||||
|
||||
final ByteBuf valueBuffer = Unpooled.wrappedBuffer(value).asReadOnly();
|
||||
final int valueOffset = scope.start() + column.offset();
|
||||
buffer.setBit(scope.start(), column.nullBit());
|
||||
|
||||
buffer.writeFixedBinary(valueOffset, valueBuffer, column.size());
|
||||
buffer.writeFixedBinary(valueOffset, value, column.size());
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull byte[] value) {
|
||||
public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull ByteBuf value) {
|
||||
return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT);
|
||||
}
|
||||
|
||||
@@ -146,16 +144,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
public Result writeSparse(
|
||||
@Nonnull RowBuffer buffer,
|
||||
@Nonnull RowCursor edit,
|
||||
@Nonnull byte[] value,
|
||||
@Nonnull ByteBuf value,
|
||||
@Nonnull UpdateOptions options) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(edit, "expected non-null edit");
|
||||
checkNotNull(value, "expected non-null value");
|
||||
checkNotNull(options, "expected non-null options");
|
||||
|
||||
Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options);
|
||||
|
||||
if (result != Result.SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
buffer.writeSparseBinary(edit, Unpooled.wrappedBuffer(value).asReadOnly(), options);
|
||||
buffer.writeSparseBinary(edit, value, options);
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -165,7 +168,12 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
@Nonnull RowBuffer buffer,
|
||||
@Nonnull RowCursor scope,
|
||||
@Nonnull LayoutColumn column,
|
||||
@Nonnull byte[] value) {
|
||||
@Nonnull ByteBuf value) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
checkNotNull(scope, "expected non-null scope");
|
||||
checkNotNull(column, "expected non-null column");
|
||||
checkNotNull(value, "expected non-null value");
|
||||
|
||||
checkArgument(scope.scopeType() instanceof LayoutUDT);
|
||||
|
||||
@@ -173,16 +181,15 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
||||
return Result.INSUFFICIENT_PERMISSIONS;
|
||||
}
|
||||
|
||||
if ((column.size() > 0) && (value.length > column.size())) {
|
||||
if ((column.size() > 0) && (value.readableBytes() > column.size())) {
|
||||
return Result.TOO_BIG;
|
||||
}
|
||||
|
||||
final boolean exists = buffer.readBit(scope.start(), column.nullBit());
|
||||
final ByteBuf valueBuffer = Unpooled.wrappedBuffer(value).asReadOnly();
|
||||
final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
|
||||
final Out<Integer> shift = new Out<>();
|
||||
|
||||
buffer.writeVariableBinary(valueOffset, valueBuffer, exists, shift);
|
||||
buffer.writeVariableBinary(valueOffset, value, exists, shift);
|
||||
buffer.setBit(scope.start(), column.nullBit());
|
||||
scope.metaOffset(scope.metaOffset() + shift.get());
|
||||
scope.valueOffset(scope.valueOffset() + shift.get());
|
||||
|
||||
@@ -50,7 +50,7 @@ public final class LayoutTypedTuple extends LayoutIndexedScope {
|
||||
@Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out<Integer> lengthInBytes) {
|
||||
|
||||
checkNotNull(buffer, "expected non-null buffer");
|
||||
lengthInBytes
|
||||
checkNotNull(lengthInBytes, "expected non-null lengthInBytes");
|
||||
checkArgument(offset >= 0, "expected non-negative offset, not %s", offset);
|
||||
|
||||
final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes);
|
||||
|
||||
@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public abstract class LayoutUniqueScope extends LayoutIndexedScope {
|
||||
public abstract class LayoutUniqueScope extends LayoutIndexedScope implements ILayoutType {
|
||||
|
||||
protected LayoutUniqueScope(LayoutCode code, boolean immutable, boolean isSizedScope, boolean isTypedScope) {
|
||||
super(code, immutable, isSizedScope, false, true, isTypedScope);
|
||||
|
||||
@@ -14,7 +14,8 @@ import javax.annotation.Nonnull;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class LayoutUtf8 extends LayoutTypePrimitive<String> implements LayoutUtf8Readable, LayoutUtf8Writable {
|
||||
public final class LayoutUtf8 extends LayoutTypePrimitive<String>
|
||||
implements LayoutUtf8Readable, LayoutUtf8Writable {
|
||||
|
||||
public LayoutUtf8() {
|
||||
super(LayoutCode.UTF_8, 0);
|
||||
|
||||
@@ -15,199 +15,199 @@ import static com.google.common.base.Strings.lenientFormat;
|
||||
|
||||
public final class SchemaHash {
|
||||
|
||||
/**
|
||||
* Computes the logical hash for a logical schema.
|
||||
*
|
||||
* @param namespace The namespace within which <paramref name="schema" /> is defined.
|
||||
* @param schema The logical schema to compute the hash of.
|
||||
* @param seed The seed to initialized the hash function.
|
||||
* @return The logical 128-bit hash as a two-tuple (low, high).
|
||||
*/
|
||||
public static HashCode128 computeHash(Namespace namespace, Schema schema, HashCode128 seed) {
|
||||
HashCode128 hash = seed;
|
||||
/**
|
||||
* Computes the logical hash for a logical schema.
|
||||
*
|
||||
* @param namespace The namespace within which <paramref name="schema" /> is defined.
|
||||
* @param schema The logical schema to compute the hash of.
|
||||
* @param seed The seed to initialized the hash function.
|
||||
* @return The logical 128-bit hash as a two-tuple (low, high).
|
||||
*/
|
||||
public static HashCode128 computeHash(Namespace namespace, Schema schema, HashCode128 seed) {
|
||||
HashCode128 hash = seed;
|
||||
|
||||
hash = Murmur3Hash.Hash128(schema.schemaId().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(schema.type().value(), hash);
|
||||
hash = SchemaHash.computeHash(namespace, schema.options(), hash);
|
||||
hash = Murmur3Hash.Hash128(schema.schemaId().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(schema.type().value(), hash);
|
||||
hash = SchemaHash.computeHash(namespace, schema.options(), hash);
|
||||
|
||||
if (schema.partitionKeys() != null) {
|
||||
for (PartitionKey partitionKey : schema.partitionKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, partitionKey, hash);
|
||||
}
|
||||
}
|
||||
if (schema.partitionKeys() != null) {
|
||||
for (PartitionKey partitionKey : schema.partitionKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, partitionKey, hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.primarySortKeys() != null) {
|
||||
for (PrimarySortKey p : schema.primarySortKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
if (schema.primarySortKeys() != null) {
|
||||
for (PrimarySortKey p : schema.primarySortKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.staticKeys() != null) {
|
||||
for (StaticKey p : schema.staticKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
if (schema.staticKeys() != null) {
|
||||
for (StaticKey p : schema.staticKeys()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.properties() != null) {
|
||||
for (Property p : schema.properties()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
if (schema.properties() != null) {
|
||||
for (Property p : schema.properties()) {
|
||||
hash = SchemaHash.computeHash(namespace, p, hash);
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace namespace, SchemaOptions options, HashCode128 seed) {
|
||||
private static HashCode128 computeHash(Namespace namespace, SchemaOptions options, HashCode128 seed) {
|
||||
|
||||
HashCode128 hash = seed;
|
||||
HashCode128 hash = seed;
|
||||
|
||||
hash = Murmur3Hash.Hash128(options != null && options.disallowUnschematized(), hash);
|
||||
hash = Murmur3Hash.Hash128(options != null && options.enablePropertyLevelTimestamp(), hash);
|
||||
hash = Murmur3Hash.Hash128(options != null && options.disableSystemPrefix(), hash);
|
||||
hash = Murmur3Hash.Hash128(options != null && options.disallowUnschematized(), hash);
|
||||
hash = Murmur3Hash.Hash128(options != null && options.enablePropertyLevelTimestamp(), hash);
|
||||
hash = Murmur3Hash.Hash128(options != null && options.disableSystemPrefix(), hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace ns, Property p, HashCode128 seed) {
|
||||
private static HashCode128 computeHash(Namespace ns, Property p, HashCode128 seed) {
|
||||
|
||||
HashCode128 hash = seed;
|
||||
HashCode128 hash = seed;
|
||||
|
||||
hash = Murmur3Hash.Hash128(p.path(), hash);
|
||||
hash = SchemaHash.computeHash(ns, p.propertyType(), hash);
|
||||
hash = Murmur3Hash.Hash128(p.path(), hash);
|
||||
hash = SchemaHash.computeHash(ns, p.propertyType(), hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace namespace, PropertyType p, HashCode128 seed) {
|
||||
private static HashCode128 computeHash(Namespace namespace, PropertyType p, HashCode128 seed) {
|
||||
|
||||
HashCode128 hash = seed;
|
||||
HashCode128 hash = seed;
|
||||
|
||||
hash = Murmur3Hash.Hash128(p.type().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(p.nullable(), hash);
|
||||
hash = Murmur3Hash.Hash128(p.type().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(p.nullable(), hash);
|
||||
|
||||
if (p.apiType() != null) {
|
||||
hash = Murmur3Hash.Hash128(p.apiType(), hash);
|
||||
}
|
||||
if (p.apiType() != null) {
|
||||
hash = Murmur3Hash.Hash128(p.apiType(), hash);
|
||||
}
|
||||
|
||||
if (p instanceof PrimitivePropertyType) {
|
||||
if (p instanceof PrimitivePropertyType) {
|
||||
|
||||
PrimitivePropertyType pp = (PrimitivePropertyType) p;
|
||||
PrimitivePropertyType pp = (PrimitivePropertyType) p;
|
||||
|
||||
hash = Murmur3Hash.Hash128(pp.storage().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(pp.length(), hash);
|
||||
hash = Murmur3Hash.Hash128(pp.storage().value(), hash);
|
||||
hash = Murmur3Hash.Hash128(pp.length(), hash);
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
checkState(p instanceof ScopePropertyType);
|
||||
ScopePropertyType pp = (ScopePropertyType) p;
|
||||
hash = Murmur3Hash.Hash128(pp.immutable(), hash);
|
||||
checkState(p instanceof ScopePropertyType);
|
||||
ScopePropertyType pp = (ScopePropertyType) p;
|
||||
hash = Murmur3Hash.Hash128(pp.immutable(), hash);
|
||||
|
||||
if (p instanceof ArrayPropertyType) {
|
||||
ArrayPropertyType spp = (ArrayPropertyType) p;
|
||||
if (spp.items() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
if (p instanceof ArrayPropertyType) {
|
||||
ArrayPropertyType spp = (ArrayPropertyType) p;
|
||||
if (spp.items() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof ObjectPropertyType) {
|
||||
ObjectPropertyType spp = (ObjectPropertyType) p;
|
||||
if (spp.properties() != null) {
|
||||
for (Property opp : spp.properties()) {
|
||||
hash = SchemaHash.computeHash(namespace, opp, hash);
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
if (p instanceof ObjectPropertyType) {
|
||||
ObjectPropertyType spp = (ObjectPropertyType) p;
|
||||
if (spp.properties() != null) {
|
||||
for (Property opp : spp.properties()) {
|
||||
hash = SchemaHash.computeHash(namespace, opp, hash);
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof MapPropertyType) {
|
||||
if (p instanceof MapPropertyType) {
|
||||
|
||||
MapPropertyType spp = (MapPropertyType) p;
|
||||
MapPropertyType spp = (MapPropertyType) p;
|
||||
|
||||
if (spp.keys() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.keys(), hash);
|
||||
}
|
||||
if (spp.keys() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.keys(), hash);
|
||||
}
|
||||
|
||||
if (spp.values() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.values(), hash);
|
||||
}
|
||||
if (spp.values() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.values(), hash);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof SetPropertyType) {
|
||||
if (p instanceof SetPropertyType) {
|
||||
|
||||
SetPropertyType spp = (SetPropertyType) p;
|
||||
SetPropertyType spp = (SetPropertyType) p;
|
||||
|
||||
if (spp.items() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
|
||||
}
|
||||
if (spp.items() != null) {
|
||||
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof TaggedPropertyType) {
|
||||
if (p instanceof TaggedPropertyType) {
|
||||
|
||||
TaggedPropertyType spp = (TaggedPropertyType) p;
|
||||
TaggedPropertyType spp = (TaggedPropertyType) p;
|
||||
|
||||
if (spp.items() != null) {
|
||||
for (PropertyType pt : spp.items()) {
|
||||
hash = SchemaHash.computeHash(namespace, pt, hash);
|
||||
}
|
||||
}
|
||||
if (spp.items() != null) {
|
||||
for (PropertyType pt : spp.items()) {
|
||||
hash = SchemaHash.computeHash(namespace, pt, hash);
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof TuplePropertyType) {
|
||||
if (p instanceof TuplePropertyType) {
|
||||
|
||||
TuplePropertyType spp = (TuplePropertyType) p;
|
||||
TuplePropertyType spp = (TuplePropertyType) p;
|
||||
|
||||
if (spp.items() != null) {
|
||||
for (PropertyType pt : spp.items()) {
|
||||
hash = SchemaHash.computeHash(namespace, pt, hash);
|
||||
}
|
||||
}
|
||||
if (spp.items() != null) {
|
||||
for (PropertyType pt : spp.items()) {
|
||||
hash = SchemaHash.computeHash(namespace, pt, hash);
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
if (p instanceof UdtPropertyType) {
|
||||
if (p instanceof UdtPropertyType) {
|
||||
|
||||
Stream<Schema> schemaStream = namespace.schemas().stream();
|
||||
UdtPropertyType spp = (UdtPropertyType) p;
|
||||
Optional<Schema> udtSchema;
|
||||
Stream<Schema> schemaStream = namespace.schemas().stream();
|
||||
UdtPropertyType spp = (UdtPropertyType) p;
|
||||
Optional<Schema> udtSchema;
|
||||
|
||||
if (spp.schemaId() == SchemaId.INVALID) {
|
||||
udtSchema = schemaStream.filter(schema -> schema.name().equals(spp.name())).findFirst();
|
||||
} else {
|
||||
udtSchema = schemaStream.filter(schema -> schema.schemaId().equals(spp.schemaId())).findFirst();
|
||||
udtSchema.ifPresent(schema -> checkState(schema.name().equals(spp.name()),
|
||||
"Ambiguous schema reference: '%s:%s'", spp.name(), spp.schemaId()));
|
||||
}
|
||||
if (spp.schemaId() == SchemaId.INVALID) {
|
||||
udtSchema = schemaStream.filter(schema -> schema.name().equals(spp.name())).findFirst();
|
||||
} else {
|
||||
udtSchema = schemaStream.filter(schema -> schema.schemaId().equals(spp.schemaId())).findFirst();
|
||||
udtSchema.ifPresent(schema -> checkState(schema.name().equals(spp.name()),
|
||||
"Ambiguous schema reference: '%s:%s'", spp.name(), spp.schemaId()));
|
||||
}
|
||||
|
||||
checkState(udtSchema.isPresent(), "Cannot resolve schema reference '{0}:{1}'", spp.name(), spp.schemaId());
|
||||
return SchemaHash.computeHash(namespace, udtSchema.get(), hash);
|
||||
}
|
||||
checkState(udtSchema.isPresent(), "Cannot resolve schema reference '{0}:{1}'", spp.name(), spp.schemaId());
|
||||
return SchemaHash.computeHash(namespace, udtSchema.get(), hash);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(lenientFormat("unrecognized property type: %s", p.getClass()));
|
||||
}
|
||||
throw new IllegalStateException(lenientFormat("unrecognized property type: %s", p.getClass()));
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace namespace, PartitionKey key, HashCode128 seed) {
|
||||
return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed);
|
||||
}
|
||||
private static HashCode128 computeHash(Namespace namespace, PartitionKey key, HashCode128 seed) {
|
||||
return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed);
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace namespace, PrimarySortKey key, HashCode128 seed) {
|
||||
HashCode128 hash = seed;
|
||||
if (key != null) {
|
||||
hash = Murmur3Hash.Hash128(key.path(), hash);
|
||||
hash = Murmur3Hash.Hash128(key.direction().value(), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
private static HashCode128 computeHash(Namespace namespace, PrimarySortKey key, HashCode128 seed) {
|
||||
HashCode128 hash = seed;
|
||||
if (key != null) {
|
||||
hash = Murmur3Hash.Hash128(key.path(), hash);
|
||||
hash = Murmur3Hash.Hash128(key.direction().value(), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static HashCode128 computeHash(Namespace ns, StaticKey key, HashCode128 seed) {
|
||||
return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed);
|
||||
}
|
||||
private static HashCode128 computeHash(Namespace ns, StaticKey key, HashCode128 seed) {
|
||||
return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ package tangible;
|
||||
|
||||
public final class StringHelper {
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'IndexOfAny' (1 parameter version).
|
||||
// This method replaces the .NET string method 'IndexOfAny' (1 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int indexOfAny(String string, char[] anyOf) {
|
||||
int lowestIndex = -1;
|
||||
@@ -26,7 +26,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'IndexOfAny' (2 parameter version).
|
||||
// This method replaces the .NET string method 'IndexOfAny' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int indexOfAny(String string, char[] anyOf, int startIndex) {
|
||||
int indexInSubstring = indexOfAny(string.substring(startIndex), anyOf);
|
||||
@@ -38,7 +38,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'IndexOfAny' (3 parameter version).
|
||||
// This method replaces the .NET string method 'IndexOfAny' (3 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int indexOfAny(String string, char[] anyOf, int startIndex, int count) {
|
||||
int endIndex = startIndex + count;
|
||||
@@ -51,14 +51,14 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET static string method 'IsNullOrEmpty'.
|
||||
// This method replaces the .NET static string method 'IsNullOrEmpty'.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static boolean isNullOrEmpty(String string) {
|
||||
return string == null || string.length() == 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET static string method 'IsNullOrWhiteSpace'.
|
||||
// This method replaces the .NET static string method 'IsNullOrWhiteSpace'.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static boolean isNullOrWhiteSpace(String string) {
|
||||
if (string == null) {
|
||||
@@ -75,7 +75,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET static string method 'Join' (2 parameter version).
|
||||
// This method replaces the .NET static string method 'Join' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String join(String separator, String[] stringArray) {
|
||||
if (stringArray == null) {
|
||||
@@ -86,7 +86,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET static string method 'Join' (4 parameter version).
|
||||
// This method replaces the .NET static string method 'Join' (4 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String join(String separator, String[] stringArray, int startIndex, int count) {
|
||||
String result = "";
|
||||
@@ -109,7 +109,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'LastIndexOf' (char version).
|
||||
// This method replaces the .NET string method 'LastIndexOf' (char version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int lastIndexOf(String string, char value, int startIndex, int count) {
|
||||
int leftMost = startIndex + 1 - count;
|
||||
@@ -124,7 +124,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'LastIndexOf' (string version).
|
||||
// This method replaces the .NET string method 'LastIndexOf' (string version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int lastIndexOf(String string, String value, int startIndex, int count) {
|
||||
int leftMost = startIndex + 1 - count;
|
||||
@@ -139,7 +139,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (1 parameter version).
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (1 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int lastIndexOfAny(String string, char[] anyOf) {
|
||||
int highestIndex = -1;
|
||||
@@ -158,7 +158,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (2 parameter version).
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int lastIndexOfAny(String string, char[] anyOf, int startIndex) {
|
||||
String substring = string.substring(0, startIndex + 1);
|
||||
@@ -171,7 +171,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (3 parameter version).
|
||||
// This method replaces the .NET string method 'LastIndexOfAny' (3 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static int lastIndexOfAny(String string, char[] anyOf, int startIndex, int count) {
|
||||
int leftMost = startIndex + 1 - count;
|
||||
@@ -186,14 +186,14 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'PadLeft' (1 parameter version).
|
||||
// This method replaces the .NET string method 'PadLeft' (1 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String padLeft(String string, int totalWidth) {
|
||||
return padLeft(string, totalWidth, ' ');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'PadLeft' (2 parameter version).
|
||||
// This method replaces the .NET string method 'PadLeft' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String padLeft(String string, int totalWidth, char paddingChar) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -207,14 +207,14 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'PadRight' (1 parameter version).
|
||||
// This method replaces the .NET string method 'PadRight' (1 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String padRight(String string, int totalWidth) {
|
||||
return padRight(string, totalWidth, ' ');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'PadRight' (2 parameter version).
|
||||
// This method replaces the .NET string method 'PadRight' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String padRight(String string, int totalWidth, char paddingChar) {
|
||||
StringBuilder sb = new StringBuilder(string);
|
||||
@@ -227,21 +227,21 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'Remove' (1 parameter version).
|
||||
// This method replaces the .NET string method 'Remove' (1 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String remove(String string, int start) {
|
||||
return string.substring(0, start);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'Remove' (2 parameter version).
|
||||
// This method replaces the .NET string method 'Remove' (2 parameter version).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String remove(String string, int start, int count) {
|
||||
return string.substring(0, start) + string.substring(start + count);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string constructor which repeats a character.
|
||||
// This method replaces the .NET string constructor which repeats a character.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String repeatChar(char charToRepeat, int count) {
|
||||
String newString = "";
|
||||
@@ -252,9 +252,9 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method is used for string equality comparisons when the option
|
||||
// 'Use helper 'stringsEqual' method to handle null strings' is selected
|
||||
// (The Java String 'equals' method can't be called on a null instance).
|
||||
// This method is used for string equality comparisons when the option
|
||||
// 'Use helper 'stringsEqual' method to handle null strings' is selected
|
||||
// (The Java String 'equals' method can't be called on a null instance).
|
||||
//------------------------------------------------------------------------------------
|
||||
public static boolean stringsEqual(String s1, String s2) {
|
||||
if (s1 == null && s2 == null) {
|
||||
@@ -265,8 +265,8 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'Substring' when 'start' is a method
|
||||
// call or calculated value to ensure that 'start' is obtained just once.
|
||||
// This method replaces the .NET string method 'Substring' when 'start' is a method
|
||||
// call or calculated value to ensure that 'start' is obtained just once.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String substring(String string, int start, int length) {
|
||||
if (length < 0) {
|
||||
@@ -277,14 +277,14 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'Trim' when arguments are used.
|
||||
// This method replaces the .NET string method 'Trim' when arguments are used.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String trim(String string, Character... charsToTrim) {
|
||||
return trimEnd(trimStart(string, charsToTrim), charsToTrim);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'TrimEnd'.
|
||||
// This method replaces the .NET string method 'TrimEnd'.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String trimEnd(String string, Character... charsToTrim) {
|
||||
if (string == null || charsToTrim == null) {
|
||||
@@ -316,7 +316,7 @@ public final class StringHelper {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// This method replaces the .NET string method 'TrimStart'.
|
||||
// This method replaces the .NET string method 'TrimStart'.
|
||||
//------------------------------------------------------------------------------------
|
||||
public static String trimStart(String string, Character... charsToTrim) {
|
||||
if (string == null || charsToTrim == null) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public final class JsonModelRowGenerator {
|
||||
new Reference<RowBuffer>(this.row);
|
||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
||||
// converted by C# to Java Converter:
|
||||
Result tempVar = RowWriter.WriteBuffer(tempReference_row, value, (RowWriter RowWriter writer, TypeArgument typeArg,
|
||||
Result tempVar = RowWriter.writeBuffer(tempReference_row, value, (RowWriter RowWriter writer, TypeArgument typeArg,
|
||||
HashMap<Utf8String, Object> dict) ->
|
||||
{
|
||||
for ((Utf8String propPath,Object propValue) :dict)
|
||||
@@ -118,7 +118,7 @@ public final class JsonModelRowGenerator {
|
||||
//ORIGINAL LINE: case bool x:
|
||||
case
|
||||
boolean x:
|
||||
return writer.get().WriteBoolean(path, x);
|
||||
return writer.get().writeBoolean(path, x);
|
||||
// TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements:
|
||||
//ORIGINAL LINE: case long x:
|
||||
case
|
||||
@@ -155,7 +155,7 @@ public final class JsonModelRowGenerator {
|
||||
case HashMap < Utf8String, Object > x:
|
||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these
|
||||
// are not converted by C# to Java Converter:
|
||||
return writer.get().WriteScope(path, new TypeArgument(LayoutType.Object), x,
|
||||
return writer.get().writeScope(path, new TypeArgument(LayoutType.Object), x,
|
||||
(RowWriter RowWriter writer2, TypeArgument typeArg, HashMap<Utf8String, Object> dict) ->
|
||||
{
|
||||
for ((Utf8String propPath,Object propValue) :dict)
|
||||
@@ -172,7 +172,7 @@ public final class JsonModelRowGenerator {
|
||||
//ORIGINAL LINE: case List<object> x:
|
||||
case ArrayList < Object > x:
|
||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter:
|
||||
return writer.get().WriteScope(path, new TypeArgument(LayoutType.Array), x, (RowWriter RowWriter writer2, TypeArgument typeArg, ArrayList<Object> list) ->
|
||||
return writer.get().writeScope(path, new TypeArgument(LayoutType.Array), x, (RowWriter RowWriter writer2, TypeArgument typeArg, ArrayList<Object> list) ->
|
||||
{
|
||||
for (Object elm : list) {
|
||||
Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter> tempReference_writer2 = new Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter>(writer2);
|
||||
|
||||
@@ -16,7 +16,6 @@ public final class AssertThrowsException {
|
||||
if (input1 == null) {
|
||||
return "(null)";
|
||||
}
|
||||
|
||||
return Assert.ReplaceNullChars(input1);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.azure.data.cosmos.serialization.hybridrow.Result;
|
||||
import com.azure.data.cosmos.serialization.hybridrow.RowBuffer;
|
||||
import com.azure.data.cosmos.serialization.hybridrow.RowCursor;
|
||||
import com.azure.data.cosmos.serialization.hybridrow.RowCursors;
|
||||
import com.azure.data.cosmos.serialization.hybridrow.unit.customerschema.Hotel;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
@@ -25,16 +26,18 @@ import java.util.UUID;
|
||||
// are anonymous.")][DeploymentItem("TestData\\CustomerSchema.json", "TestData")] public sealed class
|
||||
// CustomerExampleUnitTests
|
||||
public final class CustomerExampleUnitTests {
|
||||
private final Hotel hotelExample = new Hotel() {
|
||||
Id ="The-Westin-St-John-Resort-Villas-1187",Name ="The Westin St. John Resort Villas",Phone ="+1 340-693-8000"
|
||||
,Address =new Address
|
||||
|
||||
{
|
||||
private final Hotel hotelExample = new Hotel() {
|
||||
Id = "The-Westin-St-John-Resort-Villas-1187",
|
||||
Name ="The Westin St. John Resort Villas",
|
||||
Phone ="+1 340-693-8000",
|
||||
Address = new Address {
|
||||
Street = "300B Chocolate Hole", City = "Great Cruz Bay", State = "VI", PostalCode = new PostalCode {
|
||||
Zip = 00830, Plus4 = 0001
|
||||
}
|
||||
Zip = 00830, Plus4 = 0001
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private LayoutResolver customerResolver;
|
||||
private Namespace customerSchema;
|
||||
private Layout guestLayout;
|
||||
|
||||
@@ -57,7 +57,7 @@ public final class RowWriterUnitTests {
|
||||
new Reference<RowBuffer>(row);
|
||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
||||
// converted by C# to Java Converter:
|
||||
ResultAssert.IsSuccess(RowWriter.WriteBuffer(tempReference_row, null, (RowWriter RowWriter writer,
|
||||
ResultAssert.IsSuccess(RowWriter.writeBuffer(tempReference_row, null, (RowWriter RowWriter writer,
|
||||
TypeArgument rootTypeArg, Object ignored) ->
|
||||
{
|
||||
ResultAssert.IsSuccess(writer.WriteNull("null"));
|
||||
|
||||
Reference in New Issue
Block a user