mirror of
https://github.com/microsoft/HybridRow.git
synced 2026-06-18 02:07:01 +01: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() {
|
public T get() {
|
||||||
return value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(T 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}
|
* @return {@code true} if there is a value present, otherwise {@code false}
|
||||||
*/
|
*/
|
||||||
public boolean isPresent() {
|
public boolean isPresent() {
|
||||||
return value != null;
|
return this.value != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,12 +66,12 @@ public final class Reference<T> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Objects.equals(value, ((Reference)other).value);
|
return Objects.equals(this.value, ((Reference)other).value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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.deser.std.StdDeserializer;
|
||||||
import com.fasterxml.jackson.databind.node.JsonNodeType;
|
import com.fasterxml.jackson.databind.node.JsonNodeType;
|
||||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
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 com.google.common.base.Utf8;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.ByteBufHolder;
|
import io.netty.buffer.ByteBufHolder;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.util.ByteProcessor;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -27,6 +30,7 @@ import java.util.Optional;
|
|||||||
import java.util.Spliterator;
|
import java.util.Spliterator;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
@@ -40,32 +44,49 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
public final class Utf8String implements ByteBufHolder, CharSequence, Comparable<Utf8String> {
|
public final class Utf8String implements ByteBufHolder, CharSequence, Comparable<Utf8String> {
|
||||||
|
|
||||||
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER, 0);
|
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER);
|
||||||
public static final Utf8String NULL = new Utf8String();
|
public static final Utf8String NULL = new Utf8String(null);
|
||||||
|
|
||||||
private final ByteBuf buffer;
|
private final ByteBuf buffer;
|
||||||
private final int length;
|
private final Supplier<Integer> codePointCount;
|
||||||
|
private final Supplier<Integer> utf16CodeUnitCount;
|
||||||
|
|
||||||
private Utf8String() {
|
private Utf8String(@Nullable final ByteBuf buffer) {
|
||||||
|
|
||||||
|
if (buffer == null) {
|
||||||
this.buffer = null;
|
this.buffer = null;
|
||||||
this.length = -1;
|
this.codePointCount = Suppliers.memoize(() -> -1);
|
||||||
|
this.utf16CodeUnitCount = Suppliers.memoize(() -> -1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Utf8String(@Nonnull final ByteBuf buffer) {
|
if (buffer.writerIndex() == 0) {
|
||||||
this(buffer, decodedLength(buffer));
|
this.buffer = Unpooled.EMPTY_BUFFER;
|
||||||
|
this.codePointCount = Suppliers.memoize(() -> 0);
|
||||||
|
this.utf16CodeUnitCount = Suppliers.memoize(() -> 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Utf8String(@Nonnull final ByteBuf buffer, final int decodedLength) {
|
this.buffer = buffer;
|
||||||
checkNotNull(buffer, "expected non-null buffer");
|
|
||||||
this.buffer = buffer.asReadOnly();
|
this.codePointCount = Suppliers.memoize(() -> {
|
||||||
this.length = decodedLength;
|
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
|
* {@code true} if the length of this instance is zero
|
||||||
*/
|
*/
|
||||||
public final boolean isEmpty() {
|
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
|
* Non-allocating enumeration of each code point in the UTF-8 stream
|
||||||
*/
|
*/
|
||||||
public final IntStream codePoints() {
|
public final IntStream codePoints() {
|
||||||
if (this.length == 0) {
|
if (this.buffer == null || this.buffer.writerIndex() == 0) {
|
||||||
return IntStream.empty();
|
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) {
|
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;
|
int index = 0;
|
||||||
|
|
||||||
for (int codePoint : iterable) {
|
for (int codePoint : iterable) {
|
||||||
@@ -182,16 +203,16 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
/**
|
/**
|
||||||
* Encoded length of this {@link Utf8String}
|
* Encoded length of this {@link Utf8String}
|
||||||
* <p>
|
* <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}
|
* @return encoded length of {@link Utf8String}
|
||||||
*/
|
*/
|
||||||
public final int encodedLength() {
|
public final int encodedLength() {
|
||||||
return this.buffer.writerIndex();
|
return this.buffer == null ? 0 : this.buffer.writerIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean equals(ByteBuf other) {
|
public final boolean equals(ByteBuf other) {
|
||||||
return this.buffer.equals(other);
|
return Objects.equal(this.buffer, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean equals(String other) {
|
public final boolean equals(String other) {
|
||||||
@@ -202,34 +223,26 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final boolean equals(Utf8String other) {
|
public final boolean equals(Utf8String other) {
|
||||||
if (other == null) {
|
if (this == other) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (other == this) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.buffer.equals(other.buffer);
|
if (null == other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equal(this.buffer, other.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other == null) {
|
if (this == other) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (other == this) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (other instanceof ByteBuf) {
|
if (null == other || this.getClass() != other.getClass()) {
|
||||||
return this.equals((ByteBuf)other);
|
|
||||||
}
|
|
||||||
if (other instanceof String) {
|
|
||||||
return this.equals((String)other);
|
|
||||||
}
|
|
||||||
if (other instanceof Utf8String) {
|
|
||||||
return this.equals((Utf8String)other);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Utf8String that = (Utf8String) other;
|
||||||
|
return this.utf16CodeUnitCount == that.utf16CodeUnitCount && Objects.equal(this.buffer, that.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Utf8String} from a {@link ByteBuf} with UTF-8 character validation
|
* Creates a new {@link Utf8String} from a {@link ByteBuf} with UTF-8 character validation
|
||||||
@@ -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>
|
* <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}
|
* @return a new {@link Utf8String}
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@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>
|
* <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() {
|
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
|
* Decreases the reference count by {@code 1}.
|
||||||
* {@code 0}.
|
|
||||||
*
|
*
|
||||||
* @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
|
@Override
|
||||||
public boolean release() {
|
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
|
* Decreases the reference count by the specified {@code decrement}
|
||||||
* count reaches at {@code 0}.
|
|
||||||
*
|
*
|
||||||
* @param decrement
|
* 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
|
*
|
||||||
|
* @param decrement the value to subtract from the reference count.
|
||||||
|
* @return {@code true} if and only if the reference count became {@code 0}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean release(int decrement) {
|
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.
|
* @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>
|
* <p>
|
||||||
* This method returns a retained duplicate unlike {@link #duplicate()}.
|
* This method returns a retained duplicate unlike {@link #duplicate()}.
|
||||||
*
|
*
|
||||||
@@ -343,9 +360,8 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence subSequence(int start, int end) {
|
public CharSequence subSequence(int start, int end) {
|
||||||
checkArgument(start < 0 || end < 0 || start > end || end > this.length, "start: %s, end: %s", start, 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(start, end));
|
||||||
return new Utf8String(this.buffer.slice(), end - start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -394,43 +410,34 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
|
|
||||||
checkState(count == length, "count: %s, length: %s", count, length);
|
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) {
|
private static final class CodePointIterable extends UTF8CodePointGetter implements
|
||||||
|
Iterable<Integer>, Iterator<Integer>, Spliterator.OfInt {
|
||||||
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 int CHARACTERISTICS = Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED;
|
private static final int CHARACTERISTICS = Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED;
|
||||||
|
|
||||||
private final ByteBuf buffer;
|
private final ByteBuf buffer;
|
||||||
private final int length;
|
private final int codePointCount;
|
||||||
private int index;
|
|
||||||
|
|
||||||
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.buffer = buffer;
|
||||||
this.length = length;
|
this.start = 0;
|
||||||
this.index = 0;
|
this.length = buffer.writerIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int characteristics() {
|
public int characteristics() {
|
||||||
return this.length == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
|
return this.codePointCount == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long estimateSize() {
|
public long estimateSize() {
|
||||||
return this.length < 0 ? Long.MAX_VALUE : this.length;
|
return this.codePointCount < 0 ? Long.MAX_VALUE : this.codePointCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -440,7 +447,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return this.index < this.buffer.capacity();
|
return this.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -456,50 +463,10 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
throw new NoSuchElementException();
|
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
|
return this.codePoint();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -563,4 +530,204 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
|
|||||||
generator.writeString(value.toString());
|
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,17 +17,22 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString> {
|
public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString> {
|
||||||
|
|
||||||
private static final UtfAnyString EMPTY = new UtfAnyString("");
|
public static final UtfAnyString EMPTY = new UtfAnyString("");
|
||||||
|
public static final UtfAnyString NULL = new UtfAnyString();
|
||||||
|
|
||||||
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
|
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
|
||||||
|
|
||||||
private CharSequence buffer;
|
private CharSequence buffer;
|
||||||
|
|
||||||
public UtfAnyString(final String string) {
|
public UtfAnyString(final String value) {
|
||||||
this.buffer = string;
|
this.buffer = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UtfAnyString(final Utf8String utf8String) {
|
public UtfAnyString(final Utf8String value) {
|
||||||
this.buffer = utf8String;
|
this.buffer = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UtfAnyString() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private UtfAnyString(final CharSequence sequence) {
|
private UtfAnyString(final CharSequence sequence) {
|
||||||
@@ -63,7 +68,7 @@ public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString
|
|||||||
* sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char}
|
* 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.
|
* 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
|
* @param index the index of the {@code char} value to be returned.
|
||||||
* @return the specified {@code char} value
|
* @return the specified {@code char} value
|
||||||
* @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
|
* @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than
|
||||||
* {@link UtfAnyString#length()}
|
* {@link UtfAnyString#length()}
|
||||||
@@ -79,7 +84,7 @@ public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString
|
|||||||
|
|
||||||
public int compareTo(@Nonnull final String other) {
|
public int compareTo(@Nonnull final String other) {
|
||||||
|
|
||||||
checkNotNull(other);
|
checkNotNull(other, "expected non-null other");
|
||||||
|
|
||||||
if (other == this.buffer) {
|
if (other == this.buffer) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -96,7 +101,7 @@ public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString
|
|||||||
|
|
||||||
public int compareTo(@Nonnull final Utf8String other) {
|
public int compareTo(@Nonnull final Utf8String other) {
|
||||||
|
|
||||||
checkNotNull(other);
|
checkNotNull(other, "expected non-null other");
|
||||||
|
|
||||||
if (other == this.buffer) {
|
if (other == this.buffer) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -114,7 +119,7 @@ public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString
|
|||||||
@Override
|
@Override
|
||||||
public int compareTo(@Nonnull final UtfAnyString other) {
|
public int compareTo(@Nonnull final UtfAnyString other) {
|
||||||
|
|
||||||
checkNotNull(other);
|
checkNotNull(other, "expected non-null other");
|
||||||
|
|
||||||
if (other.buffer == this.buffer) {
|
if (other.buffer == this.buffer) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -229,7 +234,6 @@ public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString
|
|||||||
* of 16-bit {@code char}s in the sequence.
|
* of 16-bit {@code char}s in the sequence.
|
||||||
*
|
*
|
||||||
* @return the number of {@code char}s in this sequence
|
* @return the number of {@code char}s in this sequence
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}
|
* @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+268
-430
File diff suppressed because it is too large
Load Diff
+25
-18
@@ -16,7 +16,7 @@ import javax.annotation.Nonnull;
|
|||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
public final class LayoutBinary extends LayoutTypePrimitive<ByteBuf> {
|
||||||
// implements
|
// implements
|
||||||
// LayoutListWritable<Byte>,
|
// LayoutListWritable<Byte>,
|
||||||
// LayoutListReadable<Byte>,
|
// LayoutListReadable<Byte>,
|
||||||
@@ -41,7 +41,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
@Nonnull final RowBuffer buffer,
|
@Nonnull final RowBuffer buffer,
|
||||||
@Nonnull final RowCursor scope,
|
@Nonnull final RowCursor scope,
|
||||||
@Nonnull final LayoutColumn column,
|
@Nonnull final LayoutColumn column,
|
||||||
@Nonnull final Out<byte[]> value) {
|
@Nonnull final Out<ByteBuf> value) {
|
||||||
|
|
||||||
checkNotNull(buffer, "expected non-null buffer");
|
checkNotNull(buffer, "expected non-null buffer");
|
||||||
checkNotNull(scope, "expected non-null scope");
|
checkNotNull(scope, "expected non-null scope");
|
||||||
@@ -56,14 +56,14 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
return Result.NOT_FOUND;
|
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;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Result readSparse(
|
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(buffer, "expected non-null buffer");
|
||||||
checkNotNull(edit, "expected non-null edit");
|
checkNotNull(edit, "expected non-null edit");
|
||||||
@@ -76,7 +76,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
value.set(ByteBufUtil.getBytes(buffer.readSparseBinary(edit)));
|
value.set(buffer.readSparseBinary(edit));
|
||||||
return Result.SUCCESS;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
@Nonnull RowBuffer buffer,
|
@Nonnull RowBuffer buffer,
|
||||||
@Nonnull RowCursor scope,
|
@Nonnull RowCursor scope,
|
||||||
@Nonnull LayoutColumn column,
|
@Nonnull LayoutColumn column,
|
||||||
@Nonnull Out<byte[]> value) {
|
@Nonnull Out<ByteBuf> value) {
|
||||||
|
|
||||||
checkNotNull(buffer, "expected non-null buffer");
|
checkNotNull(buffer, "expected non-null buffer");
|
||||||
checkNotNull(scope, "expected non-null scope");
|
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());
|
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;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
@Nonnull RowBuffer buffer,
|
@Nonnull RowBuffer buffer,
|
||||||
@Nonnull RowCursor scope,
|
@Nonnull RowCursor scope,
|
||||||
@Nonnull LayoutColumn column,
|
@Nonnull LayoutColumn column,
|
||||||
@Nonnull byte[] value) {
|
@Nonnull ByteBuf value) {
|
||||||
|
|
||||||
checkNotNull(buffer, "expected non-null buffer");
|
checkNotNull(buffer, "expected non-null buffer");
|
||||||
checkNotNull(scope, "expected non-null scope");
|
checkNotNull(scope, "expected non-null scope");
|
||||||
@@ -121,23 +121,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
|
|
||||||
checkArgument(scope.scopeType() instanceof LayoutUDT);
|
checkArgument(scope.scopeType() instanceof LayoutUDT);
|
||||||
checkArgument(column.size() >= 0);
|
checkArgument(column.size() >= 0);
|
||||||
checkArgument(value.length == column.size());
|
|
||||||
|
|
||||||
if (scope.immutable()) {
|
if (scope.immutable()) {
|
||||||
return Result.INSUFFICIENT_PERMISSIONS;
|
return Result.INSUFFICIENT_PERMISSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ByteBuf valueBuffer = Unpooled.wrappedBuffer(value).asReadOnly();
|
|
||||||
final int valueOffset = scope.start() + column.offset();
|
final int valueOffset = scope.start() + column.offset();
|
||||||
buffer.setBit(scope.start(), column.nullBit());
|
buffer.setBit(scope.start(), column.nullBit());
|
||||||
|
|
||||||
buffer.writeFixedBinary(valueOffset, valueBuffer, column.size());
|
buffer.writeFixedBinary(valueOffset, value, column.size());
|
||||||
return Result.SUCCESS;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nonnull
|
@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);
|
return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,16 +144,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
public Result writeSparse(
|
public Result writeSparse(
|
||||||
@Nonnull RowBuffer buffer,
|
@Nonnull RowBuffer buffer,
|
||||||
@Nonnull RowCursor edit,
|
@Nonnull RowCursor edit,
|
||||||
@Nonnull byte[] value,
|
@Nonnull ByteBuf value,
|
||||||
@Nonnull UpdateOptions options) {
|
@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);
|
Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options);
|
||||||
|
|
||||||
if (result != Result.SUCCESS) {
|
if (result != Result.SUCCESS) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.writeSparseBinary(edit, Unpooled.wrappedBuffer(value).asReadOnly(), options);
|
buffer.writeSparseBinary(edit, value, options);
|
||||||
return Result.SUCCESS;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +168,12 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
@Nonnull RowBuffer buffer,
|
@Nonnull RowBuffer buffer,
|
||||||
@Nonnull RowCursor scope,
|
@Nonnull RowCursor scope,
|
||||||
@Nonnull LayoutColumn column,
|
@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);
|
checkArgument(scope.scopeType() instanceof LayoutUDT);
|
||||||
|
|
||||||
@@ -173,16 +181,15 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
|
|||||||
return Result.INSUFFICIENT_PERMISSIONS;
|
return Result.INSUFFICIENT_PERMISSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((column.size() > 0) && (value.length > column.size())) {
|
if ((column.size() > 0) && (value.readableBytes() > column.size())) {
|
||||||
return Result.TOO_BIG;
|
return Result.TOO_BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean exists = buffer.readBit(scope.start(), column.nullBit());
|
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 int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
|
||||||
final Out<Integer> shift = new Out<>();
|
final Out<Integer> shift = new Out<>();
|
||||||
|
|
||||||
buffer.writeVariableBinary(valueOffset, valueBuffer, exists, shift);
|
buffer.writeVariableBinary(valueOffset, value, exists, shift);
|
||||||
buffer.setBit(scope.start(), column.nullBit());
|
buffer.setBit(scope.start(), column.nullBit());
|
||||||
scope.metaOffset(scope.metaOffset() + shift.get());
|
scope.metaOffset(scope.metaOffset() + shift.get());
|
||||||
scope.valueOffset(scope.valueOffset() + shift.get());
|
scope.valueOffset(scope.valueOffset() + shift.get());
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ public final class LayoutTypedTuple extends LayoutIndexedScope {
|
|||||||
@Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out<Integer> lengthInBytes) {
|
@Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out<Integer> lengthInBytes) {
|
||||||
|
|
||||||
checkNotNull(buffer, "expected non-null buffer");
|
checkNotNull(buffer, "expected non-null buffer");
|
||||||
lengthInBytes
|
checkNotNull(lengthInBytes, "expected non-null lengthInBytes");
|
||||||
checkArgument(offset >= 0, "expected non-negative offset, not %s", offset);
|
checkArgument(offset >= 0, "expected non-negative offset, not %s", offset);
|
||||||
|
|
||||||
final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes);
|
final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes);
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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) {
|
protected LayoutUniqueScope(LayoutCode code, boolean immutable, boolean isSizedScope, boolean isTypedScope) {
|
||||||
super(code, immutable, isSizedScope, false, true, isTypedScope);
|
super(code, immutable, isSizedScope, false, true, isTypedScope);
|
||||||
|
|||||||
+2
-1
@@ -14,7 +14,8 @@ import javax.annotation.Nonnull;
|
|||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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() {
|
public LayoutUtf8() {
|
||||||
super(LayoutCode.UTF_8, 0);
|
super(LayoutCode.UTF_8, 0);
|
||||||
|
|||||||
+4
-4
@@ -80,7 +80,7 @@ public final class JsonModelRowGenerator {
|
|||||||
new Reference<RowBuffer>(this.row);
|
new Reference<RowBuffer>(this.row);
|
||||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
||||||
// converted by C# to Java Converter:
|
// 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) ->
|
HashMap<Utf8String, Object> dict) ->
|
||||||
{
|
{
|
||||||
for ((Utf8String propPath,Object propValue) :dict)
|
for ((Utf8String propPath,Object propValue) :dict)
|
||||||
@@ -118,7 +118,7 @@ public final class JsonModelRowGenerator {
|
|||||||
//ORIGINAL LINE: case bool x:
|
//ORIGINAL LINE: case bool x:
|
||||||
case
|
case
|
||||||
boolean x:
|
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:
|
// TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements:
|
||||||
//ORIGINAL LINE: case long x:
|
//ORIGINAL LINE: case long x:
|
||||||
case
|
case
|
||||||
@@ -155,7 +155,7 @@ public final class JsonModelRowGenerator {
|
|||||||
case HashMap < Utf8String, Object > x:
|
case HashMap < Utf8String, Object > x:
|
||||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these
|
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these
|
||||||
// are not converted by C# to Java Converter:
|
// 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) ->
|
(RowWriter RowWriter writer2, TypeArgument typeArg, HashMap<Utf8String, Object> dict) ->
|
||||||
{
|
{
|
||||||
for ((Utf8String propPath,Object propValue) :dict)
|
for ((Utf8String propPath,Object propValue) :dict)
|
||||||
@@ -172,7 +172,7 @@ public final class JsonModelRowGenerator {
|
|||||||
//ORIGINAL LINE: case List<object> x:
|
//ORIGINAL LINE: case List<object> x:
|
||||||
case ArrayList < 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:
|
// 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) {
|
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);
|
Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter> tempReference_writer2 = new Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter>(writer2);
|
||||||
|
|||||||
-1
@@ -16,7 +16,6 @@ public final class AssertThrowsException {
|
|||||||
if (input1 == null) {
|
if (input1 == null) {
|
||||||
return "(null)";
|
return "(null)";
|
||||||
}
|
}
|
||||||
|
|
||||||
return Assert.ReplaceNullChars(input1);
|
return Assert.ReplaceNullChars(input1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -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.RowBuffer;
|
||||||
import com.azure.data.cosmos.serialization.hybridrow.RowCursor;
|
import com.azure.data.cosmos.serialization.hybridrow.RowCursor;
|
||||||
import com.azure.data.cosmos.serialization.hybridrow.RowCursors;
|
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.nio.file.Files;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -25,16 +26,18 @@ import java.util.UUID;
|
|||||||
// are anonymous.")][DeploymentItem("TestData\\CustomerSchema.json", "TestData")] public sealed class
|
// are anonymous.")][DeploymentItem("TestData\\CustomerSchema.json", "TestData")] public sealed class
|
||||||
// CustomerExampleUnitTests
|
// CustomerExampleUnitTests
|
||||||
public final 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 {
|
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 LayoutResolver customerResolver;
|
||||||
private Namespace customerSchema;
|
private Namespace customerSchema;
|
||||||
private Layout guestLayout;
|
private Layout guestLayout;
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ public final class RowWriterUnitTests {
|
|||||||
new Reference<RowBuffer>(row);
|
new Reference<RowBuffer>(row);
|
||||||
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
// TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not
|
||||||
// converted by C# to Java Converter:
|
// 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) ->
|
TypeArgument rootTypeArg, Object ignored) ->
|
||||||
{
|
{
|
||||||
ResultAssert.IsSuccess(writer.WriteNull("null"));
|
ResultAssert.IsSuccess(writer.WriteNull("null"));
|
||||||
|
|||||||
Reference in New Issue
Block a user